summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.BANNER4
-rw-r--r--.github/ISSUE_TEMPLATE/BUG.yml44
-rw-r--r--.github/ISSUE_TEMPLATE/BUG_REPORT.md33
-rw-r--r--.github/ISSUE_TEMPLATE/FEATURE.yml20
-rw-r--r--.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md15
-rw-r--r--.github/ISSUE_TEMPLATE/config.yml4
-rw-r--r--.github/workflows/ci-alpine.yml59
-rw-r--r--.github/workflows/ci-linux.yml11
-rw-r--r--.github/workflows/ci-windows.yml46
-rw-r--r--.gitignore26
-rw-r--r--CMakeLists.txt393
-rwxr-xr-xConfig121
-rw-r--r--README.md14
-rw-r--r--cmake/Anope.cmake513
-rw-r--r--cmake/FindGettext.cmake26
-rw-r--r--cmake/ReadFile.cmake5
-rw-r--r--data/CMakeLists.txt4
-rw-r--r--data/anope.example.conf (renamed from data/example.conf)414
-rw-r--r--data/botserv.example.conf18
-rw-r--r--data/chanserv.example.conf90
-rw-r--r--data/chanstats.example.conf2
-rw-r--r--data/cron.example.sh (renamed from data/example.chk)8
-rw-r--r--data/global.example.conf43
-rw-r--r--data/hostserv.example.conf26
-rw-r--r--data/memoserv.example.conf15
-rw-r--r--data/modules.example.conf231
-rw-r--r--data/nickserv.example.conf260
-rw-r--r--data/operserv.example.conf64
-rw-r--r--data/stats.standalone.example.conf94
-rw-r--r--docs/ASTYLE1
-rw-r--r--docs/BUGS1
-rw-r--r--docs/C++CASTING111
-rw-r--r--docs/CMakeLists.txt6
-rw-r--r--docs/CODING239
-rw-r--r--docs/Changes649
-rw-r--r--docs/Changes.conf333
-rw-r--r--docs/DEFCON8
-rw-r--r--docs/EVENTS34
-rw-r--r--docs/INSTALL26
-rw-r--r--docs/INSTALL.fr28
-rw-r--r--docs/LANGUAGE4
-rw-r--r--docs/MODULES6
-rw-r--r--docs/NEWS6
-rw-r--r--docs/README16
-rw-r--r--docs/REDIS6
-rw-r--r--docs/RPC/RPC (renamed from docs/XMLRPC/XMLRPC)13
-rw-r--r--docs/RPC/jsonrpc.php (renamed from docs/XMLRPC/xmlrpc.php)29
-rw-r--r--docs/TOOLS25
-rw-r--r--docs/WIN32.txt6
-rw-r--r--include/CMakeLists.txt48
-rw-r--r--include/access.h36
-rw-r--r--include/account.h138
-rw-r--r--include/anope.h257
-rw-r--r--include/base.h37
-rw-r--r--include/bots.h25
-rw-r--r--include/channels.h36
-rw-r--r--include/commands.h48
-rw-r--r--include/config.h72
-rw-r--r--include/convert.h132
-rw-r--r--include/defs.h2
-rw-r--r--include/extensible.h104
-rw-r--r--include/hashcomp.h41
-rw-r--r--include/language.h83
-rw-r--r--include/lists.h27
-rw-r--r--include/logger.h41
-rw-r--r--include/mail.h14
-rw-r--r--include/memo.h18
-rw-r--r--include/messages.h139
-rw-r--r--include/modes.h117
-rw-r--r--include/module.h5
-rw-r--r--include/modules.h338
-rw-r--r--include/modules/bs_badwords.h14
-rw-r--r--include/modules/bs_kick.h10
-rw-r--r--include/modules/cs_entrymsg.h17
-rw-r--r--include/modules/cs_log.h17
-rw-r--r--include/modules/cs_mode.h10
-rw-r--r--include/modules/dns.h49
-rw-r--r--include/modules/encryption.h138
-rw-r--r--include/modules/hs_request.h23
-rw-r--r--include/modules/httpd.h62
-rw-r--r--include/modules/info.h49
-rw-r--r--include/modules/ldap.h31
-rw-r--r--include/modules/ns_cert.h27
-rw-r--r--include/modules/os_forbid.h22
-rw-r--r--include/modules/os_ignore.h17
-rw-r--r--include/modules/os_news.h15
-rw-r--r--include/modules/os_oper.h46
-rw-r--r--include/modules/os_session.h41
-rw-r--r--include/modules/pseudoclients/chanserv.h10
-rw-r--r--include/modules/pseudoclients/global.h71
-rw-r--r--include/modules/pseudoclients/memoserv.h10
-rw-r--r--include/modules/pseudoclients/nickserv.h11
-rw-r--r--include/modules/redis.h17
-rw-r--r--include/modules/rpc.h65
-rw-r--r--include/modules/sasl.h32
-rw-r--r--include/modules/set_misc.h7
-rw-r--r--include/modules/sql.h93
-rw-r--r--include/modules/ssl.h7
-rw-r--r--include/modules/suspend.h6
-rw-r--r--include/modules/xmlrpc.h47
-rw-r--r--include/numeric.h35
-rw-r--r--include/opertype.h19
-rw-r--r--include/protocol.h294
-rw-r--r--include/pstdint.h800
-rw-r--r--include/regchannel.h37
-rw-r--r--include/regexpr.h23
-rw-r--r--include/serialize.h109
-rw-r--r--include/servers.h20
-rw-r--r--include/service.h49
-rw-r--r--include/services.h63
-rw-r--r--include/socketengine.h9
-rw-r--r--include/sockets.h137
-rw-r--r--include/sysconf.h.cmake85
-rw-r--r--include/threadengine.h79
-rw-r--r--include/timers.h38
-rw-r--r--include/uplink.h60
-rw-r--r--include/users.h62
-rw-r--r--include/version.cpp22
-rw-r--r--include/xline.h27
-rw-r--r--language/CMakeLists.txt10
-rw-r--r--language/anope.ca_ES.po10057
-rw-r--r--language/anope.de_DE.po6
-rw-r--r--language/anope.el_GR.po6
-rw-r--r--language/anope.en_US.po5346
-rw-r--r--language/anope.fr_FR.po2439
-rw-r--r--language/anope.hu_HU.po9966
-rw-r--r--language/anope.it_IT.po548
-rw-r--r--language/anope.nl_NL.po404
-rw-r--r--language/anope.pl_PL.po798
-rw-r--r--language/anope.pt_PT.po7130
-rw-r--r--language/anope.ru_RU.po10224
-rw-r--r--language/anope.tr_TR.po1210
-rwxr-xr-xlanguage/update.sh2
-rw-r--r--modules/CMakeLists.txt258
-rw-r--r--modules/botserv/botserv.cpp (renamed from modules/pseudoclients/botserv.cpp)70
-rw-r--r--modules/botserv/bs_assign.cpp (renamed from modules/commands/bs_assign.cpp)42
-rw-r--r--modules/botserv/bs_autoassign.cpp (renamed from modules/bs_autoassign.cpp)7
-rw-r--r--modules/botserv/bs_badwords.cpp (renamed from modules/commands/bs_badwords.cpp)89
-rw-r--r--modules/botserv/bs_bot.cpp (renamed from modules/commands/bs_bot.cpp)49
-rw-r--r--modules/botserv/bs_botlist.cpp116
-rw-r--r--modules/botserv/bs_control.cpp (renamed from modules/commands/bs_control.cpp)31
-rw-r--r--modules/botserv/bs_info.cpp (renamed from modules/commands/bs_info.cpp)40
-rw-r--r--modules/botserv/bs_kick.cpp (renamed from modules/commands/bs_kick.cpp)361
-rw-r--r--modules/botserv/bs_set.cpp (renamed from modules/commands/bs_set.cpp)60
-rw-r--r--modules/chanserv/chanserv.cpp (renamed from modules/pseudoclients/chanserv.cpp)107
-rw-r--r--modules/chanserv/cs_access.cpp (renamed from modules/commands/cs_access.cpp)189
-rw-r--r--modules/chanserv/cs_akick.cpp (renamed from modules/commands/cs_akick.cpp)59
-rw-r--r--modules/chanserv/cs_ban.cpp (renamed from modules/commands/cs_ban.cpp)37
-rw-r--r--modules/chanserv/cs_clone.cpp (renamed from modules/commands/cs_clone.cpp)37
-rw-r--r--modules/chanserv/cs_drop.cpp (renamed from modules/commands/cs_drop.cpp)48
-rw-r--r--modules/chanserv/cs_enforce.cpp (renamed from modules/commands/cs_enforce.cpp)77
-rw-r--r--modules/chanserv/cs_entrymsg.cpp (renamed from modules/commands/cs_entrymsg.cpp)86
-rw-r--r--modules/chanserv/cs_fantasy_stats.cpp (renamed from modules/extra/stats/cs_fantasy_stats.cpp)32
-rw-r--r--modules/chanserv/cs_fantasy_top.cpp (renamed from modules/extra/stats/cs_fantasy_top.cpp)44
-rw-r--r--modules/chanserv/cs_flags.cpp (renamed from modules/commands/cs_flags.cpp)114
-rw-r--r--modules/chanserv/cs_getkey.cpp (renamed from modules/commands/cs_getkey.cpp)14
-rw-r--r--modules/chanserv/cs_info.cpp (renamed from modules/commands/cs_info.cpp)20
-rw-r--r--modules/chanserv/cs_invite.cpp (renamed from modules/commands/cs_invite.cpp)14
-rw-r--r--modules/chanserv/cs_kick.cpp (renamed from modules/commands/cs_kick.cpp)20
-rw-r--r--modules/chanserv/cs_list.cpp (renamed from modules/commands/cs_list.cpp)49
-rw-r--r--modules/chanserv/cs_log.cpp (renamed from modules/commands/cs_log.cpp)87
-rw-r--r--modules/chanserv/cs_mode.cpp (renamed from modules/commands/cs_mode.cpp)257
-rw-r--r--modules/chanserv/cs_register.cpp (renamed from modules/commands/cs_register.cpp)20
-rw-r--r--modules/chanserv/cs_seen.cpp (renamed from modules/commands/cs_seen.cpp)97
-rw-r--r--modules/chanserv/cs_set.cpp (renamed from modules/commands/cs_set.cpp)287
-rw-r--r--modules/chanserv/cs_set_misc.cpp (renamed from modules/commands/cs_set_misc.cpp)69
-rw-r--r--modules/chanserv/cs_status.cpp (renamed from modules/commands/cs_status.cpp)18
-rw-r--r--modules/chanserv/cs_statusupdate.cpp58
-rw-r--r--modules/chanserv/cs_suspend.cpp (renamed from modules/commands/cs_suspend.cpp)62
-rw-r--r--modules/chanserv/cs_sync.cpp (renamed from modules/commands/cs_sync.cpp)18
-rw-r--r--modules/chanserv/cs_topic.cpp (renamed from modules/commands/cs_topic.cpp)31
-rw-r--r--modules/chanserv/cs_unban.cpp (renamed from modules/commands/cs_unban.cpp)56
-rw-r--r--modules/chanserv/cs_updown.cpp (renamed from modules/commands/cs_updown.cpp)30
-rw-r--r--modules/chanserv/cs_xop.cpp (renamed from modules/commands/cs_xop.cpp)131
-rw-r--r--modules/chanstats.cpp (renamed from modules/extra/stats/m_chanstats.cpp)155
-rw-r--r--modules/commands/bs_botlist.cpp82
-rw-r--r--modules/commands/gl_global.cpp66
-rw-r--r--modules/commands/ns_access.cpp206
-rw-r--r--modules/commands/ns_drop.cpp86
-rw-r--r--modules/commands/ns_getpass.cpp74
-rw-r--r--modules/commands/ns_set.cpp1350
-rw-r--r--modules/commands/ns_status.cpp87
-rw-r--r--modules/commands/os_oline.cpp78
-rw-r--r--modules/cs_statusupdate.cpp65
-rw-r--r--modules/database/db_atheme.cpp1615
-rw-r--r--modules/database/db_flatfile.cpp134
-rw-r--r--modules/database/db_old.cpp97
-rw-r--r--modules/database/db_redis.cpp233
-rw-r--r--modules/database/db_sql.cpp103
-rw-r--r--modules/database/db_sql_live.cpp72
-rw-r--r--modules/dns.cpp (renamed from modules/m_dns.cpp)188
-rw-r--r--modules/dnsbl.cpp (renamed from modules/m_dnsbl.cpp)46
-rw-r--r--modules/encryption/enc_bcrypt.cpp1008
-rw-r--r--modules/encryption/enc_md5.cpp382
-rw-r--r--modules/encryption/enc_none.cpp55
-rw-r--r--modules/encryption/enc_old.cpp100
-rw-r--r--modules/encryption/enc_sha1.cpp109
-rw-r--r--modules/encryption/enc_sha2.cpp215
-rw-r--r--modules/encryption/enc_sha256.cpp300
-rw-r--r--modules/extra/enc_argon2.cpp210
-rw-r--r--modules/extra/enc_posix.cpp53
-rw-r--r--modules/extra/ldap.cpp (renamed from modules/extra/m_ldap.cpp)176
-rw-r--r--modules/extra/m_regex_pcre.cpp83
-rw-r--r--modules/extra/mysql.cpp (renamed from modules/extra/m_mysql.cpp)353
-rw-r--r--modules/extra/regex_pcre2.cpp (renamed from modules/extra/m_regex_pcre2.cpp)28
-rw-r--r--modules/extra/regex_posix.cpp (renamed from modules/extra/m_regex_posix.cpp)26
-rw-r--r--modules/extra/regex_tre.cpp (renamed from modules/extra/m_regex_tre.cpp)26
-rw-r--r--modules/extra/sqlite.cpp (renamed from modules/extra/m_sqlite.cpp)153
-rw-r--r--modules/extra/ssl_gnutls.cpp (renamed from modules/extra/m_ssl_gnutls.cpp)127
-rw-r--r--modules/extra/ssl_openssl.cpp (renamed from modules/extra/m_ssl_openssl.cpp)111
-rw-r--r--modules/extra/stats/irc2sql/irc2sql.h84
-rw-r--r--modules/fantasy.cpp41
-rw-r--r--modules/global/gl_global.cpp105
-rw-r--r--modules/global/gl_queue.cpp208
-rw-r--r--modules/global/gl_server.cpp112
-rw-r--r--modules/global/global.cpp173
-rw-r--r--modules/greet.cpp (renamed from modules/commands/greet.cpp)41
-rw-r--r--modules/help.cpp (renamed from modules/commands/help.cpp)32
-rw-r--r--modules/helpchan.cpp (renamed from modules/m_helpchan.cpp)7
-rw-r--r--modules/hostserv/hostserv.cpp133
-rw-r--r--modules/hostserv/hs_del.cpp (renamed from modules/commands/hs_del.cpp)39
-rw-r--r--modules/hostserv/hs_group.cpp (renamed from modules/commands/hs_group.cpp)41
-rw-r--r--modules/hostserv/hs_list.cpp (renamed from modules/commands/hs_list.cpp)59
-rw-r--r--modules/hostserv/hs_off.cpp (renamed from modules/commands/hs_off.cpp)22
-rw-r--r--modules/hostserv/hs_on.cpp (renamed from modules/commands/hs_on.cpp)35
-rw-r--r--modules/hostserv/hs_request.cpp (renamed from modules/commands/hs_request.cpp)180
-rw-r--r--modules/hostserv/hs_set.cpp (renamed from modules/commands/hs_set.cpp)62
-rw-r--r--modules/httpd.cpp (renamed from modules/m_httpd.cpp)106
-rw-r--r--modules/irc2sql/CMakeLists.txt (renamed from modules/extra/stats/irc2sql/CMakeLists.txt)0
-rw-r--r--modules/irc2sql/irc2sql.cpp (renamed from modules/extra/stats/irc2sql/irc2sql.cpp)60
-rw-r--r--modules/irc2sql/irc2sql.h88
-rw-r--r--modules/irc2sql/tables.cpp (renamed from modules/extra/stats/irc2sql/tables.cpp)28
-rw-r--r--modules/irc2sql/utils.cpp (renamed from modules/extra/stats/irc2sql/utils.cpp)0
-rw-r--r--modules/ldap_authentication.cpp (renamed from modules/extra/m_ldap_authentication.cpp)70
-rw-r--r--modules/ldap_oper.cpp (renamed from modules/extra/m_ldap_oper.cpp)28
-rw-r--r--modules/m_xmlrpc_main.cpp310
-rw-r--r--modules/memoserv/memoserv.cpp (renamed from modules/pseudoclients/memoserv.cpp)61
-rw-r--r--modules/memoserv/ms_cancel.cpp (renamed from modules/commands/ms_cancel.cpp)14
-rw-r--r--modules/memoserv/ms_check.cpp (renamed from modules/commands/ms_check.cpp)14
-rw-r--r--modules/memoserv/ms_del.cpp (renamed from modules/commands/ms_del.cpp)23
-rw-r--r--modules/memoserv/ms_ignore.cpp (renamed from modules/commands/ms_ignore.cpp)26
-rw-r--r--modules/memoserv/ms_info.cpp (renamed from modules/commands/ms_info.cpp)40
-rw-r--r--modules/memoserv/ms_list.cpp (renamed from modules/commands/ms_list.cpp)29
-rw-r--r--modules/memoserv/ms_read.cpp (renamed from modules/commands/ms_read.cpp)27
-rw-r--r--modules/memoserv/ms_rsend.cpp (renamed from modules/commands/ms_rsend.cpp)22
-rw-r--r--modules/memoserv/ms_send.cpp (renamed from modules/commands/ms_send.cpp)22
-rw-r--r--modules/memoserv/ms_sendall.cpp (renamed from modules/commands/ms_sendall.cpp)18
-rw-r--r--modules/memoserv/ms_set.cpp (renamed from modules/commands/ms_set.cpp)38
-rw-r--r--modules/memoserv/ms_staff.cpp (renamed from modules/commands/ms_staff.cpp)18
-rw-r--r--modules/nickserv/nickserv.cpp (renamed from modules/pseudoclients/nickserv.cpp)261
-rw-r--r--modules/nickserv/ns_ajoin.cpp (renamed from modules/commands/ns_ajoin.cpp)65
-rw-r--r--modules/nickserv/ns_alist.cpp (renamed from modules/commands/ns_alist.cpp)31
-rw-r--r--modules/nickserv/ns_cert.cpp (renamed from modules/commands/ns_cert.cpp)117
-rw-r--r--modules/nickserv/ns_drop.cpp124
-rw-r--r--modules/nickserv/ns_getemail.cpp (renamed from modules/commands/ns_getemail.cpp)32
-rw-r--r--modules/nickserv/ns_group.cpp (renamed from modules/commands/ns_group.cpp)83
-rw-r--r--modules/nickserv/ns_identify.cpp (renamed from modules/commands/ns_identify.cpp)25
-rw-r--r--modules/nickserv/ns_info.cpp (renamed from modules/commands/ns_info.cpp)86
-rw-r--r--modules/nickserv/ns_list.cpp (renamed from modules/commands/ns_list.cpp)58
-rw-r--r--modules/nickserv/ns_logout.cpp (renamed from modules/commands/ns_logout.cpp)16
-rw-r--r--modules/nickserv/ns_maxemail.cpp (renamed from modules/ns_maxemail.cpp)18
-rw-r--r--modules/nickserv/ns_recover.cpp (renamed from modules/commands/ns_recover.cpp)49
-rw-r--r--modules/nickserv/ns_register.cpp (renamed from modules/commands/ns_register.cpp)117
-rw-r--r--modules/nickserv/ns_resetpass.cpp (renamed from modules/commands/ns_resetpass.cpp)20
-rw-r--r--modules/nickserv/ns_set.cpp828
-rw-r--r--modules/nickserv/ns_set_keepmodes.cpp206
-rw-r--r--modules/nickserv/ns_set_kill.cpp189
-rw-r--r--modules/nickserv/ns_set_language.cpp160
-rw-r--r--modules/nickserv/ns_set_message.cpp137
-rw-r--r--modules/nickserv/ns_set_misc.cpp (renamed from modules/commands/ns_set_misc.cpp)52
-rw-r--r--modules/nickserv/ns_suspend.cpp (renamed from modules/commands/ns_suspend.cpp)55
-rw-r--r--modules/nickserv/ns_update.cpp (renamed from modules/commands/ns_update.cpp)14
-rw-r--r--modules/operserv/operserv.cpp (renamed from modules/pseudoclients/operserv.cpp)76
-rw-r--r--modules/operserv/os_akill.cpp (renamed from modules/commands/os_akill.cpp)55
-rw-r--r--modules/operserv/os_chankill.cpp (renamed from modules/commands/os_chankill.cpp)20
-rw-r--r--modules/operserv/os_config.cpp (renamed from modules/commands/os_config.cpp)45
-rw-r--r--modules/operserv/os_defcon.cpp (renamed from modules/commands/os_defcon.cpp)90
-rw-r--r--modules/operserv/os_dns.cpp (renamed from modules/commands/os_dns.cpp)203
-rw-r--r--modules/operserv/os_forbid.cpp (renamed from modules/commands/os_forbid.cpp)112
-rw-r--r--modules/operserv/os_ignore.cpp (renamed from modules/commands/os_ignore.cpp)73
-rw-r--r--modules/operserv/os_info.cpp (renamed from modules/commands/os_info.cpp)82
-rw-r--r--modules/operserv/os_jupe.cpp (renamed from modules/commands/os_jupe.cpp)22
-rw-r--r--modules/operserv/os_kick.cpp (renamed from modules/commands/os_kick.cpp)14
-rw-r--r--modules/operserv/os_kill.cpp (renamed from modules/commands/os_kill.cpp)14
-rw-r--r--modules/operserv/os_list.cpp (renamed from modules/commands/os_list.cpp)87
-rw-r--r--modules/operserv/os_login.cpp (renamed from modules/commands/os_login.cpp)29
-rw-r--r--modules/operserv/os_logsearch.cpp (renamed from modules/commands/os_logsearch.cpp)56
-rw-r--r--modules/operserv/os_mode.cpp (renamed from modules/commands/os_mode.cpp)34
-rw-r--r--modules/operserv/os_modinfo.cpp (renamed from modules/commands/os_modinfo.cpp)39
-rw-r--r--modules/operserv/os_module.cpp (renamed from modules/commands/os_module.cpp)32
-rw-r--r--modules/operserv/os_news.cpp (renamed from modules/commands/os_news.cpp)122
-rw-r--r--modules/operserv/os_noop.cpp (renamed from modules/commands/os_noop.cpp)25
-rw-r--r--modules/operserv/os_oper.cpp (renamed from modules/commands/os_oper.cpp)94
-rw-r--r--modules/operserv/os_reload.cpp (renamed from modules/commands/os_reload.cpp)22
-rw-r--r--modules/operserv/os_session.cpp (renamed from modules/commands/os_session.cpp)139
-rw-r--r--modules/operserv/os_set.cpp (renamed from modules/commands/os_set.cpp)34
-rw-r--r--modules/operserv/os_shutdown.cpp (renamed from modules/commands/os_shutdown.cpp)78
-rw-r--r--modules/operserv/os_stats.cpp (renamed from modules/commands/os_stats.cpp)132
-rw-r--r--modules/operserv/os_svs.cpp (renamed from modules/commands/os_svs.cpp)36
-rw-r--r--modules/operserv/os_sxline.cpp (renamed from modules/commands/os_sxline.cpp)108
-rw-r--r--modules/operserv/os_update.cpp (renamed from modules/commands/os_update.cpp)18
-rw-r--r--modules/protocol/bahamut.cpp268
-rw-r--r--modules/protocol/hybrid.cpp377
-rw-r--r--modules/protocol/inspircd.cpp2592
-rw-r--r--modules/protocol/inspircd12.cpp1408
-rw-r--r--modules/protocol/inspircd20.cpp1106
-rw-r--r--modules/protocol/inspircd3.cpp2031
-rw-r--r--modules/protocol/ngircd.cpp223
-rw-r--r--modules/protocol/plexus.cpp186
-rw-r--r--modules/protocol/ratbox.cpp144
-rw-r--r--modules/protocol/solanum.cpp (renamed from modules/protocol/charybdis.cpp)276
-rw-r--r--modules/protocol/unreal.cpp1340
-rw-r--r--modules/protocol/unrealircd.cpp (renamed from modules/protocol/unreal4.cpp)998
-rw-r--r--modules/proxyscan.cpp (renamed from modules/m_proxyscan.cpp)113
-rw-r--r--modules/pseudoclients/global.cpp100
-rw-r--r--modules/pseudoclients/hostserv.cpp130
-rw-r--r--modules/redis.cpp (renamed from modules/m_redis.cpp)158
-rw-r--r--modules/regex_stdlib.cpp107
-rw-r--r--modules/rewrite.cpp (renamed from modules/m_rewrite.cpp)73
-rw-r--r--modules/rpc/jsonrpc.cpp209
-rw-r--r--modules/rpc/rpc_main.cpp309
-rw-r--r--modules/rpc/xmlrpc.cpp (renamed from modules/m_xmlrpc.cpp)115
-rw-r--r--modules/sasl.cpp (renamed from modules/m_sasl.cpp)208
-rw-r--r--modules/sql_authentication.cpp (renamed from modules/extra/m_sql_authentication.cpp)30
-rw-r--r--modules/sql_log.cpp (renamed from modules/extra/m_sql_log.cpp)12
-rw-r--r--modules/sql_oper.cpp (renamed from modules/extra/m_sql_oper.cpp)43
-rw-r--r--modules/third/language/CMakeLists.txt10
-rw-r--r--modules/webcpanel/CMakeLists.txt4
-rw-r--r--modules/webcpanel/pages/chanserv/access.cpp13
-rw-r--r--modules/webcpanel/pages/chanserv/access.h26
-rw-r--r--modules/webcpanel/pages/chanserv/akick.cpp11
-rw-r--r--modules/webcpanel/pages/chanserv/akick.h26
-rw-r--r--modules/webcpanel/pages/chanserv/chanserv.h72
-rw-r--r--modules/webcpanel/pages/chanserv/drop.cpp4
-rw-r--r--modules/webcpanel/pages/chanserv/drop.h25
-rw-r--r--modules/webcpanel/pages/chanserv/info.cpp1
-rw-r--r--modules/webcpanel/pages/chanserv/info.h24
-rw-r--r--modules/webcpanel/pages/chanserv/modes.cpp18
-rw-r--r--modules/webcpanel/pages/chanserv/modes.h26
-rw-r--r--modules/webcpanel/pages/chanserv/set.cpp14
-rw-r--r--modules/webcpanel/pages/chanserv/set.h26
-rw-r--r--modules/webcpanel/pages/chanserv/utils.cpp4
-rw-r--r--modules/webcpanel/pages/chanserv/utils.h18
-rw-r--r--modules/webcpanel/pages/confirm.h9
-rw-r--r--modules/webcpanel/pages/hostserv/hostserv.h (renamed from modules/webcpanel/pages/hostserv/request.h)19
-rw-r--r--modules/webcpanel/pages/hostserv/request.cpp9
-rw-r--r--modules/webcpanel/pages/index.cpp23
-rw-r--r--modules/webcpanel/pages/index.h15
-rw-r--r--modules/webcpanel/pages/logout.h9
-rw-r--r--modules/webcpanel/pages/memoserv/memos.cpp16
-rw-r--r--modules/webcpanel/pages/memoserv/memoserv.h (renamed from modules/webcpanel/pages/memoserv/memos.h)19
-rw-r--r--modules/webcpanel/pages/nickserv/access.cpp39
-rw-r--r--modules/webcpanel/pages/nickserv/access.h24
-rw-r--r--modules/webcpanel/pages/nickserv/alist.cpp8
-rw-r--r--modules/webcpanel/pages/nickserv/alist.h24
-rw-r--r--modules/webcpanel/pages/nickserv/cert.cpp4
-rw-r--r--modules/webcpanel/pages/nickserv/cert.h24
-rw-r--r--modules/webcpanel/pages/nickserv/confirm.h24
-rw-r--r--modules/webcpanel/pages/nickserv/info.cpp55
-rw-r--r--modules/webcpanel/pages/nickserv/info.h24
-rw-r--r--modules/webcpanel/pages/nickserv/nickserv.h48
-rw-r--r--modules/webcpanel/pages/operserv/akill.cpp8
-rw-r--r--modules/webcpanel/pages/operserv/operserv.h (renamed from modules/webcpanel/pages/operserv/akill.h)19
-rw-r--r--modules/webcpanel/pages/register.h9
-rw-r--r--modules/webcpanel/static_fileserver.cpp2
-rw-r--r--modules/webcpanel/static_fileserver.h9
-rw-r--r--modules/webcpanel/template_fileserver.cpp24
-rw-r--r--modules/webcpanel/template_fileserver.h13
-rw-r--r--modules/webcpanel/templates/chanserv/access.html (renamed from modules/webcpanel/templates/default/chanserv/access.html)6
-rw-r--r--modules/webcpanel/templates/chanserv/akick.html (renamed from modules/webcpanel/templates/default/chanserv/akick.html)6
-rw-r--r--modules/webcpanel/templates/chanserv/chanlist.html (renamed from modules/webcpanel/templates/default/chanserv/chanlist.html)0
-rw-r--r--modules/webcpanel/templates/chanserv/drop.html (renamed from modules/webcpanel/templates/default/chanserv/drop.html)4
-rw-r--r--modules/webcpanel/templates/chanserv/main.html3
-rw-r--r--modules/webcpanel/templates/chanserv/modes.html (renamed from modules/webcpanel/templates/default/chanserv/modes.html)6
-rw-r--r--modules/webcpanel/templates/chanserv/set.html (renamed from modules/webcpanel/templates/default/chanserv/set.html)8
-rw-r--r--modules/webcpanel/templates/confirm.html22
-rw-r--r--modules/webcpanel/templates/cubes.png (renamed from modules/webcpanel/templates/default/cubes.png)bin723 -> 723 bytes
-rw-r--r--modules/webcpanel/templates/default/chanserv/main.html3
-rw-r--r--modules/webcpanel/templates/default/confirm.html51
-rw-r--r--modules/webcpanel/templates/default/footer.html14
-rw-r--r--modules/webcpanel/templates/default/login.html55
-rw-r--r--modules/webcpanel/templates/default/nickserv/access.html42
-rw-r--r--modules/webcpanel/templates/favicon.ico (renamed from modules/webcpanel/templates/default/favicon.ico)bin3774 -> 3774 bytes
-rw-r--r--modules/webcpanel/templates/hostserv/request.html (renamed from modules/webcpanel/templates/default/hostserv/request.html)14
-rw-r--r--modules/webcpanel/templates/layout/footer.html11
-rw-r--r--modules/webcpanel/templates/layout/footer.loggedin.html4
-rw-r--r--modules/webcpanel/templates/layout/header.html14
-rw-r--r--modules/webcpanel/templates/layout/header.loggedin.html (renamed from modules/webcpanel/templates/default/header.html)25
-rw-r--r--modules/webcpanel/templates/login.html26
-rw-r--r--modules/webcpanel/templates/logo.png (renamed from modules/webcpanel/templates/default/logo.png)bin19247 -> 19247 bytes
-rw-r--r--modules/webcpanel/templates/memoserv/memos.html (renamed from modules/webcpanel/templates/default/memoserv/memos.html)4
-rw-r--r--modules/webcpanel/templates/nickserv/alist.html (renamed from modules/webcpanel/templates/default/nickserv/alist.html)4
-rw-r--r--modules/webcpanel/templates/nickserv/cert.html (renamed from modules/webcpanel/templates/default/nickserv/cert.html)6
-rw-r--r--modules/webcpanel/templates/nickserv/confirm.html (renamed from modules/webcpanel/templates/default/nickserv/confirm.html)4
-rw-r--r--modules/webcpanel/templates/nickserv/info.html (renamed from modules/webcpanel/templates/default/nickserv/info.html)24
-rw-r--r--modules/webcpanel/templates/operserv/akill.html (renamed from modules/webcpanel/templates/default/operserv/akill.html)6
-rw-r--r--modules/webcpanel/templates/register.html (renamed from modules/webcpanel/templates/default/register.html)33
-rw-r--r--modules/webcpanel/templates/style.css (renamed from modules/webcpanel/templates/default/style.css)8
-rw-r--r--modules/webcpanel/webcpanel.cpp35
-rw-r--r--modules/webcpanel/webcpanel.h61
-rw-r--r--src/CMakeLists.txt101
-rw-r--r--src/access.cpp90
-rw-r--r--src/account.cpp2
-rw-r--r--src/base.cpp8
-rw-r--r--src/bots.cpp59
-rw-r--r--src/channels.cpp112
-rw-r--r--src/command.cpp103
-rw-r--r--src/config.cpp201
-rw-r--r--src/extensible.cpp7
-rw-r--r--src/hashcomp.cpp8
-rw-r--r--src/init.cpp135
-rw-r--r--src/language.cpp112
-rw-r--r--src/logger.cpp82
-rw-r--r--src/mail.cpp43
-rw-r--r--src/main.cpp63
-rw-r--r--src/memos.cpp22
-rw-r--r--src/messages.cpp168
-rw-r--r--src/misc.cpp415
-rw-r--r--src/modes.cpp143
-rw-r--r--src/module.cpp12
-rw-r--r--src/modulemanager.cpp79
-rw-r--r--src/nickalias.cpp73
-rw-r--r--src/nickcore.cpp176
-rw-r--r--src/opertype.cpp54
-rw-r--r--src/pipeengine.cpp2
-rw-r--r--src/process.cpp137
-rw-r--r--src/protocol.cpp318
-rw-r--r--src/regchannel.cpp102
-rw-r--r--src/serialize.cpp15
-rw-r--r--src/servers.cpp83
-rw-r--r--src/siphash.cpp139
-rw-r--r--src/socket_clients.cpp2
-rw-r--r--src/socket_transport.cpp18
-rw-r--r--src/socketengines/epoll.cpp (renamed from src/socketengines/socketengine_epoll.cpp)8
-rw-r--r--src/socketengines/kqueue.cpp (renamed from src/socketengines/socketengine_kqueue.cpp)2
-rw-r--r--src/socketengines/poll.cpp (renamed from src/socketengines/socketengine_poll.cpp)6
-rw-r--r--src/socketengines/select.cpp (renamed from src/socketengines/socketengine_select.cpp)9
-rw-r--r--src/sockets.cpp102
-rw-r--r--src/threadengine.cpp89
-rw-r--r--src/timers.cpp44
-rw-r--r--src/tools/CMakeLists.txt30
-rw-r--r--src/tools/anope.service.in17
-rw-r--r--src/tools/anoperc.in8
-rw-r--r--src/tools/anopesmtp.cpp535
-rw-r--r--src/uplink.cpp126
-rw-r--r--src/users.cpp240
-rw-r--r--src/version.sh4
-rw-r--r--src/win32/Config.cs2
-rw-r--r--src/win32/anope_windows.h11
-rw-r--r--src/win32/conanfile.txt2
-rw-r--r--src/win32/dir/dir.cpp48
-rw-r--r--src/win32/dir/dir.h27
-rw-r--r--src/win32/dl/dl.cpp2
-rw-r--r--src/win32/dl/dl.h2
-rw-r--r--src/win32/pipe/pipe.cpp2
-rw-r--r--src/win32/pipe/pipe.h2
-rw-r--r--src/win32/pthread/pthread.cpp119
-rw-r--r--src/win32/pthread/pthread.h35
-rw-r--r--src/win32/resource.h2
-rw-r--r--src/win32/sigaction/sigaction.cpp2
-rw-r--r--src/win32/sigaction/sigaction.h4
-rw-r--r--src/win32/socket.cpp83
-rw-r--r--src/win32/socket.h6
-rw-r--r--src/win32/win32.rc.cmake4
-rw-r--r--src/win32/windows.cpp173
-rw-r--r--src/xline.cpp37
-rw-r--r--vendor/README.md43
-rw-r--r--vendor/bcrypt/crypt_blowfish.c907
-rw-r--r--vendor/bcrypt/crypt_blowfish.h27
-rw-r--r--vendor/md5/LICENSE8
-rw-r--r--vendor/md5/md5.c291
-rw-r--r--vendor/md5/md5.h45
-rw-r--r--vendor/sha2/sha2.c949
-rw-r--r--vendor/sha2/sha2.h108
-rwxr-xr-xvendor/update111
-rw-r--r--vendor/update.toml34
-rw-r--r--vendor/yyjson/LICENSE21
-rw-r--r--vendor/yyjson/yyjson.c9568
-rw-r--r--vendor/yyjson/yyjson.h7942
479 files changed, 47816 insertions, 66538 deletions
diff --git a/.BANNER b/.BANNER
index bae644cd0..cd113fc66 100644
--- a/.BANNER
+++ b/.BANNER
@@ -7,11 +7,11 @@
| |
|_| IRC Services
CURVER
-This program will help you to compile your Services, and ask you
+This program will help you to compile your services, and ask you
questions regarding the compile-time settings of it during the
process. For more options type SOURCE_DIR/Config --help
-Anope is a set of Services for IRC networks that allows users to
+Anope is a set of services for IRC networks that allows users to
manage their nicks and channels in a secure and efficient way,
and administrators to manage their network with powerful tools.
diff --git a/.github/ISSUE_TEMPLATE/BUG.yml b/.github/ISSUE_TEMPLATE/BUG.yml
new file mode 100644
index 000000000..6ecf407f1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/BUG.yml
@@ -0,0 +1,44 @@
+---
+name: Bug report
+description: Report a non-security bug in Anope.
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this bug report!
+
+ If you're looking for help with setting up your services please post on [our support forum](https://github.com/orgs/anope/discussions/categories/support) instead.
+
+ If you're reporting a crash or other security issue [please read our security policy](https://github.com/anope/anope/security/policy#reporting-a-vulnerability) for how to report security issues privately.
+
+ - type: textarea
+ attributes:
+ label: Description
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Steps to reproduce the issue
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Describe the results you received
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Describe the results you expected
+ validations:
+ required: true
+
+ - type: input
+ attributes:
+ label: Anope version
+ description: |-
+ Either the output of `services --version` (2.0) or `anope --version` (2.1).
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
deleted file mode 100644
index ba7f67999..000000000
--- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-name: Bug report
-about: Report a non-security issue with Anope.
----
-
-<!--
-Please fill in the template below. It will help us process your bug report a lot faster. If you have multiple bugs to report then please open one issue for each bug.
--->
-
-**Description**
-
-
-
-**Steps to reproduce the issue:**
-
-1.
-2.
-3.
-
-**Describe the results you received:**
-
-
-
-**Describe the results you expected:**
-
-
-
-**Additional information you deem important (e.g. issue happens only occasionally):**
-
-
-
-**Output of `services --version`:**
-
diff --git a/.github/ISSUE_TEMPLATE/FEATURE.yml b/.github/ISSUE_TEMPLATE/FEATURE.yml
new file mode 100644
index 000000000..625f1284f
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/FEATURE.yml
@@ -0,0 +1,20 @@
+---
+name: Feature request
+description: Request that a new feature is added to Anope.
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to fill out this feature request!
+
+ - type: textarea
+ attributes:
+ label: Description
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Why this would be useful?
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
deleted file mode 100644
index 8b64999a4..000000000
--- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-name: Feature request
-about: Request that a new feature is added to Anope.
----
-
-<!--
-Please fill in the template below. It will help us process your feature request a lot faster. If you have multiple features to request then please open one issue for each feature.
--->
-
-**Description**
-
-
-
-**Why this would be useful**
-
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 3ba13e0ce..5ac78f510 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1 +1,5 @@
blank_issues_enabled: false
+contact_links:
+ - name: Support forum
+ url: https://github.com/orgs/anope/discussions/categories/support
+ about: Please ask support questions here.
diff --git a/.github/workflows/ci-alpine.yml b/.github/workflows/ci-alpine.yml
new file mode 100644
index 000000000..c2a679303
--- /dev/null
+++ b/.github/workflows/ci-alpine.yml
@@ -0,0 +1,59 @@
+name: Alpine CI
+on:
+ pull_request:
+ push:
+ schedule:
+ - cron: '0 0 * * 0'
+jobs:
+ build:
+ if: "!contains(github.event.head_commit.message, '[skip alpine ci]')"
+ container: alpine:edge
+ runs-on: ubuntu-latest
+ env:
+ CXX: ${{ matrix.compiler }}
+ CXXFLAGS: -Werror
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install dependencies
+ run: |
+ echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
+ apk update
+ apk add \
+ argon2-dev \
+ clang \
+ cmake \
+ g++ \
+ gettext \
+ git \
+ gnutls-dev \
+ mariadb-dev \
+ openldap-dev \
+ openssl-dev \
+ pcre2-dev \
+ samurai \
+ sqlite-dev \
+ tre-dev
+
+ - name: Enable extras
+ run: |
+ for MODULE in enc_argon2 enc_posix ldap mysql regex_pcre2 regex_posix regex_tre sqlite ssl_gnutls ssl_openssl
+ do
+ ln -s $PWD/modules/extra/$MODULE.cpp $PWD/modules
+ done
+
+ - name: Run CMake
+ run: |
+ mkdir build && cd build
+ cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=DEBUG -DINSTDIR:STRING=$(readlink -f ../run) ..
+
+ - name: Build Anope
+ run: |
+ ninja -C build install
+
+ strategy:
+ fail-fast: false
+ matrix:
+ compiler:
+ - clang++
+ - g++
diff --git a/.github/workflows/ci-linux.yml b/.github/workflows/ci-linux.yml
index 6dd554928..9c281dbc2 100644
--- a/.github/workflows/ci-linux.yml
+++ b/.github/workflows/ci-linux.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-24.04
env:
CXX: ${{ matrix.compiler }}
- CXXFLAGS: -std=${{ matrix.standard }}
+ CXXFLAGS: -Werror
steps:
- uses: actions/checkout@v4
@@ -20,11 +20,11 @@ jobs:
g++ \
gettext \
git \
+ libargon2-dev \
libgnutls28-dev \
libldap2-dev \
libmysqlclient-dev \
libpcre2-dev \
- libpcre3-dev \
libsqlite3-dev \
libssl-dev \
libtre-dev \
@@ -32,9 +32,9 @@ jobs:
- name: Enable extras
run: |
- for MODULE in m_ldap.cpp m_ldap_authentication.cpp m_ldap_oper.cpp m_mysql.cpp m_regex_pcre.cpp m_regex_pcre2.cpp m_regex_posix.cpp m_regex_tre.cpp m_sql_authentication.cpp m_sql_log.cpp m_sql_oper.cpp m_sqlite.cpp m_ssl_gnutls.cpp m_ssl_openssl.cpp stats
+ for MODULE in enc_argon2 enc_posix ldap mysql regex_pcre2 regex_posix regex_tre sqlite ssl_gnutls ssl_openssl
do
- ln -s ${{ github.workspace }}/modules/extra/$MODULE ${{ github.workspace }}/modules
+ ln -s ${{ github.workspace }}/modules/extra/$MODULE.cpp ${{ github.workspace }}/modules
done
- name: Run CMake
@@ -52,6 +52,3 @@ jobs:
compiler:
- clang++
- g++
- standard:
- - c++98
- - c++17
diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml
new file mode 100644
index 000000000..37d14b061
--- /dev/null
+++ b/.github/workflows/ci-windows.yml
@@ -0,0 +1,46 @@
+name: Windows CI
+on:
+ pull_request:
+ push:
+ release:
+ types:
+ - published
+ schedule:
+ - cron: '0 0 * * 0'
+jobs:
+ build:
+ if: "!contains(github.event.head_commit.message, '[skip windows ci]')"
+ runs-on: windows-2019
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup MSBuild
+ uses: microsoft/setup-msbuild@v2
+
+ - name: Setup Conan
+ uses: turtlebrowser/get-conan@v1.2
+ with:
+ version: 1.64.0
+
+ - name: Install libraries
+ run: |
+ conan install ${{ github.workspace }}\src\win32 --build=missing
+
+ - name: Run CMake
+ run: |
+ mkdir ${{ github.workspace }}\build
+ cd ${{ github.workspace }}\build
+ cmake -A "x64" -D "CMAKE_BUILD_TYPE=${{ github.event_name == 'release' && 'Release' || 'Debug' }}" -G "Visual Studio 16 2019" ..
+
+ - name: Build Anope
+ working-directory: ${{ github.workspace }}\build
+ run: |
+ msbuild PACKAGE.vcxproj /M:3 /P:Configuration=${{ github.event_name == 'release' && 'Release' || 'Debug' }} /P:Platform=x64 /VERBOSITY:MINIMAL
+
+ - name: Upload installer
+ if: "${{ github.event_name == 'release' }}"
+ working-directory: ${{ github.workspace }}\build
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release upload ${{ github.event.release.tag_name }} $(Get-ChildItem anope-*.exe)
diff --git a/.gitignore b/.gitignore
index 03a3a02f5..bfe5f3746 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,19 +1,17 @@
build/
config.cache
include/sysconf.h
-modules/m_ldap.cpp
-modules/m_ldap_authentication.cpp
-modules/m_ldap_oper.cpp
-modules/m_mysql.cpp
-modules/m_regex_pcre.cpp
-modules/m_regex_pcre2.cpp
-modules/m_regex_posix.cpp
-modules/m_regex_tre.cpp
-modules/m_sql_authentication.cpp
-modules/m_sql_log.cpp
-modules/m_sql_oper.cpp
-modules/m_sqlite.cpp
-modules/m_ssl_gnutls.cpp
-modules/m_ssl_openssl.cpp
+modules/enc_argon2.cpp
+modules/enc_posix.cpp
+modules/ldap.cpp
+modules/mysql.cpp
+modules/regex_pcre2.cpp
+modules/regex_posix.cpp
+modules/regex_tre.cpp
+modules/sqlite.cpp
+modules/ssl_gnutls.cpp
+modules/ssl_openssl.cpp
modules/stats
run/
+*.mo
+*.pot
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 822f6f39d..65553c241 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,73 +1,10 @@
-# This usage of CMake requires at least version 2.4 (checks are made to determine what to use when certain versions lack functions)
-cmake_minimum_required(VERSION 2.4 FATAL_ERROR)
-if(COMMAND cmake_policy)
- cmake_policy(SET CMP0003 NEW)
- if(POLICY CMP0026)
- cmake_policy(SET CMP0026 OLD)
- endif(POLICY CMP0026)
- if(POLICY CMP0007)
- cmake_policy(SET CMP0007 OLD)
- endif(POLICY CMP0007)
-endif(COMMAND cmake_policy)
+# This usage of CMake requires at least version 3.8
+cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
# Set the project as C++ primarily, but have C enabled for the checks required later
project(Anope CXX)
enable_language(C)
-# Detect the version of CMake for the later conditional checks
-execute_process(COMMAND ${CMAKE_COMMAND} --version OUTPUT_VARIABLE VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
-string(REGEX REPLACE "cmake version 2\\.(.*)" "\\1" ONLY_VERSION "${VERSION}")
-string(REGEX MATCH "-patch .*$" HAS_PATCH "${ONLY_VERSION}")
-if(HAS_PATCH)
- string(REGEX REPLACE "(.*)-patch .*" "\\1" MINOR_VERSION "${ONLY_VERSION}")
- string(REGEX REPLACE ".*-patch (.*)" "\\1" PATCH_VERSION "${ONLY_VERSION}")
-else(HAS_PATCH)
- string(REGEX MATCH "\\." HAS_DOT "${ONLY_VERSION}")
- if(HAS_DOT)
- string(REGEX REPLACE "(.*)\\..*" "\\1" MINOR_VERSION "${ONLY_VERSION}")
- string(REGEX REPLACE ".*\\.(.*)" "\\1" PATCH_VERSION "${ONLY_VERSION}")
- else(HAS_DOT)
- string(REGEX REPLACE "(.*)-beta" "\\1" MINOR_VERSION "${ONLY_VERSION}")
- if(MINOR_VERSION STREQUAL "4-1\n")
- set(PATCH_VERSION 1)
- else(MINOR_VERSION STREQUAL "4-1\n")
- set(PATCH_VERSION 0)
- endif(MINOR_VERSION STREQUAL "4-1\n")
- set(MINOR_VERSION 4)
- endif(HAS_DOT)
-endif(HAS_PATCH)
-
-# Detect is we are using CMake 2.6 or better, these versions include functions that require less work than CMake 2.4 does
-if(MINOR_VERSION GREATER 5)
- set(CMAKE26_OR_BETTER TRUE)
- set(CMAKE248_OR_BETTER TRUE)
- set(CMAKE244_OR_BETTER TRUE)
- set(CMAKE242_OR_BETTER TRUE)
-else(MINOR_VERSION GREATER 5)
- set(CMAKE26_OR_BETTER FALSE)
- # Also detect if we are using CMake 2.4.8 or better, the FIND sub-command of list() is nonexistent in earlier versions
- if(PATCH_VERSION GREATER 7)
- set(CMAKE248_OR_BETTER TRUE)
- set(CMAKE244_OR_BETTER TRUE)
- set(CMAKE242_OR_BETTER TRUE)
- else(PATCH_VERSION GREATER 7)
- set(CMAKE248_OR_BETTER FALSE)
- # Also detect if we are using CMake 2.4.4 or better, the CheckCXXCompilerFlag module and SORT sub-command of list() are nonexistent in earlier versions
- if(PATCH_VERSION GREATER 3)
- set(CMAKE244_OR_BETTER TRUE)
- set(CMAKE242_OR_BETTER TRUE)
- else(PATCH_VERSION GREATER 3)
- set(CMAKE244_OR_BETTER FALSE)
- # ALSO detect if we are using CMake 2.4.2 or better, the APPEND sub-command of list() is nonexistent in earlier versions
- if(PATCH_VERSION GREATER 1)
- set(CMAKE242_OR_BETTER TRUE)
- else(PATCH_VERSION GREATER 1)
- set(CMAKE242_OR_BETTER FALSE)
- endif(PATCH_VERSION GREATER 1)
- endif(PATCH_VERSION GREATER 3)
- endif(PATCH_VERSION GREATER 7)
-endif(MINOR_VERSION GREATER 5)
-
# Override the module include path to include our directory, for our Anope.cmake, as well as we are using our own version of the NSIS template
set(CMAKE_MODULE_PATH ${Anope_SOURCE_DIR}/cmake)
@@ -80,14 +17,13 @@ set(ENV{LC_ALL} C)
set(DEFAULT_LIBRARY_DIRS)
set(DEFAULT_INCLUDE_DIRS)
-# Check that we aren't running on an ancient broken GCC
-if(CMAKE_COMPILER_IS_GNUCXX)
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_FULL_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(REGEX REPLACE "^(\\d+\\.\\d+)" "\\1" GCC_VERSION ${GCC_FULL_VERSION})
- if(GCC_VERSION LESS 4.2)
- message(FATAL_ERROR "Your compiler is too old to build Anope. Upgrade to GCC 4.2 or newer!")
- endif(GCC_VERSION LESS 4.2)
-endif(CMAKE_COMPILER_IS_GNUCXX)
+# We require C++17 to build
+set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Put modules in their own folder
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# If we are using a GNU compiler (have to use CXX because it seems to fail on C), we will be able to determine it's default paths for libraries and includes
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
@@ -95,12 +31,8 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-search-dirs OUTPUT_VARIABLE LINES OUTPUT_STRIP_TRAILING_WHITESPACE)
# Find only the part after "libraries: "
string(REGEX REPLACE ".*\nlibraries: (.*)$" "\\1" LINE "${LINES}")
- # Replace the colons in the list with semicolons (only when not on MinGW, which uses semicolons already), and if on MinGW, just copy the line
- if(NOT MINGW)
- string(REGEX REPLACE ":" ";" LIBRARIES ${LINE})
- else(NOT MINGW)
- set(LIBRARIES "${LINE}")
- endif(NOT MINGW)
+ # Replace the colons in the list with semicolons
+ string(REGEX REPLACE ":" ";" LIBRARIES ${LINE})
# Iterate through the libraries
foreach(LIBRARY ${LIBRARIES})
# Check if the first character is an equal sign, and skip that library directory as it is (I believe) the primary default and shows up later in the list anyways
@@ -108,13 +40,13 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
if(NOT FIRST_CHAR STREQUAL "=")
# If the directory had no = in front of it, make sure it's absolute and add it to the list of default library directories
get_filename_component(LIBRARY ${LIBRARY} ABSOLUTE)
- append_to_list(DEFAULT_LIBRARY_DIRS ${LIBRARY})
- endif(NOT FIRST_CHAR STREQUAL "=")
- endforeach(LIBRARY)
+ list(APPEND DEFAULT_LIBRARY_DIRS ${LIBRARY})
+ endif()
+ endforeach()
# Remove duplicate entries from the list
if(DEFAULT_LIBRARY_DIRS)
- remove_list_duplicates(DEFAULT_LIBRARY_DIRS)
- endif(DEFAULT_LIBRARY_DIRS)
+ list(REMOVE_DUPLICATES DEFAULT_LIBRARY_DIRS)
+ endif()
# Create a temporary file to test for the default include directories
FILE(WRITE empty.cpp "")
# Next, we look for the compiler's default include directories
@@ -131,11 +63,11 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
# If the line has the following on it, the next lines will contain directory names
if(LINE STREQUAL "#include <...> search starts here:")
set(IN_SEARCH TRUE)
- else(LINE STREQUAL "#include <...> search starts here:")
+ else()
# If the line has the following on it, we hit the end of the list
if(LINE STREQUAL "End of search list.")
set(IN_SEARCH FALSE)
- else(LINE STREQUAL "End of search list.")
+ else()
# If we are within the block between the above two lines...
if(IN_SEARCH)
# Get everything but the first character of the line
@@ -147,47 +79,16 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
# Convert the path to an absolute one, just in case it wasn't
get_filename_component(INCLUDE ${INCLUDE} ABSOLUTE)
# Add that directory to the list of default include directories
- append_to_list(DEFAULT_INCLUDE_DIRS ${INCLUDE})
- endif(IN_SEARCH)
- endif(LINE STREQUAL "End of search list.")
- endif(LINE STREQUAL "#include <...> search starts here:")
- endforeach(LINE)
+ list(APPEND DEFAULT_INCLUDE_DIRS ${INCLUDE})
+ endif()
+ endif()
+ endif()
+ endforeach()
# Remove duplicate entries from the list
if(DEFAULT_INCLUDE_DIRS)
- remove_list_duplicates(DEFAULT_INCLUDE_DIRS)
- endif(DEFAULT_INCLUDE_DIRS)
-endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
-
-# If we are using Visual Studio, locate the path of the Windows Server 2008 SDK or Windows Server 2003 Platform SDK, depending on which is installed
-if(MSVC)
- # If the path comes up as "/registry" from any of these, the path wasn't found, otherwise, we'll set WSDK_PATH to the corresponding path
- # Look for the 2008 SDK under HKLM first
- get_filename_component(WSDK2008_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" ABSOLUTE CACHE)
- if(WSDK2008_PATH STREQUAL "/registry")
- # If not found, look for the 2003 SDK under HKLM
- get_filename_component(WSDK2003_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1;Install Dir]" ABSOLUTE CACHE)
- if(WSDK2003_PATH STREQUAL "/registry")
- # If not found, look for the 2008 SDK under HKCU
- get_filename_component(WSDK2008_PATH "[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" ABSOLUTE CACHE)
- if(WSDK2008_PATH STREQUAL "/registry")
- # If not found, look for the 2003 SDK under HKCU
- get_filename_component(WSDK2003_PATH "[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1;Install Dir]" ABSOLUTE CACHE)
- if(WSDK2003_PATH STREQUAL "/registry")
- # The SDK was never found, set the path to nothing
- set(WSDK_PATH "")
- else(WSDK2003_PATH STREQUAL "/registry")
- set(WSDK_PATH "${WSDK2003_PATH}")
- endif(WSDK2003_PATH STREQUAL "/registry")
- else(WSDK2008_PATH STREQUAL "/registry")
- set(WSDK_PATH "${WSDK2008_PATH}")
- endif(WSDK2008_PATH STREQUAL "/registry")
- else(WSDK2003_PATH STREQUAL "/registry")
- set(WSDK_PATH "${WSDK2003_PATH}")
- endif(WSDK2003_PATH STREQUAL "/registry")
- else(WSDK2008_PATH STREQUAL "/registry")
- set(WSDK_PATH "${WSDK2008_PATH}")
- endif(WSDK2008_PATH STREQUAL "/registry")
-endif(MSVC)
+ list(REMOVE_DUPLICATES DEFAULT_INCLUDE_DIRS)
+ endif()
+endif()
# If the user specifies -DCMAKE_BUILD_TYPE on the command line, take their definition
# and dump it in the cache along with proper documentation, otherwise set CMAKE_BUILD_TYPE
@@ -196,38 +97,26 @@ endif(MSVC)
if(NOT MSVC)
if(CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
- else(CMAKE_BUILD_TYPE)
+ else()
set(CMAKE_BUILD_TYPE DEBUG CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
- endif(CMAKE_BUILD_TYPE)
-endif(NOT MSVC)
-
-# If running under MinGW, we have to force the resource compiler settings (hopefully this will be fixed in a later version of CMake)
-if(MINGW)
- set(CMAKE_RC_COMPILER_INIT windres)
- enable_language(RC)
- set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -o <OBJECT> <SOURCE>")
-endif(MINGW)
+ endif()
+endif()
# Include the checking functions used later in this CMakeLists.txt
include(CheckFunctionExists)
-include(CheckIncludeFile)
include(CheckTypeSize)
include(CheckLibraryExists)
-if(CMAKE244_OR_BETTER)
- include(CheckCXXCompilerFlag)
-else(CMAKE244_OR_BETTER)
- include(TestCXXAcceptsFlag)
-endif(CMAKE244_OR_BETTER)
+include(CheckCXXCompilerFlag)
# If extra include directories were specified, tell cmake about them.
if(EXTRA_INCLUDE)
include_directories(${EXTRA_INCLUDE})
-endif(EXTRA_INCLUDE)
+endif()
# If extra library directories were specified, tell cmake about them.
if(EXTRA_LIBS)
link_directories(${EXTRA_LIBS})
-endif(EXTRA_LIBS)
+endif()
# setup conan
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/conanbuildinfo.cmake")
@@ -237,25 +126,31 @@ endif()
# Find gettext
find_package(Gettext)
-
-option(USE_PCH "Use precompiled headers" OFF)
+find_package(Intl)
+if(GETTEXT_FOUND AND Intl_FOUND)
+ set(HAVE_LOCALIZATION ON)
+ include_directories(${Intl_INCLUDE_DIRS})
+else()
+ message("Unable to find gettext and libintl; disabling localization")
+ set(HAVE_LOCALIZATION OFF)
+endif()
# Use the following directories as includes
-# Note that it is important the binary include directory comes before the
-# source include directory so the precompiled headers work correctly.
-include_directories(${Anope_BINARY_DIR}/include ${Anope_SOURCE_DIR}/include ${Anope_BINARY_DIR}/language ${Anope_SOURCE_DIR}/modules/pseudoclients)
+include_directories(
+ ${Anope_BINARY_DIR}/include
+ ${Anope_SOURCE_DIR}/include
+ ${Anope_SOURCE_DIR}/vendor
+)
# Pass on REPRODUCIBLE_BUILD
if(REPRODUCIBLE_BUILD)
add_definitions(-DREPRODUCIBLE_BUILD)
-endif(REPRODUCIBLE_BUILD)
+endif()
-# If using Windows, always add the _WIN32 define
if(WIN32)
- add_definitions(-D_WIN32)
- # And include the windows specific folder for our anope_windows.h
+ # If using Windows, include the windows specific folder for anope_windows.h
include_directories(${Anope_SOURCE_DIR}/src/win32)
-endif(WIN32)
+endif()
# If using Visual Studio, set the C++ flags accordingly
if(MSVC)
@@ -264,108 +159,56 @@ if(MSVC)
string(REPLACE "/GX " "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
string(REPLACE "/W3 " "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# Set the compile flags to have warnings on the max setting (but disable a few annoying ones), exception handling turned on, the proper defines
- set(CXXFLAGS "${CXXFLAGS} /W4 /wd4100 /wd4127 /wd4250 /wd4251 /wd4355 /wd4706 /wd4800 /wd4996 /EHs")
- add_definitions(-DMSVCPP -D_CRT_SECURE_NO_WARNINGS)
+ set(CXXFLAGS "${CXXFLAGS} /W4 /wd4100 /wd4127 /wd4250 /wd4251 /wd4267 /wd4275 /wd4355 /wd4706 /wd4800 /wd4996 /EHs")
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS)
# Otherwise, we're not using Visual Studio
-else(MSVC)
+else()
# Set the compile flags to have all warnings on (including shadowed variables)
- set(CXXFLAGS "${CXXFLAGS} -Wall -Wshadow")
- # If on a *nix system, also set the compile flags to remove GNU extensions (favor ISO C++) as well as reject non-ISO C++ code, also remove all leading underscores in exported symbols (only on GNU compiler)
- if(UNIX)
- set(CXXFLAGS "${CXXFLAGS} -ansi -pedantic ${CMAKE_CXX_FLAGS}")
- if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- set(CXXFLAGS "${CXXFLAGS} -Wno-long-long -fno-leading-underscore")
- endif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- # If we aren't on a *nix system, we are using MinGW
- else(UNIX)
- # Also, if we are building under MinGW, add another define for MinGW
- if(MINGW)
- add_definitions(-DMINGW)
- endif(MINGW)
- endif(UNIX)
-endif(MSVC)
+ set(CXXFLAGS "${CXXFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wextra -Wformat=2 -Wmissing-format-attribute -Wpedantic -Wno-format-nonliteral -Wno-format-zero-length -Wno-unused-parameter ${CMAKE_CXX_FLAGS}")
+endif()
# If CMake has found that the given system requires a special library for dl* calls, include it with the linker flags
if(CMAKE_DL_LIBS)
- append_to_list(LINK_LIBS ${CMAKE_DL_LIBS})
-endif(CMAKE_DL_LIBS)
+ list(APPEND LINK_LIBS ${CMAKE_DL_LIBS})
+endif()
-# Under MinGW, the -shared flag isn't properly set in the module-specific linker flags, add it from the C flags for shared libraries
-if(MINGW)
- set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS}")
-endif(MINGW)
+# Find the linker flags required for using threads.
+find_package("Threads" REQUIRED)
+if(CMAKE_THREAD_LIBS_INIT)
+ list(APPEND LINK_LIBS ${CMAKE_THREAD_LIBS_INIT})
+endif()
if(NOT PROGRAM_NAME)
- # Under Windows, we set the executable name for Anope to be anope
- if(WIN32)
- set(PROGRAM_NAME anope)
- # Under *nix, we set the executable name for Anope to be services
- else(WIN32)
- set(PROGRAM_NAME services)
- endif(WIN32)
-endif(NOT PROGRAM_NAME)
+ set(PROGRAM_NAME anope)
+endif()
# If we are not using Visual Studio, we'll run the following checks
if(NOT MSVC)
# Check if the C++ compiler can accept the -pipe flag, and add it to the compile flags if it works
- if(CMAKE244_OR_BETTER)
- # If using CMake 2.4.4 or better, we can use check_cxx_compiler_flag
- check_cxx_compiler_flag(-pipe HAVE_PIPE_FLAG)
- else(CMAKE244_OR_BETTER)
- # If using CMake 2.4.3 or older, we will use check_cxx_accepts_flags instead
- check_cxx_accepts_flag(-pipe HAVE_PIPE_FLAG)
- endif(CMAKE244_OR_BETTER)
+ check_cxx_compiler_flag(-pipe HAVE_PIPE_FLAG)
# If the flag was accepted, add it to the list of flags
if(HAVE_PIPE_FLAG)
set(CXXFLAGS "${CXXFLAGS} -pipe")
- endif(HAVE_PIPE_FLAG)
-
- # The following are additional library checks, they are not required for Windows
- if(NOT WIN32)
- # Check if socket is within the socket library (if the library exists), and add it to the linker flags if needed
- check_library_exists(socket socket "" HAVE_SOCKET_LIB)
- if(HAVE_SOCKET_LIB)
- append_to_list(LINK_LIBS socket)
- endif(HAVE_SOCKET_LIB)
- # Check if inet_addr is within the nsl library (if the library exists), and add it to the linker flags if needed
- check_library_exists(nsl inet_addr "" HAVE_NSL_LIB)
- if(HAVE_NSL_LIB)
- append_to_list(LINK_LIBS nsl)
- endif(HAVE_NSL_LIB)
- # Check if pthread_create is within the pthread library (if the library exists), and add it to the linker flags if needed
- check_library_exists(pthread pthread_create "" HAVE_PTHREAD)
- if(HAVE_PTHREAD)
- if(NOT APPLE)
- set(LDFLAGS "${LDFLAGS} -pthread")
- endif(NOT APPLE)
- else(HAVE_PTHREAD)
- message(FATAL_ERROR "The pthread library is required to build Anope")
- endif(HAVE_PTHREAD)
- endif(NOT WIN32)
-endif(NOT MSVC)
+ endif()
+endif()
# If DEFUMASK wasn't passed to CMake, set a default depending on if RUNGROUP was passed in or not
if(NOT DEFUMASK)
if(RUNGROUP)
set(DEFUMASK "007")
- else(RUNGROUP)
+ else()
set(DEFUMASK "077")
- endif(RUNGROUP)
-endif(NOT DEFUMASK)
+ endif()
+endif()
# Set the DEBUG_BUILD for sysconf.h
if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(DEBUG_BUILD TRUE)
-endif(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
-
-# Check for the existence of the following include files
-check_include_file(cstdint HAVE_CSTDINT)
-check_include_file(stdint.h HAVE_STDINT_H)
-check_include_file(strings.h HAVE_STRINGS_H)
+endif()
# Check for the existence of the following functions
-check_function_exists(strcasecmp HAVE_STRCASECMP)
-check_function_exists(stricmp HAVE_STRICMP)
+check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
check_function_exists(umask HAVE_UMASK)
check_function_exists(epoll_wait HAVE_EPOLL)
check_function_exists(poll HAVE_POLL)
@@ -373,63 +216,62 @@ check_function_exists(kqueue HAVE_KQUEUE)
# Strip the leading and trailing spaces from the compile flags
if(CXXFLAGS)
- strip_string(${CXXFLAGS} CXXFLAGS)
-endif(CXXFLAGS)
+ string(STRIP ${CXXFLAGS} CXXFLAGS)
+endif()
# Strip the leading and trailing spaces from the linker flags
if(LDFLAGS)
- strip_string(${LDFLAGS} LDFLAGS)
-endif(LDFLAGS)
+ string(STRIP ${LDFLAGS} LDFLAGS)
+endif()
# Search for the following programs
-find_program(GREP grep)
-find_program(SH sh)
-find_program(CHGRP chgrp)
-find_program(CHMOD chmod)
+if(NOT WIN32 AND RUNGROUP)
+ find_program(CHGRP "chgrp" REQUIRED)
+ find_program(CHMOD "chmod" REQUIRED)
+endif()
-# If a INSTDIR was passed in to CMake, use it as the install prefix, otherwise set the default install prefix to the services directory under the user's home directory
+# If a INSTDIR was passed in to CMake, use it as the install prefix, otherwise set the default install prefix to the anope directory under the user's home directory
if(INSTDIR)
set(CMAKE_INSTALL_PREFIX "${INSTDIR}")
elseif(NOT CMAKE_INSTALL_PREFIX)
- set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/services")
-endif(INSTDIR)
+ set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/anope")
+endif()
# Set default paths for various directories if not already defined
if(NOT BIN_DIR)
set(BIN_DIR "bin")
-endif(NOT BIN_DIR)
-if(NOT DB_DIR)
- set(DB_DIR "data")
-endif(NOT DB_DIR)
+endif()
+if(NOT DATA_DIR)
+ set(DATA_DIR "data")
+endif()
if(NOT DOC_DIR)
set(DOC_DIR "doc")
-endif(NOT DOC_DIR)
+endif()
if(NOT CONF_DIR)
set(CONF_DIR "conf")
-endif(NOT CONF_DIR)
-if(NOT LIB_DIR)
- set(LIB_DIR "lib")
-endif(NOT LIB_DIR)
+endif()
+if(NOT MODULE_DIR)
+ set(MODULE_DIR "modules")
+endif()
if(NOT LOCALE_DIR)
set(LOCALE_DIR "locale")
-endif(NOT LOCALE_DIR)
-if(NOT LOGS_DIR)
- set(LOGS_DIR "logs")
-endif(NOT LOGS_DIR)
+endif()
+if(NOT LOG_DIR)
+ set(LOG_DIR "logs")
+endif()
# Version number processing
# Find all lines in src/version.sh that start with VERSION_
-read_from_file(${Anope_SOURCE_DIR}/src/version.sh "^VERSION_" VERSIONS)
+file(STRINGS ${Anope_SOURCE_DIR}/src/version.sh VERSIONS REGEX "^VERSION_")
# Iterate through the strings found
foreach(VERSION_STR ${VERSIONS})
string(REGEX REPLACE "^VERSION_([A-Z]+)=\"?([^\"]*)\"?$" "\\1;\\2" VERSION_OUT ${VERSION_STR})
- # Depends on CMP0007 OLD
list(LENGTH VERSION_OUT VERSION_LEN)
list(GET VERSION_OUT 0 VERSION_TYPE)
if(${VERSION_LEN} GREATER 1)
list(GET VERSION_OUT 1 VERSION_DATA)
set(VERSION_${VERSION_TYPE} ${VERSION_DATA})
- endif(${VERSION_LEN} GREATER 1)
-endforeach(VERSION_STR ${VERSIONS})
+ endif()
+endforeach()
# Default build version to 0
set(VERSION_BUILD 0)
@@ -437,7 +279,7 @@ set(VERSION_BUILD 0)
# Only change the build number if version.h exists
if(EXISTS "${Anope_SOURCE_DIR}/include/version.h")
# Attempt to read the build number from include/version.h
- read_from_file(${Anope_SOURCE_DIR}/include/version.h "^#define VERSION_BUILD" VERSIONS)
+ file(STRINGS ${Anope_SOURCE_DIR}/src/version.sh VERSIONS REGEX "^#define VERSION_BUILD")
foreach(VERSION_STR ${VERSIONS})
# Get the length of the string
string(LENGTH ${VERSION_STR} VERSION_LEN)
@@ -447,8 +289,8 @@ if(EXISTS "${Anope_SOURCE_DIR}/include/version.h")
string(SUBSTRING ${VERSION_STR} 22 ${VERSION_NUM_LEN} VERSION)
# Set VERSION_BUILD correctly
set(VERSION_BUILD ${VERSION})
- endforeach(VERSION_STR ${VERSIONS})
-endif(EXISTS "${Anope_SOURCE_DIR}/include/version.h")
+ endforeach()
+endif()
# Set the version variables based on what was found above
set(VERSION_COMMA "${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_BUILD}")
@@ -461,7 +303,7 @@ set(VERSION_FULL_NOBUILD "${VERSION_DOTTED_NOBUILD}${VERSION_EXTRA}")
if(WIN32)
# Generate the win32.rc file using the above variables
configure_file(${Anope_SOURCE_DIR}/src/win32/win32.rc.cmake ${Anope_BINARY_DIR}/src/win32/win32.rc)
-endif(WIN32)
+endif()
# Add the initial files to ignore which will be ignored regardless of if you are building in-source or out-of-source
add_to_cpack_ignored_files(".git\;config.cache\;CMakeFiles\;sysconf.h$\;build" TRUE)
@@ -476,8 +318,8 @@ if(${Anope_SOURCE_DIR} STREQUAL ${Anope_BINARY_DIR})
# If using Visual Studio, add these files as well
if(MSVC)
add_to_cpack_ignored_files(".vcproj$\;.sln$\;.ncb$\;.suo$\;.dir$\;.ilk$\;.exp$\;.pdb$\;.lib$\;/debug$;/release$;/relwithdebinfo$;/minsizerel$" TRUE)
- endif(MSVC)
-endif(${Anope_SOURCE_DIR} STREQUAL ${Anope_BINARY_DIR})
+ endif()
+endif()
# Go into the following directories and run their CMakeLists.txt as well
add_subdirectory(data)
@@ -488,29 +330,32 @@ add_subdirectory(modules)
add_subdirectory(include)
# Get the filename of the Anope binary, to use later
-get_target_property(SERVICES_BINARY ${PROGRAM_NAME} LOCATION)
+set(SERVICES_BINARY "$<TARGET_FILE:${PROGRAM_NAME}>")
get_filename_component(SERVICES_BINARY ${SERVICES_BINARY} NAME)
# At install time, create the following additional directories
-install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/backups\")")
-install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${LOGS_DIR}\")")
+get_filename_component(ABSOLUTE_DATA_DIR ${DATA_DIR} REALPATH BASE_DIR ${CMAKE_INSTALL_PREFIX})
+get_filename_component(ABSOLUTE_LOG_DIR ${LOG_DIR} REALPATH BASE_DIR ${CMAKE_INSTALL_PREFIX})
+install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/backups\")")
+install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_LOG_DIR}\")")
if(WIN32)
- install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/runtime\")")
-endif(WIN32)
+ install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/runtime\")")
+endif()
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the below directories, as well as the group of the data directory
if(NOT WIN32 AND RUNGROUP)
- install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DB_DIR}/backups\")")
- install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${LOGS_DIR}\")")
+ install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/backups\")")
+ install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}${ABSOLUTE_LOG_DIR}\")")
install(CODE "execute_process(COMMAND ${CHGRP} -R ${RUNGROUP} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}\")")
-endif(NOT WIN32 AND RUNGROUP)
+endif()
# On Windows platforms, install extra files
if(WIN32)
install(FILES ${Anope_SOURCE_DIR}/src/win32/anope.bat
DESTINATION ${BIN_DIR}
)
-endif(WIN32)
+endif()
-install(CODE "file(REMOVE_RECURSE \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/modules\")")
+get_filename_component(ABSOLUTE_MODULE_DIR ${MODULE_DIR} REALPATH BASE_DIR ${CMAKE_INSTALL_PREFIX})
+install(CODE "file(REMOVE_RECURSE \"$ENV{DESTDIR}${ABSOLUTE_MODULE_DIR}\")")
# Only process the CPack section if we have CPack
if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
@@ -549,10 +394,10 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
set(CPACK_NSIS_INSTALLED_ICON_NAME "${SERVICES_BINARY}")
set(CPACK_NSIS_URL_INFO_ABOUT "https://www.anope.org/")
set(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
- endif(WIN32)
+ endif()
set(CPACK_SOURCE_PACKAGE_FILE_NAME "anope-${VERSION_FULL_NOBUILD}-source")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "$ENV{CPACK_IGNORED_FILES}")
set(CPACK_MONOLITHIC_INSTALL TRUE)
include(CPack)
-endif(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+endif()
diff --git a/Config b/Config
index 9cf1a6cc4..c872a9913 100755
--- a/Config
+++ b/Config
@@ -1,8 +1,8 @@
#!/bin/sh
#
-# Configuration script for Services.
+# Configuration script for Anope.
#
-# Anope (C) 2003-2024 Anope Team
+# Anope (C) 2003-2025 Anope Team
# Contact us at team@anope.org
#
# This program is free but copyrighted software; see the file COPYING for
@@ -13,10 +13,6 @@
#
###########################################################################
-echo2 () {
- $ECHO2 "$*$ECHO2SUF" # these are defined later
-}
-
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
@@ -42,7 +38,6 @@ Run_Build_System () {
WITH_PERM=""
EXTRA_INCLUDE=""
EXTRA_LIBS=""
- GEN_TYPE=""
if [ "$INSTDIR" != "" ] ; then
WITH_INST="-DINSTDIR:STRING=$INSTDIR"
@@ -62,12 +57,6 @@ Run_Build_System () {
BUILD_TYPE="-DCMAKE_BUILD_TYPE:STRING=RELEASE"
fi
- if [ "$USE_PCH" = "yes" ] ; then
- PCH="-DUSE_PCH:BOOLEAN=ON"
- else
- PCH="-DUSE_PCH:BOOLEAN=OFF"
- fi
-
if [ "$EXTRA_INCLUDE_DIRS" != "" ] ; then
EXTRA_INCLUDE="-DEXTRA_INCLUDE:STRING=$EXTRA_INCLUDE_DIRS"
fi
@@ -76,65 +65,38 @@ Run_Build_System () {
EXTRA_LIBS="-DEXTRA_LIBS:STRING=$EXTRA_LIB_DIRS"
fi
- case `uname -s` in
- MINGW*)
- GEN_TYPE="-G\"MSYS Makefiles\""
- ;;
- esac
-
- if [ "$SOURCE_DIR" = "." ] ; then
- pwdsave=`pwd`
- test -d build || mkdir build
- cd "build"
- REAL_SOURCE_DIR=".."
- else
- REAL_SOURCE_DIR="$SOURCE_DIR"
- fi
+ BUILD_PATHS="-B ${SOURCE_DIR}/build ${SOURCE_DIR}"
- echo "cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $PCH $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $REAL_SOURCE_DIR"
+ CMAKE="cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $BUILD_PATHS"
+ echo $CMAKE
+ $CMAKE
- cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $PCH $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $REAL_SOURCE_DIR
if [ $? -ne 0 ]; then
echo "You should fix these issues and then run ./Config -quick to rerun CMake."
exit 1
fi
echo ""
- if [ "$SOURCE_DIR" = "." ] ; then
- echo "Now cd build, then run make to build Anope."
- cd "$pwdsave"
- else
+ if [ "$PWD" = "${SOURCE_DIR}/build" ]; then
echo "Now run make to build Anope."
+ else
+ echo "Now cd build, then run make to build Anope."
fi
}
-ECHO2SUF=''
-if [ "`echo -n a ; echo -n b`" = "ab" ] ; then
- ECHO2='echo -n'
-elif [ "`echo 'a\c' ; echo 'b\c'`" = "ab" ] ; then
- ECHO2='echo' ; ECHO2SUF='\c'
-elif [ "`printf 'a' 2>&1 ; printf 'b' 2>&1`" = "ab" ] ; then
- ECHO2='printf "%s"'
-else
- # oh well...
- ECHO2='echo'
-fi
-export ECHO2 ECHO2SUF
-
###########################################################################
# Init values
###########################################################################
-INSTDIR=$HOME/services
+INSTDIR=$HOME/anope
RUNGROUP=
UMASK=
DEBUG="no"
-USE_PCH="no"
EXTRA_INCLUDE_DIRS=
EXTRA_LIB_DIRS=
EXTRA_CONFIG_ARGS=
CAN_QUICK="no"
-SOURCE_DIR=`dirname $0`
+SOURCE_DIR="$(cd "$(dirname "$0")" && pwd)"
###########################################################################
# Check out the options
@@ -151,7 +113,7 @@ while [ $# -ge 1 ] ; do
exit 0
elif [ $1 = "-devel" ] ; then
DEBUG="yes"
- INSTDIR="$PWD/run"
+ INSTDIR="$SOURCE_DIR/run"
elif [ $1 = "-nocache" ] ; then
IGNORE_CACHE="1"
elif [ $1 = "-nointro" ] ; then
@@ -176,7 +138,7 @@ done
cmake --version 2>&1 > /dev/null
if [ $? -ne 0 ] ; then
clear
- echo "Anope requires CMake 2.4 or newer, which can be downloaded at https://cmake.org/ or through your system's package manager."
+ echo "Anope requires CMake 3.8 or newer, which can be downloaded at https://cmake.org/ or through your system's package manager."
echo "If you have installed CMake already, ensure it is in your PATH environment variable."
exit 0
fi
@@ -184,24 +146,15 @@ fi
###########################################################################
if [ ! "$NO_INTRO" ] ; then
- case `uname -s` in
- MINGW*)
- PAGER=less
- ;;
- *)
- PAGER=more
- clear
- ;;
- esac
export MORE='-e'
. $SOURCE_DIR/src/version.sh
- cat $SOURCE_DIR/.BANNER | sed "s/CURVER/$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH$VERSION_EXTRA/" | sed "s@SOURCE_DIR@$SOURCE_DIR@" | $PAGER
+ cat $SOURCE_DIR/.BANNER | sed "s/CURVER/$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH$VERSION_EXTRA/" | sed "s@SOURCE_DIR@$SOURCE_DIR@" | more
echo ""
else
echo ""
fi
-echo "Beginning Services configuration."
+echo "Beginning Anope configuration."
echo ""
###########################################################################
@@ -221,7 +174,7 @@ export ok INPUT
ok=0
echo "In what directory should Anope be installed?"
while [ $ok -eq 0 ] ; do
- echo2 "[$INSTDIR] "
+ echo -n "[$INSTDIR] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ ! "$INPUT" ] ; then
INPUT=$INSTDIR
@@ -231,7 +184,7 @@ while [ $ok -eq 0 ] ; do
echo "$INPUT exists, but is not a directory!"
else
echo "$INPUT does not exist. Create it?"
- echo2 "[y] "
+ echo -n "[y] "
read YN
if [ "$YN" != "n" ] ; then
if mkdir -p $INPUT ; then
@@ -240,7 +193,7 @@ while [ $ok -eq 0 ] ; do
fi
fi
elif exists "$INPUT/include/services.h" ; then
- echo "You cannot use the Services source directory as a target directory."
+ echo "You cannot use the Anope source directory as a target directory."
else
ok=1
fi
@@ -252,15 +205,15 @@ echo ""
OLD_RUNGROUP="$RUNGROUP"
if [ "$RUNGROUP" ] ; then
- echo "Which group should all Services data files be owned by? (If Services"
+ echo "Which group should all Anope data files be owned by? (If Anope"
echo "should not force files to be owned by a particular group, type \"none\""
echo "(without the quotes) and press Return.)"
else
- echo "Which group should all Services data files be owned by? (If Services"
+ echo "Which group should all Anope data files be owned by? (If Anope"
echo "should not force files to be owned by a particular group, just press"
echo "Return.)"
fi
-echo2 "[$RUNGROUP] "
+echo -n "[$RUNGROUP] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "none" ] ; then
@@ -285,7 +238,7 @@ ok=0
echo "What should the default umask for data files be (in octal)?"
echo "(077 = only accessible by owner; 007 = accessible by owner and group)"
while [ $ok -eq 0 ] ; do
- echo2 "[$UMASK] "
+ echo -n "[$UMASK] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ ! "$INPUT" ] ; then
INPUT=$UMASK
@@ -309,7 +262,7 @@ if [ "$DEBUG" = "yes" ] ; then
TEMP_YN="y"
fi
echo "Would you like to build a debug version of Anope?"
-echo2 "[$TEMP_YN] "
+echo -n "[$TEMP_YN] "
read YN
if [ "$YN" ] ; then
if [ "$YN" = "y" ] ; then
@@ -322,31 +275,12 @@ echo ""
####
-TEMP_YN="n"
-if [ "$USE_PCH" = "yes" ] ; then
- TEMP_YN="y"
-fi
-echo "Do you want to build using precompiled headers? This can speed up"
-echo "the build, but uses more disk space."
-echo2 "[$TEMP_YN] "
-read YN
-if [ "$YN" ] ; then
- if [ "$YN" = "y" ] ; then
- USE_PCH="yes"
- else
- USE_PCH="no"
- fi
-fi
-echo ""
-
-####
-
echo "Are there any extra include directories you wish to use?"
echo "You may only need to do this if CMake is unable to locate"
echo "missing dependencies without hints."
echo "Separate directories with semicolons."
echo "If you need no extra include directories, enter NONE in all caps."
-echo2 "[$EXTRA_INCLUDE_DIRS] "
+echo -n "[$EXTRA_INCLUDE_DIRS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
@@ -364,7 +298,7 @@ echo "You may only need to do this if CMake is unable to locate"
echo "missing dependencies without hints."
echo "Separate directories with semicolons."
echo "If you need no extra library directories, enter NONE in all caps."
-echo2 "[$EXTRA_LIB_DIRS] "
+echo -n "[$EXTRA_LIB_DIRS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
@@ -379,7 +313,7 @@ echo ""
echo "Are there any extra arguments you wish to pass to CMake?"
echo "If you need no extra arguments to CMake, enter NONE in all caps."
-echo2 "[$EXTRA_CONFIG_ARGS] "
+echo -n "[$EXTRA_CONFIG_ARGS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
@@ -396,14 +330,13 @@ echo ""
# Store values
################################################################################
-echo2 "Saving configuration results in config.cache... "
+echo -n "Saving configuration results in config.cache... "
cat <<EOT >$SOURCE_DIR/config.cache
INSTDIR="$INSTDIR"
RUNGROUP="$RUNGROUP"
UMASK=$UMASK
DEBUG="$DEBUG"
-USE_PCH="$USE_PCH"
EXTRA_INCLUDE_DIRS="$EXTRA_INCLUDE_DIRS"
EXTRA_LIB_DIRS="$EXTRA_LIB_DIRS"
EXTRA_CONFIG_ARGS="$EXTRA_CONFIG_ARGS"
diff --git a/README.md b/README.md
index 4a470e59f..32fde658b 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
## About
-Anope is an open source set of IRC Services. It is highly modular, with a vast number of configurable parameters, and is the most used IRC services package. There are also many modules on the [modsite](https://modules.anope.org) to add additional features. It runs on Linux, BSD, and Windows, and supports many modern IRCds, including InspIRCd, UnrealIRCd, and ircd-hybrid. For more details, credits, command line options, and contact information see [docs/README](https://github.com/anope/anope/blob/2.0/docs/README).
+Anope is an open source set of IRC services. It is highly modular, with a vast number of configurable parameters, and is the most used IRC services package. There are also many modules on the [modsite](https://modules.anope.org) to add additional features. It runs on Linux, BSD, and Windows, and supports many modern IRCds, including InspIRCd, UnrealIRCd, and ircd-hybrid. For more details, credits, command line options, and contact information see [docs/README](https://github.com/anope/anope/blob/2.0/docs/README).
* [Website](https://anope.org)
* [GitHub](https://github.com/anope)
@@ -19,7 +19,7 @@ $ make
$ make install
```
-Now change to the directory where you installed Anope to, e.g. `$ cd ~/services/`
+Now change to the directory where you installed Anope to, e.g. `$ cd ~/anope/`
### Windows
Download the latest release off of the [releases page](https://github.com/anope/anope/releases) and run the installer.
@@ -27,19 +27,19 @@ Download the latest release off of the [releases page](https://github.com/anope/
## Configuration
-Copy conf/example.conf to conf/services.conf
+Copy conf/anope.example.conf to conf/anope.conf
```
-$ cp conf/example.conf conf/services.conf
+$ cp conf/anope.example.conf conf/anope.conf
```
-Edit services.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the the example.conf documentation. The [Anope wiki](https://wiki.anope.org) is also a good source of information. Our support channel is located at #anope on [irc.teranova.net](ircs://irc.teranova.net/anope).
+Edit anope.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the the example.conf documentation. The [Anope wiki](https://wiki.anope.org) is also a good source of information. Our support channel is located at #anope on [irc.teranova.net](ircs://irc.teranova.net/anope).
-Note that the example configuration file includes other example configuration files. If you want to modify the other example configuration files, copy them (e.g. `modules.example.conf` to `modules.conf`) and modify the `include` directive in `services.conf` to include the new file.
+Note that the example configuration file includes other example configuration files. If you want to modify the other example configuration files, copy them (e.g. `modules.example.conf` to `modules.conf`) and modify the `include` directive in `anope.conf` to include the new file.
## Running
-Run `$ ./bin/services` to start Anope. If asked to provide logs for support, use the `--support` flag, e.g.: `$ ./bin/services --support`
+Run `$ ./bin/anope` to start Anope. If asked to provide logs for support, use the `--support` flag, e.g.: `$ ./bin/anope --support`
## Installing extra modules
diff --git a/cmake/Anope.cmake b/cmake/Anope.cmake
index 581dc5164..6dd136421 100644
--- a/cmake/Anope.cmake
+++ b/cmake/Anope.cmake
@@ -1,422 +1,4 @@
###############################################################################
-# strip_string(<input string> <output string>)
-#
-# A macro to handle stripping the leading and trailing spaces from a string,
-# uses string(STRIP) if using CMake 2.6.x or better, otherwise uses
-# string(REGEX REPLACE).
-###############################################################################
-macro(strip_string INPUT_STRING OUTPUT_STRING)
- if(CMAKE26_OR_BETTER)
- # For CMake 2.6.x or better, we can just use the STRIP sub-command of string()
- string(STRIP ${INPUT_STRING} ${OUTPUT_STRING})
- else(CMAKE26_OR_BETTER)
- # For CMake 2.4.x, we will have to use the REGEX REPLACE sub-command of string() instead
- # First check if the input string is empty or not
- if (${INPUT_STRING} STREQUAL "")
- set(${OUTPUT_STRING} "")
- else(${INPUT_STRING} STREQUAL "")
- # Determine if the string is entirely empty or not
- string(REGEX MATCH "^[ \t]*$" EMPTY_STRING "${INPUT_STRING}")
- if(EMPTY_STRING)
- set(${OUTPUT_STRING} "")
- else(EMPTY_STRING)
- # We detect if there is any leading whitespace and remove any if there is
- string(SUBSTRING "${INPUT_STRING}" 0 1 FIRST_CHAR)
- if(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t")
- string(REGEX REPLACE "^[ \t]+" "" TEMP_STRING "${INPUT_STRING}")
- else(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t")
- set(TEMP_STRING "${INPUT_STRING}")
- endif(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t")
- # Next we detect if there is any trailing whitespace and remove any if there is
- string(LENGTH "${TEMP_STRING}" STRING_LEN)
- math(EXPR STRING_LEN "${STRING_LEN} - 1")
- string(SUBSTRING "${TEMP_STRING}" ${STRING_LEN} 1 LAST_CHAR)
- if(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t")
- string(REGEX REPLACE "[ \t]+$" "" ${OUTPUT_STRING} "${TEMP_STRING}")
- else(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t")
- set(${OUTPUT_STRING} "${TEMP_STRING}")
- endif(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t")
- endif(EMPTY_STRING)
- endif(${INPUT_STRING} STREQUAL "")
- endif(CMAKE26_OR_BETTER)
-endmacro(strip_string)
-
-###############################################################################
-# append_to_list(<list> <args>...)
-#
-# A macro to handle appending to lists, uses list(APPEND) if using CMake 2.4.2
-# or better, otherwise uses set() instead.
-###############################################################################
-macro(append_to_list LIST)
- if(CMAKE242_OR_BETTER)
- # For CMake 2.4.2 or better, we can just use the APPEND sub-command of list()
- list(APPEND ${LIST} ${ARGN})
- else(CMAKE242_OR_BETTER)
- # For CMake 2.4.x before 2.4.2, we have to do this manually use set() instead
- set(${LIST} ${${LIST}} ${ARGN})
- endif(CMAKE242_OR_BETTER)
-endmacro(append_to_list)
-
-###############################################################################
-# find_in_list(<list> <value> <output variable>)
-#
-# A macro to handle searching within a list, will store the result in the
-# given <output variable>, uses list(FIND) if using CMake 2.6.x or better
-# (or CMake 2.4.8 or better), otherwise it iterates through the list to find
-# the item.
-###############################################################################
-macro(find_in_list LIST ITEM_TO_FIND FOUND)
- if(CMAKE248_OR_BETTER)
- # For CMake 2.4.8 or better, we can use the FIND sub-command of list()
- list(FIND ${LIST} ${ITEM_TO_FIND} ITEM_FOUND)
- else(CMAKE248_OR_BETTER)
- # For CMake 2.4.x before 2.4.8, we have to do this ourselves (NOTE: This is very slow due to a lack of break() as well)
- # Firstly we set the position to -1 indicating nothing found, we also use a temporary position
- set(ITEM_FOUND -1)
- set(POS 0)
- # Iterate through the list
- foreach(ITEM ${${LIST}})
- # If the item we are looking at is the item we are trying to find, set that we've found the item
- if(${ITEM} STREQUAL ${ITEM_TO_FIND})
- set(ITEM_FOUND ${POS})
- endif(${ITEM} STREQUAL ${ITEM_TO_FIND})
- # Increase the position value by 1
- math(EXPR POS "${POS} + 1")
- endforeach(ITEM)
- endif(CMAKE248_OR_BETTER)
- # Set the given FOUND variable to the result
- set(${FOUND} ${ITEM_FOUND})
-endmacro(find_in_list)
-
-###############################################################################
-# remove_list_duplicates(<list>)
-#
-# A macro to handle removing duplicates from a list, uses
-# list(REMOVE_DUPLICATES) if using CMake 2.6.x or better, otherwise it uses
-# a slower method of creating a temporary list and only adding to it when
-# a duplicate item hasn't been found.
-###############################################################################
-macro(remove_list_duplicates LIST)
- if(CMAKE26_OR_BETTER)
- # For CMake 2.6.x or better, this can be done automatically
- list(REMOVE_DUPLICATES ${LIST})
- else(CMAKE26_OR_BETTER)
- # For CMake 2.4.x, we have to do this ourselves, firstly we'll clear a temporary list
- set(NEW_LIST)
- # Iterate through the old list
- foreach(ITEM ${${LIST}})
- # Check if the item is in the new list
- find_in_list(NEW_LIST ${ITEM} FOUND_ITEM)
- if(FOUND_ITEM EQUAL -1)
- # If the item was not found, append it to the list
- append_to_list(NEW_LIST ${ITEM})
- endif(FOUND_ITEM EQUAL -1)
- endforeach(ITEM)
- # Replace the old list with the new list
- set(${LIST} ${NEW_LIST})
- endif(CMAKE26_OR_BETTER)
-endmacro(remove_list_duplicates)
-
-###############################################################################
-# remove_item_from_list(<list> <value>)
-#
-# A macro to handle removing a value from a list, uses list(REMOVE_ITEM) in
-# both cases, but can remove the value itself using CMake 2.4.2 or better,
-# while older versions use a slower method of iterating the list to find the
-# index of the value to remove.
-###############################################################################
-macro(remove_item_from_list LIST VALUE)
- if(CMAKE242_OR_BETTER)
- # For CMake 2.4.2 or better, this can be done automatically
- list(REMOVE_ITEM ${LIST} ${VALUE})
- else(CMAKE242_OR_BETTER)
- # For CMake 2.4.x before 2.4.2, we have to do this ourselves, firstly we set the index and a variable to indicate if the item was found
- set(INDEX 0)
- set(FOUND FALSE)
- # Iterate through the old list
- foreach(ITEM ${${LIST}})
- # If the item hasn't been found yet, but the current item is the same, remove it
- if(NOT FOUND)
- if(ITEM STREQUAL ${VALUE})
- set(FOUND TRUE)
- list(REMOVE_ITEM ${LIST} ${INDEX})
- endif(ITEM STREQUAL ${VALUE})
- endif(NOT FOUND)
- # Increase the index value by 1
- math(EXPR INDEX "${INDEX} + 1")
- endforeach(ITEM)
- endif(CMAKE242_OR_BETTER)
-endmacro(remove_item_from_list)
-
-###############################################################################
-# sort_list(<list>)
-#
-# A macro to handle sorting a list, uses list(SORT) if using CMake 2.4.4 or
-# better, otherwise it uses a slower method of creating a temporary list and
-# adding elements in alphabetical order.
-###############################################################################
-macro(sort_list LIST)
- if(CMAKE244_OR_BETTER)
- # For CMake 2.4.4 or better, this can be done automatically
- list(SORT ${LIST})
- else(CMAKE244_OR_BETTER)
- # For CMake 2.4.x before 2.4.4, we have to do this ourselves, firstly we'll create a temporary list
- set(NEW_LIST)
- # Iterate through the old list
- foreach(ITEM ${${LIST}})
- # Temporary index position for the new list, as well as temporary value to store if the item was ever found
- set(INDEX 0)
- set(FOUND FALSE)
- # Iterate through the new list
- foreach(NEW_ITEM ${NEW_LIST})
- # Compare the items, only if nothing was found before
- if(NOT FOUND)
- if(NEW_ITEM STRGREATER "${ITEM}")
- set(FOUND TRUE)
- list(INSERT NEW_LIST ${INDEX} ${ITEM})
- endif(NEW_ITEM STRGREATER "${ITEM}")
- endif(NOT FOUND)
- # Increase the index value by 1
- math(EXPR INDEX "${INDEX} + 1")
- endforeach(NEW_ITEM)
- # If the item was never found, just append it to the end
- if(NOT FOUND)
- append_to_list(NEW_LIST ${ITEM})
- endif(NOT FOUND)
- endforeach(ITEM)
- # Replace the old list with the new list
- set(${LIST} ${NEW_LIST})
- endif(CMAKE244_OR_BETTER)
-endmacro(sort_list)
-
-###############################################################################
-# read_from_file(<filename> <regex> <output variable>)
-#
-# A macro to handle reading specific lines from a file, uses file(STRINGS) if
-# using CMake 2.6.x or better, otherwise we read in the entire file and
-# perform a string(REGEX MATCH) on each line of the file instead. This
-# macro can also be used to read in all the lines of a file if REGEX is set
-# to "".
-###############################################################################
-macro(read_from_file FILE REGEX STRINGS)
- if(CMAKE26_OR_BETTER)
- # For CMake 2.6.x or better, we can just use the STRINGS sub-command to get the lines that match the given regular expression (if one is given, otherwise get all lines)
- if(REGEX STREQUAL "")
- file(STRINGS ${FILE} RESULT)
- else(REGEX STREQUAL "")
- file(STRINGS ${FILE} RESULT REGEX ${REGEX})
- endif(REGEX STREQUAL "")
- else(CMAKE26_OR_BETTER)
- # For CMake 2.4.x, we need to do this manually, firstly we read the file in
- execute_process(COMMAND ${CMAKE_COMMAND} -DFILE:STRING=${FILE} -P ${Anope_SOURCE_DIR}/cmake/ReadFile.cmake ERROR_VARIABLE ALL_STRINGS)
- # Next we replace all newlines with semicolons
- string(REGEX REPLACE "\n" ";" ALL_STRINGS ${ALL_STRINGS})
- if(REGEX STREQUAL "")
- # For no regular expression, just set the result to all the lines
- set(RESULT ${ALL_STRINGS})
- else(REGEX STREQUAL "")
- # Clear the result list
- set(RESULT)
- # Iterate through all the lines of the file
- foreach(STRING ${ALL_STRINGS})
- # Check for a match against the given regular expression
- string(REGEX MATCH ${REGEX} STRING_MATCH ${STRING})
- # If we had a match, append the match to the list
- if(STRING_MATCH)
- append_to_list(RESULT ${STRING})
- endif(STRING_MATCH)
- endforeach(STRING)
- endif(REGEX STREQUAL "")
- endif(CMAKE26_OR_BETTER)
- # Set the given STRINGS variable to the result
- set(${STRINGS} ${RESULT})
-endmacro(read_from_file)
-
-###############################################################################
-# extract_include_filename(<line> <output variable> [<optional output variable of quote type>])
-#
-# This macro will take a #include line and extract the filename.
-###############################################################################
-macro(extract_include_filename INCLUDE FILENAME)
- # Strip the leading and trailing spaces from the include line
- strip_string(${INCLUDE} INCLUDE_STRIPPED)
- # Make sure to only do the following if there is a string
- if(INCLUDE_STRIPPED STREQUAL "")
- set(FILE "")
- else(INCLUDE_STRIPPED STREQUAL "")
- # Extract the filename including the quotes or angle brackets
- string(REGEX REPLACE "^.*([\"<].*[\">]).*$" "\\1" FILE "${INCLUDE_STRIPPED}")
- # If an optional 3rd argument is given, we'll store if the quote style was quoted or angle bracketed
- if(${ARGC} GREATER 2)
- string(SUBSTRING ${FILE} 0 1 QUOTE)
- if(QUOTE STREQUAL "<")
- set(${ARGV2} "angle brackets")
- else(QUOTE STREQUAL "<")
- set(${ARGV2} "quotes")
- endif(QUOTE STREQUAL "<")
- endif(${ARGC} GREATER 2)
- # Now remove the quotes or angle brackets
- string(REGEX REPLACE "^[\"<](.*)[\">]$" "\\1" FILE "${FILE}")
- endif(INCLUDE_STRIPPED STREQUAL "")
- # Set the filename to the the given variable
- set(${FILENAME} "${FILE}")
-endmacro(extract_include_filename)
-
-###############################################################################
-# find_includes(<source filename> <output variable>)
-#
-# This macro will search through a file for #include lines, regardless of
-# whitespace, but only returns the lines that are valid for the current
-# platform CMake is running on.
-###############################################################################
-macro(find_includes SRC INCLUDES)
- # Read all lines from the file that start with #, regardless of whitespace before the #
- read_from_file(${SRC} "^[ \t]*#.*$" LINES)
- # Set that any #include lines found are valid, and create temporary variables for the last found #ifdef/#ifndef
- set(VALID_LINE TRUE)
- set(LAST_DEF)
- set(LAST_CHECK)
- # Create an empty include list
- set(INCLUDES_LIST)
- # Iterate through all the # lines
- foreach(LINE ${LINES})
- # Search for #ifdef, #ifndef, #else, #endif, and #include
- string(REGEX MATCH "^[ \t]*#[ \t]*ifdef[ \t]*.*$" FOUND_IFDEF ${LINE})
- string(REGEX MATCH "^[ \t]*#[ \t]*ifndef[ \t]*.*$" FOUND_IFNDEF ${LINE})
- string(REGEX MATCH "^[ \t]*#[ \t]*else.*$" FOUND_ELSE ${LINE})
- string(REGEX MATCH "^[ \t]*#[ \t]*endif.*$" FOUND_ENDIF ${LINE})
- string(REGEX MATCH "^[ \t]*#[ \t]*include[ \t]*[\"<].*[\">][\ t]*.*$" FOUND_INCLUDE ${LINE})
- # If we found a #ifdef on the line, extract the data after the #ifdef and set if the lines after it are valid based on the variables in CMake
- if(FOUND_IFDEF)
- # Extract the define
- string(REGEX REPLACE "^[ \t]*#[ \t]*ifdef[ \t]*(.*)$" "\\1" DEFINE ${LINE})
- # Replace _WIN32 with WIN32, so we can check if the WIN32 variable of CMake is set instead of _WIN32
- if(DEFINE STREQUAL "_WIN32")
- set(DEFINE WIN32)
- endif(DEFINE STREQUAL "_WIN32")
- # Set the last define to this one, and set the last check to true, so when #else is encountered, we can do an opposing check
- set(LAST_DEF ${DEFINE})
- set(LAST_CHECK TRUE)
- # If the define is true (it either exists or is a non-false result), the lines following will be checked, otherwise they will be skipped
- if(${DEFINE})
- set(VALID_LINE TRUE)
- else(${DEFINE})
- set(VALID_LINE FALSE)
- endif(${DEFINE})
- else(FOUND_IFDEF)
- # If we found a #ifndef on the line, the same thing as #ifdef is done, except with the checks in the opposite direction
- if(FOUND_IFNDEF)
- # Extract the define
- string(REGEX REPLACE "^[ \t]*#[ \t]*ifndef[ \t]*(.*)$" "\\1" DEFINE ${LINE})
- # Replace _WIN32 with WIN32, so we can check if the WIN32 variable of CMake is set instead of _WIN32
- if(DEFINE STREQUAL "_WIN32")
- set(DEFINE WIN32)
- endif(DEFINE STREQUAL "_WIN32")
- # Set the last define to this one, and set the last check to false, so when #else is encountered, we can do an opposing check
- set(LAST_DEF ${DEFINE})
- set(LAST_CHECK FALSE)
- # If the define is not true (it either doesn't exists or is a false result), the lines following will be checked, otherwise they will be skipped
- if(${DEFINE})
- set(VALID_LINE FALSE)
- else(${DEFINE})
- set(VALUE_LINE TRUE)
- endif(${DEFINE})
- else(FOUND_IFNDEF)
- # If we found a #else on the line, we check the last define in the opposite direction
- if(FOUND_ELSE)
- # When LAST_CHECK is true, we were inside a #ifdef, now act as if we are entering a #ifndef section by doing an opposing check
- if(LAST_CHECK)
- if(${LAST_DEF})
- set(VALID_LINE FALSE)
- else(${LAST_DEF})
- set(VALID_LINE TRUE)
- endif(${LAST_DEF})
- # When LAST_CHECK is false, we were inside a #ifndef, now act as if we are entering a #ifdef section by doing an opposing check
- else(LAST_CHECK)
- if(${LAST_DEF})
- set(VALID_LINE TRUE)
- else(${LAST_DEF})
- set(VALID_LINE FALSE)
- endif(${LAST_DEF})
- endif(LAST_CHECK)
- else(FOUND_ELSE)
- # If we found a #endif on the line, we'll assume everything following the line is valid until we meet another one of the above lines
- if(FOUND_ENDIF)
- set(VALID_LINE TRUE)
- else(FOUND_ENDIF)
- # If we found a #include on the line, add the entire line to the list of includes unless the line isn't valid
- if(FOUND_INCLUDE)
- if(VALID_LINE)
- append_to_list(INCLUDES_LIST "${LINE}")
- endif(VALID_LINE)
- endif(FOUND_INCLUDE)
- endif(FOUND_ENDIF)
- endif(FOUND_ELSE)
- endif(FOUND_IFNDEF)
- endif(FOUND_IFDEF)
- endforeach(LINE)
- set(${INCLUDES} ${INCLUDES_LIST})
-endmacro(find_includes)
-
-###############################################################################
-# calculate_depends(<source filename> [<optional output variable for includes>])
-#
-# This macro is used in most of the src (sub)directories to calculate the
-# header file dependencies for the given source file.
-###############################################################################
-macro(calculate_depends SRC)
- # Temporarily set that we didn't get a 3rd argument before we actually check if we did get one or not
- set(CHECK_ANGLE_INCLUDES FALSE)
- # Check for a third argument
- if(${ARGC} GREATER 1)
- set(CHECK_ANGLE_INCLUDES TRUE)
- endif(${ARGC} GREATER 1)
- # Find all the lines in the given source file that have any form of #include on them, regardless of whitespace, but only if they are valid for the platform we are on
- find_includes(${SRC} INCLUDES)
- # Reset the list of headers to empty
- set(HEADERS)
- # Iterate through the strings containing #include (if any)
- foreach(INCLUDE ${INCLUDES})
- # Extract the filename from the #include line
- extract_include_filename(${INCLUDE} FILENAME QUOTE_TYPE)
- if(QUOTE_TYPE STREQUAL "angle brackets")
- # The following checks will only be done if there was a request for angle includes to be checked
- if(CHECK_ANGLE_INCLUDES)
- # Find the path of the include file
- if(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
- find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include ${EXTRA_INCLUDE})
- else(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
- find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} ${EXTRA_INCLUDE})
- endif(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
- # If the include file was found, add it's path to the list of include paths, but only if it doesn't already exist and isn't in the defaults for the compiler
- if(FOUND_${FILENAME}_INCLUDE)
- # This used to be find_in_list, but it was changed to this loop to do a find on each default include directory, this fixes Mac OS X trying to get it's framework directories in here
- set(FOUND_IN_DEFAULTS -1)
- foreach(DEFAULT_INCLUDE_DIR ${DEFAULT_INCLUDE_DIRS})
- string(REGEX REPLACE "\\+" "\\\\+" DEFAULT_INCLUDE_DIR ${DEFAULT_INCLUDE_DIR})
- string(REGEX MATCH ${DEFAULT_INCLUDE_DIR} FOUND_DEFAULT ${FOUND_${FILENAME}_INCLUDE})
- if(FOUND_DEFAULT)
- set(FOUND_IN_DEFAULTS 0)
- endif(FOUND_DEFAULT)
- endforeach(DEFAULT_INCLUDE_DIR)
- if(FOUND_IN_DEFAULTS EQUAL -1)
- find_in_list(${ARGV1} "${FOUND_${FILENAME}_INCLUDE}" FOUND_IN_INCLUDES)
- if(FOUND_IN_INCLUDES EQUAL -1)
- append_to_list(${ARGV1} "${FOUND_${FILENAME}_INCLUDE}")
- endif(FOUND_IN_INCLUDES EQUAL -1)
- endif(FOUND_IN_DEFAULTS EQUAL -1)
- else(FOUND_${FILENAME}_INCLUDE)
- # XXX
- if(NOT ${FILENAME} STREQUAL "libintl.h")
- message(FATAL_ERROR "${SRC} needs header file ${FILENAME} but we were unable to locate that header file! Check that the header file is within the search path of your OS.")
- endif(NOT ${FILENAME} STREQUAL "libintl.h")
- endif(FOUND_${FILENAME}_INCLUDE)
- endif(CHECK_ANGLE_INCLUDES)
- endif(QUOTE_TYPE STREQUAL "angle brackets")
- endforeach(INCLUDE)
-endmacro(calculate_depends)
-
-###############################################################################
# calculate_libraries(<source filename> <output variable for linker flags> <output variable for extra depends>)
#
# This macro is used in most of the module (sub)directories to calculate the
@@ -433,10 +15,10 @@ macro(calculate_libraries SRC SRC_LDFLAGS EXTRA_DEPENDS)
set(LIBRARIES)
# Check to see if there are any lines matching: /* RequiredLibraries: [something] */
if(WIN32)
- read_from_file(${SRC} "/\\\\*[ \t]*RequiredWindowsLibraries:[ \t]*.*[ \t]*\\\\*/" REQUIRED_LIBRARIES)
- else(WIN32)
- read_from_file(${SRC} "/\\\\*[ \t]*RequiredLibraries:[ \t]*.*[ \t]*\\\\*/" REQUIRED_LIBRARIES)
- endif(WIN32)
+ file(STRINGS ${SRC} REQUIRED_LIBRARIES REGEX "/\\*[ \t]*RequiredWindowsLibraries:[ \t]*.*[ \t]*\\*/")
+ else()
+ file(STRINGS ${SRC} REQUIRED_LIBRARIES REGEX "/\\*[ \t]*RequiredLibraries:[ \t]*.*[ \t]*\\*/")
+ endif()
# Iterate through those lines
foreach(REQUIRED_LIBRARY ${REQUIRED_LIBRARIES})
# Strip off the /* RequiredLibraries: and */ from the line
@@ -450,86 +32,55 @@ macro(calculate_libraries SRC SRC_LDFLAGS EXTRA_DEPENDS)
if (${LIBRARY} MATCHES "^.+\\|.+$")
string(REGEX REPLACE ".+\\|(.*)" "\\1" LIBRARY_ALT ${LIBRARY})
string(REGEX REPLACE "(.+)\\|.*" "\\1" LIBRARY ${LIBRARY})
- endif(${LIBRARY} MATCHES "^.+\\|.+$")
+ endif()
# Locate the library to see if it exists
- if(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
- find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib ${EXTRA_INCLUDE} ${EXTRA_LIBS})
- else(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
+ if(DEFAULT_LIBRARY_DIRS OR DEFINED $ENV{VCINSTALLDIR})
+ find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${DEFAULT_LIBRARY_DIRS} $ENV{VCINSTALLDIR}/lib ${EXTRA_INCLUDE} ${EXTRA_LIBS})
+ else()
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${EXTRA_INCLUDE} ${EXTRA_LIBS} NO_DEFAULT_PATH)
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${EXTRA_INCLUDE} ${EXTRA_LIBS})
- endif(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
+ endif()
# If the library was found, we will add it to the linker flags
if(FOUND_${LIBRARY}_LIBRARY)
if(MSVC)
# For Visual Studio, instead of editing the linker flags, we'll add the library to a separate list of extra dependencies
- append_to_list(EXTRA_DEPENDENCIES "${FOUND_${LIBRARY}_LIBRARY}")
- else(MSVC)
+ list(APPEND EXTRA_DEPENDENCIES "${FOUND_${LIBRARY}_LIBRARY}")
+ else()
# Get the path only of the library, to add it to library paths.
get_filename_component(LIBRARY_PATH ${FOUND_${LIBRARY}_LIBRARY} PATH)
- append_to_list(LIBRARY_PATHS "${LIBRARY_PATH}")
+ list(APPEND LIBRARY_PATHS "${LIBRARY_PATH}")
# Extract the library short name, add it to the library path
get_filename_component(LIBRARY_NAME ${FOUND_${LIBRARY}_LIBRARY} NAME_WE)
string(REGEX REPLACE "^lib" "" LIBRARY_NAME ${LIBRARY_NAME})
- append_to_list(LIBRARIES ${LIBRARY_NAME})
- endif(MSVC)
- else(FOUND_${LIBRARY}_LIBRARY)
+ list(APPEND LIBRARIES ${LIBRARY_NAME})
+ endif()
+ else()
# In the case of the library not being found, we fatally error so CMake stops trying to generate
message(FATAL_ERROR "${SRC} needs library ${LIBRARY} but we were unable to locate that library! Check that the library is within the search path of your OS.")
- endif(FOUND_${LIBRARY}_LIBRARY)
- endforeach(LIBRARY)
- endforeach(REQUIRED_LIBRARY)
+ endif()
+ endforeach()
+ endforeach()
# Remove duplicates from the library paths
if(LIBRARY_PATHS)
- remove_list_duplicates(LIBRARY_PATHS)
- endif(LIBRARY_PATHS)
+ list(REMOVE_DUPLICATES LIBRARY_PATHS)
+ endif()
# Remove diplicates from the libraries
if(LIBRARIES)
- remove_list_duplicates(LIBRARIES)
- endif(LIBRARIES)
+ list(REMOVE_DUPLICATES LIBRARIES)
+ endif()
# Iterate through library paths and add them to the linker flags
foreach(LIBRARY_PATH ${LIBRARY_PATHS})
- find_in_list(DEFAULT_LIBRARY_DIRS "${LIBRARY_PATH}" FOUND_IN_DEFAULTS)
- if(FOUND_IN_DEFAULTS EQUAL -1)
+ if(NOT "${LIBRARY_PATH}" IN_LIST DEFAULT_LIBRARY_DIRS)
set(THIS_LDFLAGS "${THIS_LDFLAGS} -L${LIBRARY_PATH}")
- endif(FOUND_IN_DEFAULTS EQUAL -1)
- endforeach(LIBRARY_PATH)
+ endif()
+ endforeach()
# Iterate through libraries and add them to the linker flags
foreach(LIBRARY ${LIBRARIES})
- append_to_list(EXTRA_DEPENDENCIES "${LIBRARY}")
- endforeach(LIBRARY)
+ list(APPEND EXTRA_DEPENDENCIES "${LIBRARY}")
+ endforeach()
set(${SRC_LDFLAGS} "${THIS_LDFLAGS}")
set(${EXTRA_DEPENDS} "${EXTRA_DEPENDENCIES}")
-endmacro(calculate_libraries)
-
-###############################################################################
-# check_functions(<source filename> <output variable set to TRUE on success>)
-#
-# This macro is used in most of the module (sub)directories to calculate the
-# function dependencies for the given source file.
-###############################################################################
-macro(check_functions SRC SUCCESS)
- # Default to true
- set(${SUCCESS} TRUE)
- # Check to see if there are any lines matching: /* RequiredFunctions: [something] */
- read_from_file(${SRC} "/\\\\*[ \t]*RequiredFunctions:[ \t]*.*[ \t]*\\\\*/" REQUIRED_FUNCTIONS)
- # Iterate through those lines
- foreach(REQUIRED_FUNCTION ${REQUIRED_FUNCTIONS})
- # Strip off the /* RequiredFunctions: and */ from the line
- string(REGEX REPLACE "/\\*[ \t]*RequiredFunctions:[ \t]*([^ \t]*)[ \t]*\\*/" "\\1" REQUIRED_FUNCTION ${REQUIRED_FUNCTION})
- # Replace all commas with semicolons
- string(REGEX REPLACE "," ";" REQUIRED_FUNCTION ${REQUIRED_FUNCTION})
- # Iterate through the functions given
- foreach(FUNCTION ${REQUIRED_FUNCTION})
- # Check if the function exists
- check_function_exists(${REQUIRED_FUNCTION} HAVE_${REQUIRED_FUNCTION})
- # If we don't have the function warn the user and set SUCCESS to FALSE
- if(NOT HAVE_${REQUIRED_FUNCTION})
- message("${SRC} needs function ${REQUIRED_FUNCTION} but we were unable to locate that function!")
- set(${SUCCESS} FALSE)
- endif(NOT HAVE_${REQUIRED_FUNCTION})
- endforeach(FUNCTION)
- endforeach(REQUIRED_FUNCTION)
-endmacro(check_functions)
+endmacro()
###############################################################################
# add_to_cpack_ignored_files(<item> [TRUE])
@@ -544,12 +95,12 @@ macro(add_to_cpack_ignored_files ITEM)
# If we have 2+ arguments, assume that the second one was something like TRUE (doesn't matter really) and convert periods so they will be \\. for CPack
if(${ARGC} GREATER 1)
string(REPLACE "." "\\\\." REAL_ITEM ${REAL_ITEM})
- endif(${ARGC} GREATER 1)
+ endif()
# If the environment variable is already defined, just tack the item to the end
if(DEFINED ENV{CPACK_IGNORED_FILES})
set(ENV{CPACK_IGNORED_FILES} "$ENV{CPACK_IGNORED_FILES};${REAL_ITEM}")
# Otherwise set the environment variable to the item
- else(DEFINED ENV{CPACK_IGNORED_FILES})
+ else()
set(ENV{CPACK_IGNORED_FILES} "${REAL_ITEM}")
- endif(DEFINED ENV{CPACK_IGNORED_FILES})
-endmacro(add_to_cpack_ignored_files)
+ endif()
+endmacro()
diff --git a/cmake/FindGettext.cmake b/cmake/FindGettext.cmake
deleted file mode 100644
index 0f5502874..000000000
--- a/cmake/FindGettext.cmake
+++ /dev/null
@@ -1,26 +0,0 @@
-# Find the header files, libs, and executables for gettext
-if(NOT WIN32)
- find_path(GETTEXT_INCLUDE libintl.h /usr/include /usr/local/include ${EXTRA_INCLUDE})
- find_library(GETTEXT_LIBRARY intl PATHS /usr/lib /usr/lib64 ${EXTRA_LIBS})
- find_program(GETTEXT_MSGFMT msgfmt PATHS /usr/bin/ /usr/local/bin ${EXTRA_INCLUDE})
- if(GETTEXT_INCLUDE AND GETTEXT_MSGFMT)
- set(GETTEXT_FOUND TRUE)
- if(GETTEXT_LIBRARY)
- set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY})
- endif(GETTEXT_LIBRARY)
- endif(GETTEXT_INCLUDE AND GETTEXT_MSGFMT)
-else(NOT WIN32)
- find_path(GETTEXT_INCLUDE libintl.h)
- find_library(GETTEXT_LIBRARY gnuintl)
- find_program(GETTEXT_MSGFMT msgfmt)
- if(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
- set(GETTEXT_FOUND TRUE)
- set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY})
- endif(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
-endif(NOT WIN32)
-
-# If we found everything we need set variables correctly for lang/CMakeLists.txt to use
-if(GETTEXT_FOUND)
- include_directories("${GETTEXT_INCLUDE}")
- set(GETTEXT_MSGFMT_EXECUTABLE ${GETTEXT_MSGFMT})
-endif(GETTEXT_FOUND)
diff --git a/cmake/ReadFile.cmake b/cmake/ReadFile.cmake
deleted file mode 100644
index be60f1fa7..000000000
--- a/cmake/ReadFile.cmake
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file is external to the read_from_file macro in Anope.cmake in order to
-# get around a possible memory leak in older versions of CMake.
-
-file(READ "${FILE}" RESULT)
-message("${RESULT}")
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 8bb635dcf..37d58b26f 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -1,6 +1,6 @@
-# Only install example.chk and example.conf from this directory
+# Only install cron.example.sh and anope.example.conf from this directory
# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
-set(DATA example.chk botserv.example.conf 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 irc2sql.example.conf stats.standalone.example.conf)
install(FILES ${DATA}
DESTINATION ${CONF_DIR}
)
diff --git a/data/example.conf b/data/anope.example.conf
index 7464244fd..4c73deaa3 100644
--- a/data/example.conf
+++ b/data/anope.example.conf
@@ -1,8 +1,8 @@
/*
- * Example configuration file for Services. After making the appropriate
- * changes to this file, place it in the Services conf directory (as
- * specified in the "configure" script, default /home/username/services/conf)
- * under the name "services.conf".
+ * 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
@@ -53,7 +53,7 @@
* included to indicate whether an option is required:
*
* [REQUIRED]
- * Indicates a directive which must be given. Without it, Services will
+ * Indicates a directive which must be given. Without it, Anope will
* not start.
*
* [RECOMMENDED]
@@ -71,7 +71,7 @@
*
* [DEPRECATED]
* Indicates a directive which will disappear in a future version of
- * Services, usually because its functionality has been either
+ * Anope, usually because its functionality has been either
* superseded by that of other directives or incorporated into the main
* program.
*/
@@ -110,7 +110,7 @@ define
#include
{
type = "executable"
- name = "/usr/bin/wget -q -O - https://some.misconfigured.network.com/services.conf"
+ name = "/usr/bin/wget -q -O - https://some.misconfigured.network.com/anope.conf"
}
/*
@@ -120,7 +120,7 @@ define
* 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 Services
+ * 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
@@ -161,20 +161,22 @@ define
uplink
{
/*
- * The IP or hostname of the IRC server you wish to connect Services to.
- * Usually, you will want to connect Services over 127.0.0.1 (aka localhost).
+ * 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"
/*
- * Enable if Services should connect using IPv6.
+ * The protocol that Anope should use when connecting to the uplink. Can
+ * be set to "ipv4" (the default), "ipv6", or "unix".
*/
- ipv6 = no
+ protocol = "ipv4"
/*
- * Enable if Services should connect using SSL.
+ * Enable if Anope should connect using SSL.
* You must have an SSL module loaded for this to work.
*/
ssl = no
@@ -200,12 +202,12 @@ uplink
/*
* [REQUIRED] Server Information
*
- * This section contains information about the Services server.
+ * This section contains information about the services server.
*/
serverinfo
{
/*
- * The hostname that Services will be seen as, it must have no conflicts with any
+ * 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.
*/
@@ -215,11 +217,11 @@ serverinfo
* The text which should appear as the server's information in /WHOIS and similar
* queries.
*/
- description = "Services for IRC Networks"
+ description = "Anope IRC Services"
/*
- * The local address that Services will bind to before connecting to the remote
- * server. This may be useful for multihomed hosts. If omitted, Services will let
+ * 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
@@ -235,16 +237,16 @@ serverinfo
#id = "00A"
/*
- * The filename containing the Services process ID. The path is relative to the
- * services root directory.
+ * The filename containing the Anope process ID. The path is relative to the
+ * data directory.
*/
- pid = "data/services.pid"
+ pid = "anope.pid"
/*
* The filename containing the Message of the Day. The path is relative to the
- * services root directory.
+ * config directory.
*/
- motd = "conf/services.motd"
+ motd = "motd.txt"
}
/*
@@ -255,83 +257,62 @@ serverinfo
*
* Supported:
* - bahamut
- * - charybdis
* - hybrid
- * - inspircd12
- * - inspircd20
- * - inspircd3 (for 3.x and 4.x)
+ * - inspircd
* - ngircd
* - plexus
* - ratbox
- * - unreal (for 3.2.x)
- * - unreal4 (for 4.x or later)
+ * - solanum
+ * - unrealircd
*/
-module
-{
- name = "inspircd3"
-
- /*
- * Some protocol modules can enforce mode locks server-side. This reduces the spam caused by
- * services immediately reversing mode changes for locked modes.
- *
- * If the protocol module you have loaded does not support this, this setting will have no effect.
- */
- use_server_side_mlock = yes
-
- /*
- * Some protocol modules can enforce topic locks server-side. This reduces the spam caused by
- * services immediately reversing topic changes.
- *
- * If the protocol module you have loaded does not support this, this setting will have no effect.
- */
- use_server_side_topiclock = yes
-}
+module { name = "inspircd" }
/*
* [REQUIRED] Network Information
*
- * This section contains information about the IRC network that Services will be
+ * This section contains information about the IRC network that Anope will be
* connecting to.
*/
networkinfo
{
/*
- * This is the name of the network that Services will be running on.
+ * 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
- * Services being disconnected from the network.
+ * Anope being disconnected from the network. Defaults to 31.
*/
- nicklen = 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
- * Services being disconnected from the network.
+ * Anope being disconnected from the network. Defaults to 10.
*/
- userlen = 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
- * Services being disconnected from the network.
+ * Anope being disconnected from the network. Defaults to 64.
*/
- hostlen = 64
+ #hostlen = 64
/* Set this to the maximum allowed channel length on your network.
+ * Defaults to 32.
*/
- chanlen = 32
+ #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.
+ * Set to 0 to disable. Defaults to 100.
*/
- modelistsize = 100
+ #modelistsize = 100
/*
* Characters allowed in nicknames. This always includes the characters described
* in RFC1459, and so does not need to be set for normal behavior. Changing this to
- * include characters your IRCd doesn't support will cause your IRCd and/or Services
+ * include characters your IRCd doesn't support will cause your IRCd and/or Anope
* to break. Multibyte characters are not supported, nor are escape sequences.
*
* It is recommended you DON'T change this.
@@ -343,7 +324,7 @@ networkinfo
* 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 Services.
+ * disallows could potentially break the IRCd and/or Anope.
*
* It is recommended you DON'T change this.
*/
@@ -368,22 +349,22 @@ networkinfo
}
/*
- * [REQUIRED] Services Options
+ * [REQUIRED] Anope Options
*
- * This section contains various options which determine how Services will operate.
+ * 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
+ * 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. Services use this case map to compare, with
+ * 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.
@@ -396,36 +377,11 @@ options
casemap = "ascii"
/*
- * This key is used to initiate the random number generator. This number
- * MUST be random as you want your passcodes to be random. Don't give this
- * key to anyone! Keep it private!
- *
- * NOTE: If you don't uncomment this or keep the default values, any talented
- * programmer would be able to easily "guess" random strings used to mask
- * information. Be safe, and come up with a 7-digit number.
- *
- * This directive is optional, but highly recommended.
- */
- #seed = 9866235
-
- /*
- * If set, Services will perform more stringent checks on passwords. If this
- * isn't set, Services will only disallow a password if it is the same as the
- * entity (nickname name) with which it is associated. When set, however,
- * Services will also check that the password is at least five
- * characters long, and in the future will probably check other things
- * as well.
- *
- * This directive is optional, but recommended.
- */
- strictpasswords = yes
-
- /*
- * Sets the number of invalid password tries before Services removes a user
+ * Sets the number of invalid password tries before services removes a user
* from the network. If a user enters a number of invalid passwords equal to
- * the given amount for any Services function or combination of functions
- * during a single IRC session (subject to badpasstimeout, below), Services
- * will issues a /KILL for the user. If not given, Services will ignore
+ * the given amount for any services function or combination of functions
+ * during a single IRC session (subject to badpasstimeout, below), services
+ * will issues a /KILL for the user. If not given, services will ignore
* failed password attempts (though they will be logged in any case).
*
* This directive is optional, but recommended.
@@ -446,7 +402,7 @@ options
/*
* Sets the delay between automatic database updates.
*/
- updatetimeout = 5m
+ updatetimeout = 2m
/*
* Sets the delay between checks for expired nicknames and channels.
@@ -461,7 +417,7 @@ options
/*
* Sets the (maximum) frequency at which the timeout list is checked. This,
* combined with readtimeout above, determines how accurately timed events,
- * such as nick kills, occur; it also determines how much CPU time Services
+ * such as nick kills, occur; it also determines how much CPU time services
* will use doing this. Higher values will cause less accurate timing but
* less CPU usage.
*
@@ -474,36 +430,21 @@ options
timeoutcheck = 3s
/*
- * If set, this will allow users to let Services send PRIVMSGs to them
- * instead of NOTICEs. Also see the "msg" option of nickserv:defaults,
- * which also toggles the default communication (PRIVMSG or NOTICE) to
- * use for unregistered users.
- *
- * This is a feature that is against the IRC RFC and should be used ONLY
- * if absolutely necessary.
- *
- * This directive is optional, and not recommended.
- */
- #useprivmsg = yes
-
- /*
- * If set, will force Services to only respond to PRIVMSGs addresses to
- * Nick@ServerName - e.g. NickServ@example.com. This should be used in
- * conjunction with IRCd aliases. This directive is optional.
- *
- * This option will have no effect on some IRCds, such as TS6 IRCds.
+ * If set Anope will tell users to use a server-side alias for messaging
+ * services instead of /msg. The alias for each service defaults to the
+ * bot name but can be configured in the service block.
*/
- #usestrictprivmsg = yes
+ #servicealias = yes
/*
- * If set, Services will only show /stats o to IRC Operators. This directive
+ * 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 Services will
+ * 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.
@@ -518,23 +459,29 @@ options
retrywait = 60s
/*
- * If set, Services will hide commands that users don't have the privilege to execute
+ * If set, services will hide commands that users don't have the privilege to execute
* from HELP output.
*/
hideprivilegedcommands = yes
/*
- * If set, Services will hide commands that users can't execute because they are not
+ * If set, services will hide commands that users can't execute because they are not
* logged in from HELP output.
*/
hideregisteredcommands = yes
+ /*
+ * If set, the maximum difference between an invalid and valid command name to allow
+ * as a suggestion. Defaults to 4.
+ */
+ didyoumeandifference = 4
+
/* The regex engine to use, as provided by the regex modules.
* Leave commented to disable regex matching.
*
* Note for this to work the regex module providing the regex engine must be loaded.
*/
- #regexengine = "regex/pcre"
+ #regexengine = "regex/stdlib"
/*
* A list of languages to load on startup that will be available in /NICKSERV SET LANGUAGE.
@@ -543,7 +490,7 @@ options
*
* Removing .UTF-8 will instead use the default encoding for the language, e.g. iso-8859-1 for western European languages.
*/
- languages = "ca_ES.UTF-8 de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 hu_HU.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 ru_RU.UTF-8 tr_TR.UTF-8"
+ languages = "de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 tr_TR.UTF-8"
/*
* Default language that non- and newly-registered nicks will receive messages in.
@@ -742,7 +689,7 @@ log
{
bot = "Global"
target = "globops"
- admin = "global/* operserv/chankill operserv/mode operserv/kick operserv/akill operserv/s*line operserv/noop operserv/jupe operserv/oline operserv/set operserv/svsnick operserv/svsjoin operserv/svspart nickserv/getpass */drop"
+ admin = "global/* operserv/chankill operserv/mode operserv/kick operserv/akill operserv/s*line operserv/noop operserv/jupe operserv/set operserv/svsnick operserv/svsjoin operserv/svspart nickserv/getpass */drop"
servers = "squit"
users = "oper"
other = "expire/* bados akill/*"
@@ -755,7 +702,6 @@ log
* You may define groups of commands and privileges, as well as who may use them.
*
* This block is recommended, as without it you will be unable to access most oper commands.
- * It replaces the old ServicesRoot directive amongst others.
*
* The command names below are defaults and are configured in the *serv.conf's. If you configure
* additional commands with permissions, such as commands from third party modules, the permissions
@@ -763,25 +709,28 @@ log
*
* Available privileges:
* botserv/administration - Can view and assign private BotServ bots
- * botserv/fantasy - Can use fantasy commands without the FANTASIA privilege
+ * botserv/fantasy - Can use fantasy commands without the FANTASY privilege
* chanserv/administration - Can modify the settings of any channel (including changing of the owner!)
* chanserv/access/list - Can view channel access and akick lists, but not modify them
* chanserv/access/modify - Can modify channel access and akick lists, and use /chanserv enforce
* chanserv/auspex - Can see any information with /CHANSERV INFO
* chanserv/no-register-limit - May register an unlimited number of channels and nicknames
* chanserv/kick - Can kick and ban users from channels through ChanServ
+ * chanserv/drop/override - Allows dropping channels without using a confirmation code
* memoserv/info - Can see any information with /MEMOSERV INFO
* memoserv/set-limit - Can set the limit of max stored memos on any user and channel
* memoserv/no-limit - Can send memos through limits and throttles
- * nickserv/access - Can modify other users access and certificate lists
* 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/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
* 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
+ * protected - Can not be kicked from channels by services
*
* Available commands:
* botserv/bot/del botserv/bot/add botserv/bot/change botserv/set/private
@@ -794,17 +743,16 @@ log
*
* memoserv/sendall memoserv/staff
*
- * nickserv/getpass nickserv/getemail nickserv/suspend nickserv/ajoin
- * nickserv/list
+ * nickserv/getemail nickserv/suspend nickserv/ajoin nickserv/list
*
- * nickserv/saset/autoop nickserv/saset/email nickserv/saset/greet nickserv/saset/password
- * nickserv/saset/display nickserv/saset/kill nickserv/saset/language nickserv/saset/message
- * nickserv/saset/private nickserv/saset/secure nickserv/saset/url nickserv/saset/noexpire
- * nickserv/saset/keepmodes
+ * nickserv/saset/autoop nickserv/saset/display nickserv/saset/email nickserv/saset/greet
+ * nickserv/saset/kill nickserv/saset/keepmodes nickserv/saset/language nickserv/saset/message
+ * nickserv/saset/neverop nickserv/saset/noexpire nickserv/saset/password nickserv/saset/private
+ * nickserv/saset/url
*
* hostserv/set hostserv/del hostserv/list
*
- * global/global
+ * global/global global/queue global/server
*
* operserv/news operserv/stats operserv/kick operserv/exception operserv/seen
* operserv/mode operserv/session operserv/modinfo operserv/ignore operserv/chanlist
@@ -812,7 +760,7 @@ log
* operserv/oper operserv/config operserv/umode operserv/logsearch
* operserv/modload operserv/jupe operserv/set operserv/noop
* operserv/quit operserv/update operserv/reload operserv/restart
- * operserv/shutdown operserv/svs operserv/oline operserv/kill
+ * operserv/shutdown operserv/svs operserv/kill
*
* Firstly, we define 'opertypes' which are named whatever we want ('Network Administrator', etc).
* These can contain commands for oper-only strings (see above) which grants access to that specific command,
@@ -854,8 +802,6 @@ opertype
*
* This can be used to automatically oper users who identify for services operator accounts, and is
* useful for setting modes such as Plexus's user mode +N.
- *
- * Note that some IRCds, such as InspIRCd, do not allow directly setting +o, and this will not work.
*/
#modes = "+o"
}
@@ -866,7 +812,7 @@ opertype
inherits = "Services Operator"
- commands = "botserv/* chanserv/access/list chanserv/drop chanserv/getkey chanserv/saset/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svs operserv/stats operserv/oline operserv/noop operserv/forbid global/*"
+ commands = "botserv/* chanserv/access/list chanserv/drop chanserv/getkey chanserv/saset/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svs operserv/stats operserv/noop operserv/forbid global/*"
privs = "*"
}
@@ -884,10 +830,10 @@ opertype
* After defining different types of operators in the above opertype section, we now define who is in these groups
* through 'oper' blocks, similar to ircd access.
*
- * The default is to comment these out (so NOBODY will have Services access).
+ * The default is to comment these out (so NOBODY will have access).
* You probably want to add yourself and a few other people at minimum.
*
- * As with all permissions, make sure to only give trustworthy people access to Services.
+ * As with all permissions, make sure to only give trustworthy people access.
*/
#oper
@@ -898,7 +844,7 @@ opertype
/* The opertype this person will have */
type = "Services Root"
- /* If set, the user must be an oper on the IRCd to gain their Services
+ /* If set, the user must be an oper on the IRCd to gain their
* oper privileges.
*/
require_oper = yes
@@ -933,7 +879,7 @@ opertype
/*
* [OPTIONAL] Mail Config
*
- * This section contains settings related to the use of e-mail from Services.
+ * This section contains settings related to the use of email from services.
* If the usemail directive is set to yes, unless specified otherwise, all other
* directives are required.
*
@@ -944,7 +890,7 @@ opertype
mail
{
/*
- * If set, this option enables the mail commands in Services. You may choose
+ * If set, this option enables the mail commands in Anope. You may choose
* to disable it if you have no Sendmail-compatible mailer installed. Whilst
* this directive (and entire block) is optional, it is required if
* nickserv:registration is set to mail.
@@ -953,7 +899,7 @@ mail
/*
* This is the command-line that will be used to call the mailer to send an
- * e-mail. It must be called with all the parameters needed to make it
+ * 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.
*
@@ -961,21 +907,24 @@ mail
* 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.
*/
- sendmailpath = "/usr/sbin/sendmail -t"
+ #sendmailpath = "/usr/sbin/sendmail -it"
/*
- * This is the e-mail address from which all the e-mails are to be sent from.
+ * This is the email address from which all the emails are to be sent from.
* It should really exist.
*/
sendfrom = "services@example.com"
/*
* This controls the minimum amount of time a user must wait before sending
- * another e-mail after they have sent one. It also controls the minimum time
- * a user must wait before they can receive another e-mail.
+ * another email after they have sent one. It also controls the minimum time
+ * a user must wait before they can receive another email.
*
- * This feature prevents users from being mail bombed using Services and
+ * This feature prevents users from being mail bombed using services and
* it is highly recommended that it be used.
*
* This directive is optional, but highly recommended.
@@ -983,11 +932,11 @@ mail
delay = 5m
/*
- * If set, Services will not attempt to put quotes around the TO: fields
- * in e-mails.
+ * If set, Anope will not put quotes around the TO: fields
+ * in emails.
*
* This directive is optional, and as far as we know, it's only needed
- * if you are using ESMTP or QMail to send out e-mails.
+ * if you are using ESMTP or QMail to send out emails.
*/
#dontquoteaddresses = yes
@@ -1105,6 +1054,22 @@ mail
}
/*
+ * 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.
+ */
+#module
+{
+ name = "db_atheme"
+
+ /*
+ * The database name db_atheme should use.
+ */
+ database = "atheme.db"
+}
+
+/*
* [RECOMMENDED] db_flatfile
*
* This is the default flatfile database format.
@@ -1120,18 +1085,18 @@ module
/*
* Sets the number of days backups of databases are kept. If you don't give it,
- * or if you set it to 0, Services won't backup the databases.
+ * or if you set it to 0, Anope won't backup the databases.
*
- * NOTE: Services must run 24 hours a day for this feature to work.
+ * NOTE: Anope must run 24 hours a day for this feature to work.
*
* This directive is optional, but recommended.
*/
keepbackups = 3
/*
- * Allows Services to continue file write operations (i.e. database saving)
+ * 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 Services to continue operation under conditions where it might
+ * 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
@@ -1201,7 +1166,7 @@ module
* db_redis.
*
* This module allows using Redis (https://redis.io/) as a database backend.
- * This module requires that m_redis is loaded and configured properly.
+ * This module requires that redis is loaded and configured properly.
*
* Redis 2.8 supports keyspace notifications which allows Redis to push notifications
* to Anope about outside modifications to the database. This module supports this and
@@ -1213,7 +1178,7 @@ module
name = "db_redis"
/*
- * Redis database to use. This must be configured with m_redis.
+ * Redis database to use. This must be configured with redis.
*/
engine = "redis/main"
}
@@ -1221,50 +1186,121 @@ module
/*
* [RECOMMENDED] Encryption modules.
*
- * The encryption modules are used when dealing with passwords. This determines how
- * the passwords are stored in the databases, and does not add any security as
- * far as transmitting passwords over the network goes.
+ * The encryption modules are used when dealing with passwords. This determines
+ * how the passwords are stored in the databases.
*
- * Without any encryption modules loaded users will not be able to authenticate unless
- * there is another module loaded that provides authentication checking, such as
- * m_ldap_authentication or m_sql_authentication.
- *
- * With enc_none, passwords will be stored in plain text, allowing for passwords
- * to be recovered later but it isn't secure and therefore is not recommended.
- *
- * The other encryption modules use one-way encryption, so the passwords can not
- * be recovered later if those are used.
- *
- * The first encryption module loaded is the primary encryption module. All new passwords are
- * encrypted by this module. Old passwords stored in another encryption method are
- * automatically re-encrypted by the primary encryption module on next identify.
+ * The first encryption module loaded is the primary encryption module. All new
+ * passwords are encrypted by this module. Old passwords encrypted with another
+ * encryption method are automatically re-encrypted with the primary encryption
+ * module the next time the user identifies.
+ */
+
+/*
+ * enc_sha2
*
- * enc_md5, enc_sha1, and enc_old are deprecated, and are provided for users
- * to upgrade to a newer encryption module. Do not use them as the primary
- * encryption module. They will be removed in a future release.
+ * Provides support for encrypting passwords using the HMAC-SHA-2 algorithm. See
+ * https://en.wikipedia.org/wiki/SHA-2 and https://en.wikipedia.org/wiki/HMAC
+ * for more information.
+ */
+module
+{
+ name = "enc_sha2"
+
+ /** The sub-algorithm to use. Can be set to sha224 for SHA-224, sha256 for
+ * SHA-256, sha284 for SHA-384, or sha512 for SHA-512. Defaults to sha256.
+ */
+ #algorithm = "sha256"
+}
+
+/*
+ * [EXTRA] enc_argon2
*
+ * Provides support for encrypting passwords using the Argon2 algorithm. See
+ * https://en.wikipedia.org/wiki/Argon2 for more information.
*/
+#module
+{
+ name = "enc_argon2"
-#module { name = "enc_bcrypt" }
-module { name = "enc_sha256" }
+ /** The sub-algorithm to use. Can be set to argon2d for Argon2d, argon2i for
+ * Argon2i, or argon2id for Argon2id. Defaults to argon2id.
+ */
+ #algorithm = "argon2id"
+
+ /** The memory hardness in kibibytes of the Argon2 algorithm. Defaults to
+ * 128 mebibytes.
+ */
+ #memory_cost = 121072
+
+ /** The time hardness (iterations) of the Argon2 algorithm. Defaults to 3.
+ */
+ #time_cost = 3
+
+ /** The amount of parallel threads to use when encrypting passwords.
+ * Defaults to 1.
+ */
+ #parallelism = 1
+
+ /** The length in bytes of an Argon2 hash. Defaults to 32. */
+ #hash_length = 32
+
+ /** The length in bytes of an Argon2 salt. Defaults to 32. */
+ #salt_length = 32
+}
/*
- * When using enc_none, passwords will be stored without encryption. This isn't secure
- * therefore it is not recommended.
+ * enc_bcrypt
+ *
+ * Provides support for encrypting passwords using the Bcrypt algorithm. See
+ * https://en.wikipedia.org/wiki/Bcrypt for more information.
*/
-#module { name = "enc_none" }
+#module
+{
+ name = "enc_bcrypt"
-/* Deprecated encryption modules */
-#module { name = "enc_md5" }
-#module { name = "enc_sha1" }
+ /** The number of Bcrypt rounds to perform on passwords. Can be set to any
+ * number between 10 and 32 but higher numbers are more CPU intensive and
+ * may impact performance.
+ */
+ #rounds = 10
+}
/*
- * enc_old is Anope's previous (broken) MD5 implementation used from 1.4.x to 1.7.16.
- * If your databases were made using that module, load it here to allow conversion to the primary
- * encryption method.
+ * [EXTRA] enc_posix
+ *
+ * Provides verify-only support for passwords encrypted using the POSIX crypt()
+ * function. Load this if you are migrating from another services packages such
+ * as Atheme. See https://en.wikipedia.org/wiki/Crypt_(C) for more information.
+ *
+ * You must load another encryption method before this to re-encrypt passwords
+ * with when a user logs in.
*/
-#module { name = "enc_old" }
+#module { name = "enc_posix" }
+/*
+ * [DEPRECATED] enc_md5, enc_none, enc_old, 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
+ * and will be removed in a future version of Anope. Only load them if you are
+ * upgrading from a previous version of Anope that used them.
+ *
+ * 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.
+ *
+ * You must load another encryption method before this to re-encrypt passwords
+ * with when a user logs in.
+ */
+#module { name = "enc_md5" }
+#module { name = "enc_none" }
+#module { name = "enc_old" }
+#module { name = "enc_sha1" }
+#module { name = "enc_sha256" }
/* Extra (optional) modules. */
include
diff --git a/data/botserv.example.conf b/data/botserv.example.conf
index 9a9bdc3f2..8e7346bd1 100644
--- a/data/botserv.example.conf
+++ b/data/botserv.example.conf
@@ -59,6 +59,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "BS"
}
/*
@@ -183,7 +194,7 @@ module
/*
* The maximum number of entries a single bad words list can have.
*/
- badwordsmax = 32
+ badwordsmax = 50
/*
* If set, BotServ will use case sensitive checking for badwords.
@@ -323,6 +334,7 @@ command { service = "NickServ"; name = "SASET GREET"; command = "nickserv/saset/
privilege
{
name = "GREET"
+ desc = _("Greet message displayed on join")
rank = 40
level = 5
flag = "g"
@@ -333,10 +345,10 @@ privilege
/*
* fantasy
*
- * Allows 'fantasist' commands to be used in channels.
+ * Allows fantasy commands (e.g. !kick) to be used in channels.
*
* Provides the commands:
- * botserv/set/fantasy - Used for enabling or disabling BotServ's fantasist commands.
+ * botserv/set/fantasy - Used for enabling or disabling BotServ's fantasy commands.
*/
module
{
diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf
index 087bfa750..df91f3d92 100644
--- a/data/chanserv.example.conf
+++ b/data/chanserv.example.conf
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "CS"
}
/*
@@ -76,8 +87,6 @@ module
* access level or superior
* - cs_private: Hide the channel from ChanServ's LIST command
* - restricted: Kick/ban users who are restricted from the channel
- * - cs_secure: Enable channel security, requiring the user to be identified with NickServ in
- * order to be considered for being on the access list of the channel
* - secureops: Only allow operator status to be given if the user is on the access list
* - securefounder: Only allow the real founder of the channel to drop the channel, change its
* password, or change the founder or successor
@@ -93,10 +102,10 @@ module
* to be a registered nick, otherwise the channel will be dropped.
* - none: No defaults
*
- * This directive is optional, if left blank, the options will default to keeptopic, peace, cs_secure,
+ * This directive is optional, if left blank, the options will default to keeptopic, peace,
* securefounder, and signkick. If you really want no defaults, use "none" by itself as the option.
*/
- defaults = "keeptopic peace cs_secure securefounder signkick"
+ defaults = "keeptopic peace securefounder signkick"
/*
* The maximum number of channels which may be registered to a single nickname.
@@ -115,15 +124,15 @@ module
/*
* The maximum number of entries on a channel's access list.
- * If not set, the default is 1024. This can be set to 0 for unlimited.
+ * If not set, the default is 1000. This can be set to 0 for unlimited.
*/
- accessmax = 1024
+ accessmax = 1000
/*
* The length of time ChanServ stays in a channel after kicking a user from a channel they are not
* permitted to be in. This only occurs when the user is the only one in the channel.
*/
- inhabit = 15s
+ inhabit = 1m
/*
* Allow only IRC Operators to use ChanServ.
@@ -215,6 +224,7 @@ module
privilege
{
name = "ACCESS_CHANGE"
+ desc = _("Allowed to modify the access list")
rank = 0
level = 10
flag = "f"
@@ -231,6 +241,7 @@ privilege
privilege
{
name = "ACCESS_LIST"
+ desc = _("Allowed to view the access list")
rank = 10
level = 3
flag = "f"
@@ -247,6 +258,7 @@ privilege
privilege
{
name = "AKICK"
+ desc = _("Allowed to use the AKICK command")
rank = 250
level = 10
flag = "K"
@@ -263,6 +275,7 @@ privilege
privilege
{
name = "ASSIGN"
+ desc = _("Allowed to assign/unassign a bot")
rank = 270
level = "founder"
flag = "s"
@@ -279,6 +292,7 @@ privilege
privilege
{
name = "AUTOHALFOP"
+ desc = _("Automatic halfop upon join")
rank = 100
level = 4
flag = "H"
@@ -295,6 +309,7 @@ privilege
privilege
{
name = "AUTOOP"
+ desc = _("Automatic channel operator status upon join")
rank = 210
level = 5
flag = "O"
@@ -311,6 +326,7 @@ privilege
privilege
{
name = "AUTOOWNER"
+ desc = _("Automatic owner upon join")
rank = 330
level = 9999
flag = "Q"
@@ -327,6 +343,7 @@ privilege
privilege
{
name = "AUTOPROTECT"
+ desc = _("Automatic protect upon join")
rank = 240
level = 10
flag = "A"
@@ -343,6 +360,7 @@ privilege
privilege
{
name = "AUTOVOICE"
+ desc = _("Automatic voice on join")
rank = 50
level = 3
flag = "V"
@@ -359,6 +377,7 @@ privilege
privilege
{
name = "BADWORDS"
+ desc = _("Allowed to modify channel badwords list")
rank = 260
level = 10
flag = "K"
@@ -375,6 +394,7 @@ privilege
privilege
{
name = "BAN"
+ desc = _("Allowed to ban users")
rank = 150
level = 4
flag = "b"
@@ -382,7 +402,7 @@ privilege
}
/*
- * FANTASIA privilege.
+ * FANTASY privilege.
*
* Used by botserv/main and chanserv/xop.
*
@@ -390,7 +410,8 @@ privilege
*/
privilege
{
- name = "FANTASIA"
+ name = "FANTASY"
+ desc = _("Allowed to use fantasy commands")
rank = 30
level = 3
flag = "c"
@@ -410,6 +431,7 @@ privilege
privilege
{
name = "FOUNDER"
+ desc = _("Allowed to issue commands restricted to channel founders")
rank = 360
level = 10000
flag = "F"
@@ -427,6 +449,7 @@ privilege
privilege
{
name = "GETKEY"
+ desc = _("Allowed to use GETKEY command")
rank = 180
level = 5
flag = "G"
@@ -444,6 +467,7 @@ privilege
privilege
{
name = "HALFOP"
+ desc = _("Allowed to (de)halfop users")
rank = 120
level = 5
flag = "h"
@@ -461,6 +485,7 @@ privilege
privilege
{
name = "HALFOPME"
+ desc = _("Allowed to (de)halfop themself")
rank = 110
level = 4
flag = "h"
@@ -478,6 +503,7 @@ privilege
privilege
{
name = "INFO"
+ desc = _("Allowed to get full INFO output")
rank = 80
level = 9999
flag = "I"
@@ -495,6 +521,7 @@ privilege
privilege
{
name = "INVITE"
+ desc = _("Allowed to use the INVITE command")
rank = 190
level = 5
flag = "i"
@@ -511,6 +538,7 @@ privilege
privilege
{
name = "KICK"
+ desc = _("Allowed to use the KICK command")
rank = 130
level = 4
flag = "k"
@@ -528,6 +556,7 @@ privilege
privilege
{
name = "MEMO"
+ desc = _("Allowed to read channel memos")
rank = 280
level = 10
flag = "m"
@@ -545,6 +574,7 @@ privilege
privilege
{
name = "MODE"
+ desc = _("Allowed to use the MODE command")
rank = 170
level = 9999
flag = "s"
@@ -561,6 +591,7 @@ privilege
privilege
{
name = "NOKICK"
+ desc = _("Prevents users being kicked by services")
rank = 20
level = 1
flag = "N"
@@ -578,6 +609,7 @@ privilege
privilege
{
name = "OP"
+ desc = _("Allowed to (de)op users")
rank = 230
level = 5
flag = "o"
@@ -595,6 +627,7 @@ privilege
privilege
{
name = "OPME"
+ desc = _("Allowed to (de)op themself")
rank = 220
level = 5
flag = "o"
@@ -612,6 +645,7 @@ privilege
privilege
{
name = "OWNER"
+ desc = _("Allowed to (de)owner users")
rank = 350
level = "founder"
flag = "q"
@@ -629,6 +663,7 @@ privilege
privilege
{
name = "OWNERME"
+ desc = _("Allowed to (de)owner themself")
rank = 340
level = 9999
flag = "q"
@@ -646,6 +681,7 @@ privilege
privilege
{
name = "PROTECT"
+ desc = _("Allowed to (de)protect users")
rank = 310
level = 9999
flag = "a"
@@ -663,6 +699,7 @@ privilege
privilege
{
name = "PROTECTME"
+ desc = _("Allowed to (de)protect themself")
rank = 300
level = 10
flag = "a"
@@ -680,6 +717,7 @@ privilege
privilege
{
name = "SAY"
+ desc = _("Allowed to use SAY and ACT commands")
rank = 90
level = 5
flag = "B"
@@ -699,6 +737,7 @@ privilege
privilege
{
name = "SET"
+ desc = _("Allowed to modify channel settings")
rank = 320
level = 9999
flag = "s"
@@ -716,6 +755,7 @@ privilege
privilege
{
name = "SIGNKICK"
+ desc = _("No signed kick when SIGNKICK LEVEL is used")
rank = 140
level = 9999
flag = "K"
@@ -732,6 +772,7 @@ privilege
privilege
{
name = "TOPIC"
+ desc = _("Allowed to change channel topics")
rank = 160
level = 5
flag = "t"
@@ -748,6 +789,7 @@ privilege
privilege
{
name = "UNBAN"
+ desc = _("Allowed to unban users")
rank = 200
level = 4
flag = "u"
@@ -755,6 +797,23 @@ privilege
}
/*
+ * UNBANME privilege.
+ *
+ * Used by chanserv/unban.
+ *
+ * Users with this permission can unban themself through ChanServ.
+ */
+privilege
+{
+ name = "UNBANME"
+ desc = _("Allowed to unban themself")
+ rank = 200
+ level = 4
+ flag = "U"
+ xop = "HOP"
+}
+
+/*
* VOICE privilege.
*
* Used by chanserv/mode and chanserv/modes.
@@ -765,6 +824,7 @@ privilege
privilege
{
name = "VOICE"
+ desc = _("Allowed to (de)voice users")
rank = 70
level = 4
flag = "v"
@@ -782,6 +842,7 @@ privilege
privilege
{
name = "VOICEME"
+ desc = _("Allowed to (de)voice themself")
rank = 60
level = 3
flag = "v"
@@ -862,7 +923,7 @@ module
/*
* The maximum number of entries on a channel's autokick list.
*/
- autokickmax = 32
+ autokickmax = 50
/*
* The default reason for an autokick if none is given.
@@ -1075,7 +1136,7 @@ module
*
* This directive is optional.
*/
- max = 32
+ max = 50
}
command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; }
@@ -1195,8 +1256,8 @@ command { service = "ChanServ"; name = "SET NOEXPIRE"; command = "chanserv/saset
* A field named misc_description may be given for use with help output.
*/
module { name = "cs_set_misc" }
-command { service = "ChanServ"; name = "SET URL"; command = "chanserv/set/misc"; misc_description = _("Associate a URL with the channel"); }
-command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an E-mail address with the channel"); }
+command { service = "ChanServ"; name = "SET URL"; command = "chanserv/set/misc"; misc_description = _("Associate a URL with the channel"); misc_numeric = 328; }
+command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an email address with the channel"); }
/*
* cs_status
@@ -1208,6 +1269,7 @@ 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; }
/*
* cs_suspend
@@ -1226,7 +1288,7 @@ module
* This directive is optional.
* If not set, the default is never.
*/
- expire = 90d
+ suspendexpire = 90d
/*
* Settings to show to non-opers in ChanServ's INFO output.
diff --git a/data/chanstats.example.conf b/data/chanstats.example.conf
index 338b93306..31e6897a6 100644
--- a/data/chanstats.example.conf
+++ b/data/chanstats.example.conf
@@ -5,7 +5,7 @@
module
{
- name = "m_chanstats"
+ name = "chanstats"
/*
* The name of this engine.
diff --git a/data/example.chk b/data/cron.example.sh
index 119b1ca99..e71928f1c 100644
--- a/data/example.chk
+++ b/data/cron.example.sh
@@ -9,16 +9,16 @@
###############################################################
# Anope binary directory
-ANOPATH=/home/ircd/services/bin
+ANOPATH=/home/ircd/anope/bin
# Anope data directory
-ANODATA=/home/ircd/services/data
+ANODATA=/home/ircd/anope/data
# Name of the pid file
-ANOPIDF=services.pid
+ANOPIDF=anope.pid
# Name of the executable
-ANOPROG=services
+ANOPROG=anope
# Parameters to pass to the executable
ANOARGS=""
diff --git a/data/global.example.conf b/data/global.example.conf
index 90ec350ce..15b6347e6 100644
--- a/data/global.example.conf
+++ b/data/global.example.conf
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "GL"
}
/*
@@ -66,7 +77,7 @@ module
client = "Global"
/*
- * This is the global message that will be sent when Services are being
+ * This is the global message that will be sent when Anope is being
* shutdown/restarted.
*
* This directive is optional.
@@ -74,7 +85,7 @@ module
#globaloncycledown = "Services are restarting, they will be back shortly - please be good while they're gone"
/*
- * This is the global message that will be sent when Services (re)join the
+ * This is the global message that will be sent when Anope (re)joins the
* network.
*
* This directive is optional.
@@ -82,7 +93,7 @@ module
#globaloncycleup = "Services are now back online - have a nice day"
/*
- * If set, Services will hide the IRC Operator's nick in a global
+ * If set, Anope will hide the IRC Operator's nick in a global
* message/notice.
*
* This directive is optional.
@@ -113,3 +124,29 @@ command { service = "Global"; name = "HELP"; command = "generic/help"; }
*/
module { name = "gl_global" }
command { service = "Global"; name = "GLOBAL"; command = "global/global"; permission = "global/global"; }
+
+/*
+ * gl_queue
+ *
+ * Provides the command global/queue.
+ *
+ * Used for queuing messages to send to every online user.
+ */
+module
+{
+ name = "gl_queue"
+
+ /* The maximum number of messages in a message queue. Defaults to 10. */
+ maxqueue = 10
+}
+command { service = "Global"; name = "QUEUE"; command = "global/queue"; permission = "global/queue"; }
+
+/*
+ * gl_server
+ *
+ * Provides the command global/server.
+ *
+ * Used for sending a message to every online user on a server.
+ */
+module { name = "gl_server" }
+command { service = "Global"; name = "SERVER"; command = "global/server"; permission = "global/server"; }
diff --git a/data/hostserv.example.conf b/data/hostserv.example.conf
index e13e8fdd1..4a8354a02 100644
--- a/data/hostserv.example.conf
+++ b/data/hostserv.example.conf
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "HS"
}
/*
@@ -68,7 +79,12 @@ module
/*
* If enabled, vhosts are activated on users immediately when they are set.
*/
- activate_on_set = false
+ activate_on_set = yes
+
+ /*
+ * If enabled, vhosts are activated on users immediately when they log out of an operator account.
+ */
+ activate_on_deoper = yes
}
/*
@@ -110,12 +126,12 @@ module
/*
* Upon nickserv/group, this option syncs the nick's main vHost to the grouped nick.
*/
- syncongroup = false
+ syncongroup = true
/*
* This makes vhosts act as if they are per account.
*/
- synconset = false
+ synconset = true
}
command { service = "HostServ"; name = "GROUP"; command = "hostserv/group"; }
@@ -161,13 +177,13 @@ module
name = "hs_request"
/*
- * If set, Services 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, Services 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
}
diff --git a/data/memoserv.example.conf b/data/memoserv.example.conf
index 9f07ec424..e05e1c14a 100644
--- a/data/memoserv.example.conf
+++ b/data/memoserv.example.conf
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "MS"
}
/*
@@ -83,7 +94,7 @@ module
*
* This directive is optional, but recommended.
*/
- senddelay = 3s
+ senddelay = 30s
}
/*
@@ -146,7 +157,7 @@ module
*
* This directive is optional.
*/
- max = 32
+ max = 50
}
command { service = "MemoServ"; name = "IGNORE"; command = "memoserv/ignore"; }
diff --git a/data/modules.example.conf b/data/modules.example.conf
index b8ae09357..bfc1643ac 100644
--- a/data/modules.example.conf
+++ b/data/modules.example.conf
@@ -3,7 +3,7 @@
*
* The following blocks are used to load all non-core modules, including 3rd-party modules.
* Modules can be prevented from loading by commenting out the line, other modules can be added by
- * adding a module block. These modules will be loaded prior to Services connecting to your network.
+ * adding a module block. These modules will be loaded prior to Anope connecting to your network.
*
* Note that some of these modules are labeled EXTRA, and must be enabled prior to compiling by
* running the 'extras' script on Linux and UNIX.
@@ -19,14 +19,14 @@
module { name = "help" }
/*
- * m_dns
+ * dns
*
* Adds support for the DNS protocol. By itself this module does nothing useful,
- * but other modules such as m_dnsbl and os_dns require this.
+ * but other modules such as dnsbl and os_dns require this.
*/
#module
{
- name = "m_dns"
+ name = "dns"
/*
* The nameserver to use for resolving hostnames, must be an IP or a resolver configuration file.
@@ -59,7 +59,7 @@ module { name = "help" }
* SOA record information.
*/
- /* E-mail address of the DNS administrator. */
+ /* Email address of the DNS administrator. */
admin = "admin@example.com"
/* This should be the names of the public facing nameservers serving the records. */
@@ -80,7 +80,7 @@ module { name = "help" }
}
/*
- * m_dnsbl
+ * dnsbl
*
* Allows configurable DNS blacklists to check connecting users against. If a user
* is found on the blacklist they will be immediately banned. This is a crucial module
@@ -88,17 +88,17 @@ module { name = "help" }
*/
#module
{
- name = "m_dnsbl"
+ name = "dnsbl"
/*
- * If set, Services will check clients against the DNSBLs when services connect to its uplink.
+ * If set, Anope will check clients against the DNSBLs when services connect to its uplink.
* This is not recommended, and on large networks will open a very large amount of DNS queries.
* Whilst services are not drastically affected by this, your nameserver/DNSBL might care.
*/
check_on_connect = no
/*
- * If set, Services will check clients when coming back from a netsplit. This can cause a large number
+ * If set, Anope will check clients when coming back from a netsplit. This can cause a large number
* of DNS queries open at once. Whilst services are not drastically affected by this, your nameserver/DNSBL
* might care.
*/
@@ -179,19 +179,19 @@ module { name = "help" }
}
/*
- * m_helpchan
+ * helpchan
*
* Gives users who are op in the specified help channel usermode +h (helpop).
*/
#module
{
- name = "m_helpchan"
+ name = "helpchan"
helpchannel = "#help"
}
/*
- * m_httpd
+ * httpd
*
* Allows services to serve web pages. By itself, this module does nothing useful.
*
@@ -200,7 +200,7 @@ module { name = "help" }
*/
#module
{
- name = "m_httpd"
+ name = "httpd"
httpd
{
@@ -233,13 +233,13 @@ module { name = "help" }
}
/*
- * m_ldap [EXTRA]
+ * ldap [EXTRA]
*
* This module allows other modules to use LDAP. By itself, this module does nothing useful.
*/
#module
{
- name = "m_ldap"
+ name = "ldap"
ldap
{
@@ -254,14 +254,14 @@ module { name = "help" }
}
/*
- * m_ldap_authentication [EXTRA]
+ * ldap_authentication
*
* This module allows many commands such as IDENTIFY, RELEASE, RECOVER, GHOST, etc. use
- * LDAP to authenticate users. Requires m_ldap.
+ * LDAP to authenticate users. Requires ldap.
*/
#module
{
- name = "m_ldap_authentication"
+ name = "ldap_authentication"
/*
* The distinguished name used for searching for users's accounts.
@@ -314,16 +314,16 @@ module { name = "help" }
}
/*
- * m_ldap_oper [EXTRA]
+ * ldap_oper
*
* This module dynamically ties users to Anope opertypes when they identify
- * via LDAP group membership. Requires m_ldap.
+ * via LDAP group membership. Requires ldap.
*
- * Note that this doesn't give the user privileges on the IRCd, only in Services.
+ * Note that this doesn't give the user privileges on the IRCd, only in Anope.
*/
#module
{
- name = "m_ldap_oper"
+ name = "ldap_oper"
/*
* An optional binddn to use when searching for groups.
@@ -355,13 +355,13 @@ module { name = "help" }
}
/*
- * m_mysql [EXTRA]
+ * mysql [EXTRA]
*
* This module allows other modules to use MySQL.
*/
#module
{
- name = "m_mysql"
+ name = "mysql"
mysql
{
@@ -372,17 +372,18 @@ module { name = "help" }
username = "anope"
password = "mypassword"
port = 3306
+ socket = ""
}
}
/*
- * m_redis
+ * redis
*
* This module allows other modules to use Redis.
*/
#module
{
- name = "m_redis"
+ name = "redis"
/* A redis database */
redis
@@ -401,47 +402,61 @@ module { name = "help" }
}
/*
- * m_regex_pcre [EXTRA]
+ * regex_pcre2 [EXTRA]
*
- * Provides the regex engine regex/pcre, which uses version 1 of the Perl Compatible Regular
- * Expressions library. This can not be loaded at the same time as the m_regex_pcre2 module.
+ * Provides the regex engine regex/pcre, which uses version 2 of the Perl Compatible Regular
+ * Expressions library.
*/
-#module { name = "m_regex_pcre" }
+#module { name = "regex_pcre2" }
/*
- * m_regex_pcre2 [EXTRA]
+ * regex_posix [EXTRA]
*
- * Provides the regex engine regex/pcre, which uses version 2 of the Perl Compatible Regular
- * Expressions library. This can not be loaded at the same time as the m_regex_pcre module.
+ * Provides the regex engine regex/posix, which uses the POSIX compliant regular expressions.
*/
-#module { name = "m_regex_pcre2" }
+#module { name = "regex_posix" }
/*
- * m_regex_posix [EXTRA]
+ * regex_stdlib
*
- * Provides the regex engine regex/posix, which uses the POSIX compliant regular expressions.
- * This is likely the only regex module you will not need extra libraries for.
+ * Provides the regex engine regex/stdlib, which uses the regular expression library that is part of
+ * the C++ standard library.
*/
-#module { name = "m_regex_posix" }
+module
+{
+ name = "regex_stdlib"
+
+ /*
+ * The syntax scheme to use. Can be set to awk to use the regular expression grammar used by the
+ * awk utility in POSIX, basic to use the basic POSIX regular expression grammar, ecmascript to
+ * use the modified ECMAScript regular expression grammar, egrep to use the regular expression
+ * grammar used by the grep utility with the -E option in POSIX, extended to use the extended
+ * POSIX regular expression grammar, or grep to use the regular expression grammar used by the
+ * grep utility in POSIX.
+ *
+ * See https://en.cppreference.com/w/cpp/regex/syntax_option_type for more information.
+ */
+ syntax = "ecmascript"
+}
/*
- * m_regex_tre [EXTRA]
+ * regex_tre [EXTRA]
*
* Provides the regex engine regex/tre, which uses the TRE regex library.
*/
-#module { name = "m_regex_tre" }
+#module { name = "regex_tre" }
/*
- * m_rewrite
+ * rewrite
*
* Allows rewriting commands sent to/from clients.
*/
-#module { name = "m_rewrite" }
+#module { name = "rewrite" }
#command
{
service = "ChanServ"; name = "CLEAR"; command = "rewrite"
- /* Enable m_rewrite. */
+ /* Enable rewrite. */
rewrite = true
/* Source message to match. A $ can be used to match anything. */
@@ -462,7 +477,7 @@ module { name = "help" }
}
/*
- * m_proxyscan
+ * proxyscan
*
* This module allows you to scan connecting clients for open proxies.
* Note that using this will allow users to get the IP of your services.
@@ -476,7 +491,7 @@ module { name = "help" }
*/
#module
{
- name = "m_proxyscan"
+ name = "proxyscan"
/*
* The target IP services tells the proxy to connect back to. This must be a publicly
@@ -544,38 +559,39 @@ module { name = "help" }
}
/*
- * m_sasl
+ * sasl
*
- * Some IRCds allow "SASL" authentication to let users identify to Services
- * during the IRCd user registration process. If this module is loaded, Services will allow
+ * Some IRCds allow "SASL" authentication to let users identify to services
+ * during the IRCd user registration process. If this module is loaded, Anope will allow
* authenticating users through this mechanism. Supported mechanisms are:
* PLAIN, EXTERNAL.
*/
-module { name = "m_sasl" }
+module { name = "sasl" }
/*
- * m_ssl_gnutls [EXTRA]
+ * ssl_gnutls [EXTRA]
*
* This module provides SSL services to Anope using GnuTLS, for example to
* connect to the uplink server(s) via SSL.
*
- * You may only load either m_ssl_gnutls or m_ssl_openssl, but not both.
+ * You may only load either ssl_gnutls or ssl_openssl, but not both.
*/
#module
{
- name = "m_ssl_gnutls"
+ name = "ssl_gnutls"
/*
- * An optional certificate and key for m_ssl_gnutls to give to the uplink.
+ * An optional certificate and key for ssl_gnutls to give to the uplink. All
+ * paths are relative to the config directory.
*
* You can generate your own certificate and key pair by using:
*
- * certtool --generate-privkey --bits 2048 --outfile anope.key
- * certtool --generate-self-signed --load-privkey anope.key --outfile anope.crt
+ * certtool --generate-privkey --bits 2048 --outfile privkey.pem
+ * certtool --generate-self-signed --load-privkey privkey.pem --outfile fullchain.pem
*
*/
- cert = "data/anope.crt"
- key = "data/anope.key"
+ cert = "fullchain.pem"
+ key = "privkey.pem"
/*
* Diffie-Hellman parameters to use when acting as a server. This is only
@@ -588,53 +604,55 @@ module { name = "m_sasl" }
* certtool --generate-dh-params --bits 2048 --outfile dhparams.pem
*
*/
-# dhparams = "data/dhparams.pem"
+ #dhparams = "dhparams.pem"
}
/*
- * m_ssl_openssl [EXTRA]
+ * ssl_openssl [EXTRA]
*
* This module provides SSL services to Anope using OpenSSL, for example to
* connect to the uplink server(s) via SSL.
*
- * You may only load either m_ssl_openssl or m_ssl_gnutls, but not both.
+ * You may only load either ssl_openssl or ssl_gnutls, but not both.
*
*/
#module
{
- name = "m_ssl_openssl"
+ name = "ssl_openssl"
/*
- * An optional certificate and key for m_ssl_openssl to give to the uplink.
+ * An optional certificate and key for ssl_openssl to give to the uplink.
+ * All paths are relative to the config directory.
*
* You can generate your own certificate and key pair by using:
*
- * openssl genrsa -out anope.key 2048
- * openssl req -new -x509 -key anope.key -out anope.crt -days 1095
+ * openssl genrsa -out privkey.pem 2048
+ * openssl req -new -x509 -key privkey.pem -out fullchain.pem -days 1095
*/
- cert = "data/anope.crt"
- key = "data/anope.key"
+ cert = "fullchain.pem"
+ key = "privkey.pem"
/*
- * As of 2014 SSL 3.0 is considered insecure, but it might be enabled
- * on some systems by default for compatibility reasons.
- * You can use the following option to enable or disable it explicitly.
- * Leaving this option not set defaults to the default system behavior.
+ * If you wish to increase security you can disable support for older
+ * versions of TLS with no known vulnerabilities but that provide less
+ * security. For your security SSLv2 and SSLv3 are always disabled.
*/
- #sslv3 = no
+ #tlsv10 = no
+ #tlsv11 = no
+ #tlsv12 = yes
}
/*
- * m_sql_authentication [EXTRA]
+ * sql_authentication
*
* This module allows authenticating users against an external SQL database using a custom
* query.
*/
#module
{
- name = "m_sql_authentication"
+ name = "sql_authentication"
- /* SQL engine to use. Should be configured elsewhere with m_mysql, m_sqlite, etc. */
+ /* SQL engine to use. Should be configured elsewhere with mysql, sqlite, etc. */
engine = "mysql/main"
/* Query to execute to authenticate. A non empty result from this query is considered a success,
@@ -676,7 +694,7 @@ module { name = "m_sasl" }
}
/*
- * m_sql_log [EXTRA]
+ * 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
@@ -693,24 +711,24 @@ module { name = "m_sasl" }
* it if it doesn't exist. This module does not create any indexes (keys)
* on the table and it is recommended you add them yourself as necessary.
*/
-#module { name = "m_sql_log" }
+#module { name = "sql_log" }
/*
- * m_sql_oper [EXTRA]
+ * 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.
*/
#module
{
- name = "m_sql_oper"
+ name = "sql_oper"
- /* SQL engine to use. Should be configured elsewhere with m_mysql, m_sqlite, etc. */
+ /* SQL engine to use. Should be configured elsewhere with mysql, sqlite, etc. */
engine = "mysql/main"
/* Query to execute to determine if a user should have operator privileges.
* A field named opertype must be returned in order to link the user to their oper type.
- * The oper types must be configured earlier in services.conf.
+ * The oper types must be configured earlier in anope.conf.
*
* If a field named modes is returned from this query then those modes are set on the user.
* Without this, only a simple +o is sent.
@@ -722,13 +740,13 @@ module { name = "m_sasl" }
}
/*
- * m_sqlite [EXTRA]
+ * sqlite [EXTRA]
*
* This module allows other modules to use SQLite.
*/
#module
{
- name = "m_sqlite"
+ name = "sqlite"
/* A SQLite database */
sqlite
@@ -737,7 +755,7 @@ module { name = "m_sasl" }
name = "sqlite/main"
/* The database name, it will be created if it does not exist. */
- database = "anope.db"
+ database = "anope.sqlite"
}
}
@@ -748,40 +766,61 @@ module { name = "m_sasl" }
* as they could over IRC. If you are using the default configuration you should be able to access
* this panel by visiting http://127.0.0.1:8080 in your web browser from the machine Anope is running on.
*
- * This module requires m_httpd.
+ * This module requires httpd.
*/
#module
{
name = "webcpanel"
/* Web server to use. */
- server = "httpd/main";
+ server = "httpd/main"
- /* Template to use. */
- template = "default";
+ /*
+ * The directory containing the webcpanel templates. This is relative to the
+ * data directory.
+ */
+ template_dir = "webcpanel/templates/default"
/* Page title. */
- title = "Anope IRC Services";
+ title = "Anope IRC Services"
}
/*
- * m_xmlrpc
+ * 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 (m_xmlrpc_main) to receive and send XMLRPC queries.
+ * By itself this module does nothing, but allows other modules (rpc_main) to receive and send JSON-RPC queries.
+ *
+ * IMPORTANT: this can not be loaded at the same time as the xmlrpc module.
+ */
+#module
+{
+ name = "jsonrpc"
+
+ /* Web service to use. Requires httpd. */
+ server = "httpd/main"
+}
+
+/*
+ * 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.
+ *
+ * IMPORTANT: this can not be loaded at the same time as the jsonrpc module.
*/
#module
{
- name = "m_xmlrpc"
+ name = "xmlrpc"
- /* Web service to use. Requires m_httpd. */
+ /* Web service to use. Requires httpd. */
server = "httpd/main"
}
/*
- * m_xmlrpc_main
+ * rpc_main
*
- * Adds the main XMLRPC core functions.
- * Requires m_xmlrpc.
+ * Adds the main RPC core functions.
+ * Requires xmlrpc.
*/
-#module { name = "m_xmlrpc_main" }
+#module { name = "rpc_main" }
diff --git a/data/nickserv.example.conf b/data/nickserv.example.conf
index ef3f40855..ad41ba37f 100644
--- a/data/nickserv.example.conf
+++ b/data/nickserv.example.conf
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "NS"
}
/*
@@ -66,17 +77,20 @@ module
client = "NickServ"
/*
- * Force users to give an e-mail address when they register a nick.
+ * Requires users to give an email address when they register a nick.
*
- * This directive defaults to "yes" and is recommended to be enabled. This is required if e-mail registration is enabled.
+ * This directive defaults to "yes" and is recommended to be enabled.
*/
forceemail = yes
/*
* Require users who change their email address to confirm they
* own their new email.
+ *
+ * If {ns_register}:registration is set to mail then this defaults
+ * to yes. Otherwise, it defaults to no.
*/
- confirmemailchanges = no
+ #confirmemailchanges = yes
/*
* A message sent to users on connect if they use an unregistered nick. %n will be replaced with the user's nickname.
@@ -96,10 +110,8 @@ module
* option and the killprotect option must be specified with this one
* - kill_immed: Kill nick immediately if not identified, this one overrides both the killprotect
* and kill_quick options and the killprotect option must be specified with this one
- * - ns_secure: Enable nickname security, requiring the nick's password before any operations
- * can be done on it
* - ns_private: Hide the nick from NickServ's LIST command
- * - hide_email: Hide the nick's e-mail address from NickServ's INFO command
+ * - hide_email: Hide the nick's email address from NickServ's INFO command
* - hide_mask: Hide the nick's last or current user@host from NickServ's INFO command
* - hide_status: Hide the nick's services operator access status from NickServ's INFO command
* - hide_quit: Hide the nick's last quit message from NickServ's INFO command
@@ -107,38 +119,38 @@ module
* - memo_receive: Notify user if they have a new memo as soon as it's received
* - memo_mail: Notify user if they have a new memo by mail
* - autoop: User will be automatically opped in channels they enter and have access to
- * - msg: Services messages will be sent as PRIVMSGs instead of NOTICEs, requires
- * options:useprivmsg to be enabled as well
+ * - neverop: User can not be added to access lists
+ * - msg: Messages will be sent as PRIVMSGs instead of NOTICEs
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
*
- * This directive is optional, if left blank, the options will default to ns_secure, memo_signon, and
+ * 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.
*/
- defaults = "killprotect ns_secure ns_private hide_email hide_mask memo_signon memo_receive autoop"
+ defaults = "killprotect ns_private hide_email hide_mask memo_signon memo_receive autoop"
/*
* The minimum length of time between consecutive uses of NickServ's REGISTER command. This
* directive is optional, but recommended. If not set, this restriction will be disabled.
*/
- regdelay = 30s
+ regdelay = 5m
/*
* The length of time before a nick's registration expires.
*
- * This directive is optional, but recommended. If not set, the default is 21 days.
+ * This directive is optional, but recommended. If not set, the default is one year.
*/
- expire = 21d
+ expire = 1y
/*
- * Prevents the use of the ACCESS and CERT (excluding their LIST subcommand), DROP, FORBID, SUSPEND,
- * GETPASS and SET PASSWORD commands by services operators on other services operators.
+ * Prevents the use of the ACCESS and CERT (excluding their LIST subcommand), DROP, FORBID, SUSPEND
+ * and SET PASSWORD commands by services operators on other services operators.
*
* This directive is optional, but recommended.
*/
secureadmins = yes
/*
- * If set, Services will set the channel modes a user has access to upon identifying, assuming
+ * If set, Anope will set the channel modes a user has access to upon identifying, assuming
* they are not already set.
*
* This directive is optional.
@@ -146,14 +158,14 @@ module
modeonid = yes
/*
- * If set, Services will set these user modes on any user who identifies.
+ * If set, Anope will set these user modes on any user who identifies.
*
* This directive is optional.
*/
#modesonid = "+R"
/*
- * If set, Services will not show netsplits in the last quit message field
+ * If set, Anope will not show netsplits in the last quit message field
* of NickServ's INFO command.
*/
hidenetsplitquit = no
@@ -167,7 +179,7 @@ module
/*
* If set, forbids the registration of nicks that contain an existing
- * nick with Services access. For example, if Tester is a Services Oper,
+ * nick with services access. For example, if Tester is a Services Oper,
* you can't register NewTester or Tester123 unless you are an IRC
* Operator.
*
@@ -180,39 +192,56 @@ module
#restrictopernicks = yes
/*
- * The username, and possibly hostname, used for fake users created when Services needs to
+ * The username, and possibly hostname, used for fake users created when Anope needs to
* hold a nickname.
*/
enforceruser = "enforcer"
enforcerhost = "services.host"
/*
- * The length of time Services hold nicknames.
+ * The length of time Anope should hold nicknames for.
*
* This directive is optional, but recommended. If not set it defaults to 1 minute.
*/
releasetimeout = 1m
/*
- * When a user's nick is forcibly changed to enforce a "nick kill", their new nick will start
- * with this value. The rest will be made up of 6 or 7 digits.
- * Make sure this is a valid nick and Nicklen+7 is not longer than the allowed Nicklen on your ircd.
+ * When a user's nick is forcibly changed to enforce nickname protection their new
+ * nick will be based on this value. Any # in the value will be replaced with a random
+ * number. If your IRCd has support for unique identifiers you can also set this to an
+ * empty string to change a user's nick to their unique identifier.
+ *
+ * Make sure this is a valid nick and that it is is not longer than the maximum nick
+ * length on your IRCd.
*
- * This directive is optional. If not set it defaults to "Guest"
+ * This directive is optional. If not set it defaults to "Guest####"
*/
- guestnickprefix = "Guest"
+ guestnick = "Guest####"
/*
- * If set, Services do not allow ownership of nick names, only ownership of accounts.
+ * If set, Anope does not allow ownership of nick names, only ownership of accounts.
*/
nonicknameownership = no
/*
+ * The minimum length of passwords
+ *
+ * This directive is optional. If not set it defaults to 10.
+ */
+ minpasslen = 10
+
+ /*
* The maximum length of passwords
*
- * This directive is optional. If not set it defaults to 32.
+ * This directive is optional. If not set it defaults to 50.
+ */
+ 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.
*/
- passlen = 32
+ preservedisplay = no
}
/*
@@ -241,33 +270,6 @@ command_group
command { service = "NickServ"; name = "HELP"; command = "generic/help"; }
/*
- * ns_access
- *
- * Provides the command nickserv/access.
- *
- * Used for configuring what hosts have access to your account.
- */
-module
-{
- name = "ns_access"
-
- /*
- * The maximum number of entries allowed on a nickname's access list.
- * If not set, the default is 32. This number cannot be set to 0.
- */
- accessmax = 32
-
- /*
- * If set, Services will add the usermask of registering users to the access list of their
- * newly created account. If not set, users will always have to identify to NickServ before
- * being recognized, unless they manually add an address to the access list of their account.
- * This directive is optional.
- */
- addaccessonreg = no
-}
-command { service = "NickServ"; name = "ACCESS"; command = "nickserv/access"; }
-
-/*
* ns_ajoin
*
* Provides the command nickserv/ajoin.
@@ -294,6 +296,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; }
/*
* ns_cert
@@ -307,6 +310,12 @@ module
name = "ns_cert"
/*
+ * Should users who are connected with a SSL client certificate have its fingerprint be added to
+ * their account when they register. Defaults to yes.
+ */
+ automatic = yes
+
+ /*
* The maximum number of entries allowed on a nickname's certificate fingerprint list.
* The default is 5. This number cannot be set to 0.
*/
@@ -335,18 +344,6 @@ module { name = "ns_getemail" }
command { service = "NickServ"; name = "GETEMAIL"; command = "nickserv/getemail"; permission = "nickserv/getemail"; group = "nickserv/admin"; }
/*
- * ns_getpass
- *
- * Provides the command nickserv/getpass.
- *
- * Used for getting users passwords.
- *
- * Requires no encryption is being used.
- */
-#module { name = "ns_getpass" }
-#command { service = "NickServ"; name = "GETPASS"; command = "nickserv/getpass"; permission = "nickserv/getpass"; }
-
-/*
* ns_group
*
* Provides the commands nickserv/group, nickserv/glist, and nickserv/ungroup.
@@ -362,7 +359,7 @@ module
*
* This directive is optional, but recommended. If not set or set to 0, no limits will be applied.
*/
- maxaliases = 16
+ maxaliases = 10
/*
* If set, the NickServ GROUP command won't allow any group changes. This is recommended to
@@ -456,7 +453,7 @@ module
name = "ns_recover"
/*
- * If set, Services will svsnick and svsjoin users who use the recover
+ * If set, Anope will svsnick and svsjoin users who use the recover
* command on an identified user to the nick and channels of the recovered user.
*
* This directive is optional.
@@ -464,9 +461,10 @@ module
restoreonrecover = yes
}
command { service = "NickServ"; name = "RECOVER"; command = "nickserv/recover"; }
-# Uncomment below to emulate 1.8's behavior of ghost and release.
-#command { service = "NickServ"; name = "GHOST"; command = "nickserv/recover"; }
-#command { service = "NickServ"; name = "RELEASE"; 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; }
/*
* ns_register
@@ -499,7 +497,7 @@ module
*
* This directive is optional.
*/
- #nickregdelay = 30s
+ nickregdelay = 15s
/*
* The length of time a user using an unconfirmed account has
@@ -530,24 +528,11 @@ command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpas
* 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/kill, nickserv/saset/kill - Used for configuring nickname protection.
- * nickserv/set/language, nickserv/saset/language - Used for configuring what language services use.
- * nickserv/set/message, nickserv/saset/message - Used to configure how services send messages to you.
- * nickserv/set/password, nickserv/saset/password - Used for changing a users password.
- * nickserv/set/secure, nickserv/saset/secure - Used for configuring whether a user can identify by simply being recognized by nickserv/access.
+ * 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.
*/
-module
-{
- name = "ns_set"
-
- /*
- * Allow the use of the IMMED option in the NickServ SET KILL command.
- *
- * This directive is optional.
- */
- #allowkillimmed = yes
-}
+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"; }
@@ -561,26 +546,82 @@ command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/sase
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"; }
+
+/*
+ * ns_set_keepmodes
+ *
+ * Provides the command nickserv/set/keepmodes and nickserv/saset/keepmodes.
+ *
+ * Allows configuring services to keep user modes across logins.
+ */
+module
+{
+ name = "ns_set_keepmodes"
+
+ /*
+ * Anope will try to not restore user modes that aren't settable by users. However, if
+ * you have modes that you don't want to be automatically restored you can list them
+ * here.
+ */
+ #norestore = "ABCabc"
+}
command { service = "NickServ"; name = "SET KEEPMODES"; command = "nickserv/set/keepmodes"; }
command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/saset/keepmodes"; permission = "nickserv/saset/keepmodes"; }
+/*
+ * ns_set_kill
+ *
+ * Provides the commands nickserv/set/kill and kickserv/saset/kill.
+ *
+ * Used for configuring nickname protection.
+ */
+module
+{
+ name = "ns_set_kill"
+
+ /*
+ * Allow the use of the IMMED option in the NickServ SET KILL command.
+ *
+ * This directive is optional.
+ */
+ #allowkillimmed = yes
+}
+
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
+/*
+ * ns_set_language
+ *
+ * Provides the command nickserv/set/language and nickserv/saset/language.
+ *
+ * Allows configuring the language that services uses.
+ */
+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"; }
-command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
-command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
-
-command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
-command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
-
-command { service = "NickServ"; name = "SET SECURE"; command = "nickserv/set/secure"; }
-command { service = "NickServ"; name = "SASET SECURE"; command = "nickserv/saset/secure"; permission = "nickserv/saset/secure"; }
-
-command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
-
+/*
+ * ns_set_message
+ *
+ * Provides the commands nickserv/set/message and nickserv/saset/message.
+ *
+ * Allows users to let services send them PRIVMSGs instead of NOTICEs.
+ *
+ * This might cause problems with badly written clients as the IRC RFC
+ * requires that automatic responses to a PRIVMSG use a NOTICE to avoid
+ * message loops. Only enable this if you are sure this can not happen.
+ */
+#module { name = "ns_set_message" }
+#command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
+#command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
/*
* ns_set_misc
@@ -595,21 +636,10 @@ command { service = "NickServ"; name = "SET URL"; command = "nickserv/set/misc";
command { service = "NickServ"; name = "SASET URL"; command = "nickserv/saset/misc"; misc_description = _("Associate a URL with this account"); permission = "nickserv/saset/url"; group = "nickserv/admin"; }
#command { service = "NickServ"; name = "SET DISCORD"; command = "nickserv/set/misc"; misc_description = _("Associate a Discord account with your account"); }
#command { service = "NickServ"; name = "SASET DISCORD"; command = "nickserv/saset/misc"; misc_description = _("Associate a Discord account with this account"); permission = "nickserv/saset/discord"; group = "nickserv/admin"; }
-#command { service = "NickServ"; name = "SET FACEBOOK"; command = "nickserv/set/misc"; misc_description = _("Associate a Facebook URL with your account"); }
-#command { service = "NickServ"; name = "SASET FACEBOOK"; command = "nickserv/saset/misc"; misc_description = _("Associate a Facebook URL with this account"); permission = "nickserv/saset/facebook"; group = "nickserv/admin"; }
#command { service = "NickServ"; name = "SET MASTODON"; command = "nickserv/set/misc"; misc_description = _("Associate a Mastodon account with your account"); }
#command { service = "NickServ"; name = "SASET MASTODON"; command = "nickserv/saset/misc"; misc_description = _("Associate a Mastodon account with this account"); permission = "nickserv/saset/mastodon"; group = "nickserv/admin"; }
-
-
-/*
- * ns_status
- *
- * Provides the nickserv/status command.
- *
- * Used to determine if a user is recognized or identified by services.
- */
-module { name = "ns_status" }
-command { service = "NickServ"; name = "STATUS"; command = "nickserv/status"; }
+#command { service = "NickServ"; name = "SET TIMEZONE"; command = "nickserv/set/misc"; misc_description = _("Associate a time zone with your account"); }
+#command { service = "NickServ"; name = "SASET TIMEZONE"; command = "nickserv/saset/misc"; misc_description = _("Associate a time zone with this account"); permission = "nickserv/saset/timezone"; group = "nickserv/admin"; }
/*
* ns_suspend
@@ -665,7 +695,7 @@ command { service = "NickServ"; name = "UPDATE"; command = "nickserv/update"; }
name = "ns_maxemail"
/*
- * The limit to how many registered nicks can use the same e-mail address. If set to 0 or left
+ * 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.
*/
diff --git a/data/operserv.example.conf b/data/operserv.example.conf
index 9856d5b2d..fd7ae6c95 100644
--- a/data/operserv.example.conf
+++ b/data/operserv.example.conf
@@ -49,6 +49,17 @@ service
* Prefixes may be given to the channels in the form of mode characters or prefix symbols.
*/
#channels = "@#services,#mychan"
+
+ /*
+ * The server alias that can be used to securely message this service. If
+ * your IRC server does not have an alias for this service you can set this
+ * to an empty string to tell users to use /msg instead.
+ *
+ * This setting is ignored when options:servicealias is disabled.
+ *
+ * Defaults to the nick of the service if not set.
+ */
+ #alias = "OS"
}
/*
@@ -75,7 +86,7 @@ module
sqlineexpiry = 30d
/*
- * If set, this option will make Services send an AKILL command immediately after it has been
+ * If set, this option will make Anope send an AKILL command immediately after it has been
* added with AKILL ADD. This eliminates the need for killing the user after the AKILL has
* been added.
*
@@ -84,7 +95,7 @@ module
akillonadd = yes
/*
- * If set, this option will make Services send an (SVS)KILL command immediately after SNLINE ADD.
+ * If set, this option will make Anope send an (SVS)KILL command immediately after SNLINE ADD.
* This eliminates the need for killing the user after the SNLINE has been added.
*
* This directive is optional.
@@ -92,7 +103,7 @@ module
killonsnline = yes
/*
- * If set, this option will make Services send an (SVS)KILL command immediately after SQLINE ADD.
+ * If set, this option will make Anope send an (SVS)KILL command immediately after SQLINE ADD.
* This eliminates the need for killing the user after the SQLINE has been added.
*
* This directive is optional.
@@ -167,7 +178,7 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
name = "os_defcon"
/*
- * Default DefCon level (1-5) to use when starting Services up. Level 5 constitutes normal operation
+ * Default DefCon level (1-5) to use when starting Anope up. Level 5 constitutes normal operation
* while level 1 constitutes the most restrictive operation. If this setting is left out or set to
* 0, DefCon will be disabled and the rest of this block will be ignored.
*/
@@ -184,8 +195,8 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
* - forcechanmodes: Forces all channels to have the modes given in the later chanmodes directive
* - reducedsessions: Reduces the session limit to the value given in the later sessionlimit directive
* - nonewclients: KILL any new clients trying to connect
- * - operonly: Services will ignore all non-IRCops
- * - silentoperonly: Services will silently ignore all non-IRCops
+ * - operonly: Ignore all non-IRCops
+ * - silentoperonly: Silently ignore all non-IRCops
* - akillnewclients: AKILL any new clients trying to connect
* - nonewmemos: No new memos will be sent to block MemoServ attacks
*/
@@ -209,7 +220,7 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
* The channel modes to set on all channels when the DefCon channel mode system is in use.
*
* Note 1: Choose these modes carefully, because when DefCon switches to a level which does NOT have
- * the mode setting selected, Services will set the reverse on all channels, e.g. if this setting
+ * the mode setting selected, Anope will set the reverse on all channels, e.g. if this setting
* is +RN when DefCon is used, all channels will be set to +RN, when DefCon is removed, all
* channels will be set to -RN. You don't want to set this to +k for example, because when DefCon
* is removed, all channels are set -k, removing the key from previously keyed channels.
@@ -227,14 +238,14 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
#timeout = 15m
/*
- * If set, Services will send a global message on DefCon level changes.
+ * If set, Anope will send a global message on DefCon level changes.
*
* This directive is optional.
*/
#globalondefcon = yes
/*
- * If set, Services will send the global message defined in the message directive on DefCon level
+ * If set, Anope will send the global message defined in the message directive on DefCon level
* changes.
*
* This directive is optional.
@@ -267,7 +278,7 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
*
* Provides the command operserv/dns.
*
- * This module requires that m_dns is loaded.
+ * This module requires that dns is loaded.
*
* This module allows controlling a DNS zone. This is useful for
* controlling what servers users are placed on for load balancing,
@@ -348,7 +359,7 @@ command { service = "OperServ"; name = "FORBID"; command = "operserv/forbid"; pe
*
* Provides the command operserv/ignore.
*
- * Used to make Services ignore users.
+ * Used to make Anope ignore users.
*/
module { name = "os_ignore" }
command { service = "OperServ"; name = "IGNORE"; command = "operserv/ignore"; permission = "operserv/ignore"; }
@@ -503,21 +514,10 @@ command { service = "OperServ"; name = "RANDOMNEWS"; command = "operserv/randomn
*
* Used to NOOP a server, which prevents users from opering on that server.
*/
-module { name = "os_noop" }
+#module { name = "os_noop" }
command { service = "OperServ"; name = "NOOP"; command = "operserv/noop"; permission = "operserv/noop"; }
/*
- * os_oline
- *
- * Provides the command operserv/oline.
- *
- * Used to set oper flags on users, and is specific to UnrealIRCd 3.2.
- * See /helpop ?svso on your IRCd for more information.
- */
-#module { name = "os_oline" }
-#command { service = "OperServ"; name = "OLINE"; command = "operserv/oline"; permission = "operserv/oline"; }
-
-/*
* os_oper
*
* Provides the command operserv/oper.
@@ -532,7 +532,7 @@ command { service = "OperServ"; name = "OPER"; command = "operserv/oper"; permis
*
* Provides the command operserv/reload.
*
- * Used to reload the services.conf configuration file.
+ * Used to reload the anope.conf configuration file.
*/
module { name = "os_reload" }
command { service = "OperServ"; name = "RELOAD"; command = "operserv/reload"; permission = "operserv/reload"; }
@@ -595,7 +595,7 @@ module
#sessionlimitdetailsloc = "Please visit https://your.website.url/ for more information about session limits."
/*
- * If set and is not 0, this directive tells Services to add an AKILL if the number of subsequent kills
+ * If set and is not 0, this directive tells Anope to add an AKILL if the number of subsequent kills
* for the same host exceeds this value, preventing the network from experiencing KILL floods.
*
* This directive is optional.
@@ -649,8 +649,18 @@ command { service = "OperServ"; name = "SET"; command = "operserv/set"; permissi
*
* Used to quit, restart, or shutdown services.
*/
-module { name = "os_shutdown" }
-command { service = "OperServ"; name = "QUIT"; command = "operserv/quit"; permission = "operserv/quit"; }
+module
+{
+ name = "os_shutdown"
+
+ /*
+ * If enabled then server operators will be required to provide the network
+ * name to confirm that they are quitting, restarting, or shutting down the
+ * right server.
+ */
+ requirename = yes
+}
+#command { service = "OperServ"; name = "QUIT"; command = "operserv/quit"; permission = "operserv/quit"; }
command { service = "OperServ"; name = "RESTART"; command = "operserv/restart"; permission = "operserv/restart"; }
command { service = "OperServ"; name = "SHUTDOWN"; command = "operserv/shutdown"; permission = "operserv/shutdown"; }
diff --git a/data/stats.standalone.example.conf b/data/stats.standalone.example.conf
index c4925c4c8..27af0e182 100644
--- a/data/stats.standalone.example.conf
+++ b/data/stats.standalone.example.conf
@@ -1,8 +1,8 @@
/*
- * Example configuration file for Services. After making the appropriate
- * changes to this file, place it in the Services conf directory (as
- * specified in the "configure" script, default /home/username/services/conf)
- * under the name "services.conf".
+ * 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
@@ -53,7 +53,7 @@
* included to indicate whether an option is required:
*
* [REQUIRED]
- * Indicates a directive which must be given. Without it, Services will
+ * Indicates a directive which must be given. Without it, Anope will
* not start.
*
* [RECOMMENDED]
@@ -71,7 +71,7 @@
*
* [DEPRECATED]
* Indicates a directive which will disappear in a future version of
- * Services, usually because its functionality has been either
+ * Anope, usually because its functionality has been either
* superseded by that of other directives or incorporated into the main
* program.
*/
@@ -120,7 +120,7 @@ define
* 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 Services
+ * 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
@@ -158,20 +158,22 @@ define
uplink
{
/*
- * The IP or hostname of the IRC server you wish to connect Services to.
- * Usually, you will want to connect Services over 127.0.0.1 (aka localhost).
+ * 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"
/*
- * Enable if Services should connect using IPv6.
+ * The protocol that Anope should use when connecting to the uplink. Can
+ * be set to "ipv4" (the default), "ipv6", or "unix".
*/
- ipv6 = no
+ protocol = "ipv4"
/*
- * Enable if Services should connect using SSL.
+ * Enable if Anope should connect using SSL.
* You must have an SSL module loaded for this to work.
*/
ssl = no
@@ -197,12 +199,12 @@ uplink
/*
* [REQUIRED] Server Information
*
- * This section contains information about the Services server.
+ * This section contains information about the services server.
*/
serverinfo
{
/*
- * The hostname that Services will be seen as, it must have no conflicts with any
+ * 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.
*/
@@ -212,11 +214,11 @@ serverinfo
* The text which should appear as the server's information in /WHOIS and similar
* queries.
*/
- description = "Stats for IRC Networks"
+ description = "Anope IRC Statistics"
/*
- * The local address that Services will bind to before connecting to the remote
- * server. This may be useful for multihomed hosts. If omitted, Services will let
+ * 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
@@ -232,16 +234,16 @@ serverinfo
#id = "00A"
/*
- * The filename containing the Services process ID. The path is relative to the
- * services root directory.
+ * The filename containing the Anope process ID. The path is relative to the
+ * data directory.
*/
- pid = "data/stats.pid"
+ pid = "anope.pid"
/*
* The filename containing the Message of the Day. The path is relative to the
- * services root directory.
+ * config directory.
*/
- motd = "conf/stats.motd"
+ motd = "motd.txt"
}
/*
@@ -252,57 +254,55 @@ serverinfo
*
* Supported:
* - bahamut
- * - charybdis
* - hybrid
- * - inspircd12
- * - inspircd20
- * - inspircd3 (for 3.x and 4.x)
+ * - inspircd
* - ngircd
* - plexus
* - ratbox
- * - unreal (for 3.2.x)
- * - unreal4 (for 4.x or later)
+ * - solanum
+ * - unrealircd
*/
module
{
- name = "inspircd3"
+ name = "inspircd"
}
/*
* [REQUIRED] Network Information
*
- * This section contains information about the IRC network that Services will be
+ * This section contains information about the IRC network that Anope will be
* connecting to.
*/
networkinfo
{
/*
- * This is the name of the network that Services will be running on.
+ * 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
- * Services being disconnected from the network.
+ * Anope being disconnected from the network. Defaults to 31.
*/
- nicklen = 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
- * Services being disconnected from the network.
+ * Anope being disconnected from the network. Defaults to 10.
*/
- userlen = 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
- * Services being disconnected from the network.
+ * Anope being disconnected from the network. Defaults to 64.
*/
- hostlen = 64
+ #hostlen = 64
/* Set this to the maximum allowed channel length on your network.
+ * Defaults to 64.
*/
- chanlen = 32
+ #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.
@@ -314,7 +314,7 @@ networkinfo
* 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 Services.
+ * disallows could potentially break the IRCd and/or Anope.
*
* It is recommended you DON'T change this.
*/
@@ -339,22 +339,22 @@ networkinfo
}
/*
- * [REQUIRED] Services Options
+ * [REQUIRED] Anope Options
*
- * This section contains various options which determine how Services will operate.
+ * 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
+ * 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. Services use this case map to compare, with
+ * 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.
@@ -372,14 +372,14 @@ options
readtimeout = 5s
/*
- * If set, Services will only show /stats o to IRC Operators. This directive
+ * 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 Services will
+ * 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.
@@ -478,13 +478,13 @@ log
/*
* [REQUIRED] MySQL Database configuration.
*
- * m_mysql
+ * mysql
*
* This module allows other modules to use MySQL.
*/
module
{
- name = "m_mysql"
+ name = "mysql"
mysql
{
diff --git a/docs/ASTYLE b/docs/ASTYLE
deleted file mode 100644
index be8cf2325..000000000
--- a/docs/ASTYLE
+++ /dev/null
@@ -1 +0,0 @@
-astyle --style=java --indent=tab --brackets=break-closing --indent-switches --indent-cases --brackets=break
diff --git a/docs/BUGS b/docs/BUGS
deleted file mode 100644
index 38398be01..000000000
--- a/docs/BUGS
+++ /dev/null
@@ -1 +0,0 @@
-For all bug reports / updates please see https://github.com/anope/anope/issues
diff --git a/docs/C++CASTING b/docs/C++CASTING
deleted file mode 100644
index eed640bec..000000000
--- a/docs/C++CASTING
+++ /dev/null
@@ -1,111 +0,0 @@
-C++-style Casting
-=================
-
-In C, you can cast in one of two ways:
-
-(type)var
-type(var)
-
-The problem with C-style casting is that it allows a programmer to get away
-with too much, and is also not designed to handle C++ classes.
-
-C++ has 4 types of casting in addition to allowing C-style casting. They are:
-
-static_cast
-const_cast
-dynamic_cast
-reinterpret_cast
-
-The syntax is usually *_cast<type>(var).
-
-static_cast
------------
-
-From my experience, this cast is closest to C-style casting for non-pointer
-types as well as between some (but not all) pointer types. This type of cast,
-like C-style casting, is performed at compile-time. static_cast can also do
-a downcast of a derived class to a base class, but only if the base class is
-not a virtual base class. Sometimes the result of this cast can become
-undefined. static_cast is a bit more strict that C-style casting, though. It
-disallows certain class conversions that would've been allowed with a C-style
-cast. static_cast also doesn't allow you to cast to an incomplete type. In
-these cases, I would try either dynamic_cast or reinterpret_cast.
-
-const_cast
-----------
-
-This cast is mainly to add or remove const-ness or volatile-ness from a
-variable. This is safer than using a C-style cast to change the const-ness
-of a variable. In most cases if you try to use one of the other casts and it
-complains about const-ness, you will want to either use this cast instead or
-wrap the other cast around this cast. An example:
-
-const int *a;
-static_cast<void *>(a); <-- This will fail.
-
-To remedy the above, you would might try this:
-
-const int *a;
-const_cast<void *>(a); <-- But this will still fail.
-
-The real solution is this:
-
-const int *a;
-static_cast<void *>(const_cast<int *>(a));
-
-It is not recommended to use const_cast on the this variable within a member
-function of a class that is declared const. Instead you should use the mutable
-keyword on the variable in the class's definition.
-
-dynamic_cast
-------------
-
-This cast can only be used on pointers or references to classes. It can cast a
-derived class to a base class, a derived class to another derived class
-(provided that both are children of the same base class), or a base class to a
-derived class. You can also use this to cast a class to void *. This cast is
-done at run-time as opposed to the other casts, and relies on C++'s RTTI to be
-enabled. It is meant to be used on polymorphic classes, so use static_cast on
-non-polymorphic classes.
-
-derived-to-base conversions are actually done statically, so you use either
-dynamic_cast or static_cast on them, regardless of if the classes are
-polymorphic or not.
-
-derived-to-derived or base-to-derived conversions, however, rely on run-time
-type information, and this cast is used on those classes that are polymorphic.
-This is safer than C-style casting in that an invalid pointer conversion will
-return a NULL pointer, and an invalid reference conversion will throw a
-Bad_cast exception.
-
-Note that in Anope we prefer if Anope::debug_cast is used.
-This uses dynamic_cast (and checks for a NULL pointer return) on debug builds
-and static_cast on release builds, to speed up the program because of dynamic_cast's
-reliance on RTTI.
-
-reinterpret_cast
-----------------
-
-This cast I would use only as a last resort if static_cast isn't allowed on a
-conversion. It allows for conversions between two unrelated types, such as
-going from char * to int *. It can also be used to convert a pointer to an
-integral type and vica versa. The sites I've read mention how the result is
-non-portable, which I assume means the resulting object code is non-portable,
-so since the code is compiled on many systems anyways, I don't see this as
-being a huge issue. It is recommended to only use this if necessary, though.
-
-Links
-=====
-
-The following links are web sites I've used to get this information, and might
-describe some of the above a bit better than I have. :P
-
-https://www.acm.org/crossroads/xrds3-1/ovp3-1.html
-http://www.cplusplus.com/doc/tutorial/typecasting.html
-http://www.codeguru.com/forum/showthread.php?t=312456
-https://web.archive.org/web/20170810222238/http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/cast.html
-https://www.microsoft.com/en-us/download/details.aspx?id=55984
-https://en.wikibooks.org/wiki/C%2B%2B_Programming/Type_Casting
-https://web.archive.org/web/20160510114447/http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=134
-
--- CyberBotX, Nov 23, 2008
diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt
index 082b1da0e..64387fc73 100644
--- a/docs/CMakeLists.txt
+++ b/docs/CMakeLists.txt
@@ -6,10 +6,10 @@ if(WIN32)
if(IN_SOURCE)
# Add README.txt to list of files for CPack to ignore
add_to_cpack_ignored_files("README.txt$" TRUE)
- endif(IN_SOURCE)
- set(DOCS Changes Changes.conf DEFCON FAQ INSTALL LANGUAGE MODULES NEWS ${CMAKE_CURRENT_BINARY_DIR}/README.txt WIN32.txt)
+ endif()
+ set(DOCS Changes Changes.conf DEFCON FAQ INSTALL LANGUAGE MODULES ${CMAKE_CURRENT_BINARY_DIR}/README.txt WIN32.txt)
install(FILES ${DOCS}
DESTINATION ${DOC_DIR}
)
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/README.txt")
-endif(WIN32)
+endif()
diff --git a/docs/CODING b/docs/CODING
deleted file mode 100644
index 6c56d0ddf..000000000
--- a/docs/CODING
+++ /dev/null
@@ -1,239 +0,0 @@
-Originally pulled from: https://wiki.inspircd.org/Coding_Guidelines
-
----
-
-InspIRCd Coding Guidelines
-
-The following are a set of guidelines for writing patches to InspIRCd, or for
-creating modules for distribution with the official package. These guidelines
-were written a time after InspIRCd development started, and so not all code
-yet follows these. This will be rectified with time.
-
-
-1. Comments
-
- * Multi Line
- Multiple line comments should follow the C-style comment, for example:
- /*
- * This is a multiple line comment, huzzah..
- */
-
- * Single Line
- Single line comments should also be in the C style, for example:
- /* This is a boring one-line comment */
-
- * Doxygen commenting
- If you wish your comment to show in doxygen, the comment should be directly
- above the item you are documenting (a class, function, enum, etc) and the
- first line should be "/**". For example:
- /** This is a doxygen multiline comment.
- * Description of thingymebob here.
- */
-
- The first line after the "**" is used as the short description of the item
- (up to the full stop) and everything afterwards as the detailed description.
-
-
-2. Indentation
-
- Tabs. Tabs. ONLY TABS. Use a single tab for each level of indentation,
- for example:
- int main()
- {
- <tab>if (condition)
- <tab>{
- <tab><tab>code
- <tab>}
- }
-
-
-3. Separation
-
- Always put a space in between a keyword like if/while and the condition,
- for example:
- if (foo == bar)
- NOT
- if(foo == bar)
-
-
-4. Braces
-
- Always put braces opening and closing blocks on separate lines, see the
- indentation example. For example, place braces like this:
- if (apples == "green")
- {
- cout << "Apples are green" << endl;
- }
-
- and not:
- if (apples == "green") {
- cout << "Apples are green" << endl;
- }
-
- The one exception to this is if you are declaring a class method which is
- only one line long, in that case the following is acceptable in most cases:
- class foo : public bar
- {
- foo() { }
- getrandomfoo() { return rand(); }
- };
-
-
-5. Templates
-
- Where possible, use templates rather than #defines. Avoid use of RTTI.
-
-
-6. Structs
-
- Structs should be declared in the following fashion:
- struct BodyPartBasket
- {
- int arms;
- int legs;
- int scrotalsacs;
- };
- and not like this:
- typedef struct
- {
- int arms;
- int legs;
- int scrotalsacs;
- } BodyPartBasket;
-
- The second way is not required in C++ to be able to do this:
- BodyPartBasket mybasket;
-
- Plus, placing the name at the bottom of the declaration makes readability
- more difficult (as you have to scroll down to the bottom of the struct to
- find its name). (where possible, call them classes rather than structs.)
-
-
-7. Variable naming
-
- Class and struct names should be in camel case with a leading capital letter,
- for example "MyBagOfBones" and not "my_bag_of_bones" or "mybagofbones".
- Variable names can be in either camel case with a leading capital letter or
- alternatively all lower case, so long as the same naming convention is
- adhered to throughout the class. No classes or variables should be named in
- capitals unless this makes sense for the name (for example "class DNS").
- Constants and enum values should always be completely in CAPITALS and
- underscores may be used, for example:
- enum DecayState
- {
- DECAYED_MOULDY = 0,
- DECAYED_SMELLY = 1,
- DECAYED_MAGGOTS = 2
- };
- All value names in an enum should be started with the same text which should
- be related in some way to the enum's use. For example "DNS_CNAME, DNS_A,
- DNS_AAAA".
-
-
-8. Use of references
-
- Wherever possible, when dealing with any complex class, pass a const reference
- rather than a copy of the class. For example:
- MyThingy::MyThingy(const std::string &thingyvalue)
- {
- }
- Of course, if you intended to change the string you can just omit the 'const'.
-
-
-9. Use of char pointers
-
- Whenever you use char pointers (char*, char**) try to use const equivalents.
- This is much safer and avoids ugly and dangerous casts. For example:
- MyThingy::Thingify(const char* const* wotsits)
- {
- }
- If it is possible without performance loss, consider avoiding char pointers
- altogether and using std::string instead.
-
-
-10. Use of STL
-
- For more information on use of STL in InspIRCd, please see the separate
- STL FAQ.
-
-
-11. Making copies of data
-
- Never ever make a copy of a piece of data unless it is absolutely necessary.
- For example, don't use strlcpy() to make a copy of the const char* string
- returned by std::string::c_str(), if the change can be done to the std::string
- itself. The same goes for unnecessary variable assignments, especially those
- which assign large classes.
-
-
-12. namespace std
-
- Avoid the following:
- using namespace std;
- It might take a bit more typing, but things work better if you don't set
- (then later assume) the namespace -- specify it explicitly when you want to
- use it.
-
-
-13. Linefeeds
-
- Unix linefeeds only please. We do not like to see our screens covered in ^M.
-
-
-14. Portability
-
- Always make sure your code is portable to all supported operating systems,
- remember of course that as of 1.1.8 this includes windows. Don't write code
- that only works on windows, or only works on Linux. Test your code on all
- platforms or ask for help from other developers who have the platforms you
- want to test on.
-
- * new() and delete(), malloc() and free()
- Apart from the fact that using malloc() and free() is bad practice in C++
- code, you must never use malloc() or free() in InspIRCd, within its modules
- or within the core. This is because if you use malloc() or free() in windows,
- the memory is claimed from the program's local heap.
- In windows, each shared object (module, dll) has its own heap, which is
- protected from other dlls and executables. To get around this issue and
- allow more posix-like memory access from other dlls in the program (other
- modules), InspIRCd overrides the operators new and delete to ensure that
- memory allocated by them comes from the windows global heap. If you use
- malloc() and free() for this, the ircd will segfault when another module
- tries to access the memory you have allocated!
-
- * strdup()
- As with malloc(), above, strdup() should be avoided. Where strdup() is
- absolutely necessary, use strnewdup() which is our strdup() implementation
- that calls operator new instead of using malloc().
- char arrays allocated by strnewdup() should be deleted with operator delete[].
-
- * CoreExport and DllImport
- Prefix all types you want to import or export to other modules with CoreExport
- and DllImport macros. These do nothing in POSIX operating systems, however
- in windows these are expanded to the instructions __declspec(dllimport) and
- __declspec(dllexport) respectively depending on where they are used and how.
-
-
-15. External Dependencies
-
- If a module is compiled as standard, or the code is part of the core, you must
- not use any dependencies that are not available as standard on all supported
- operating systems beyond libstdc++, libc, and whatever else is currently
- required to build the core. Modules which use nonstandard dependencies belong
- in the modules/extra directory.
-
-
-16. Profiling and Performance
-
- It is one thing to assume that code performs bad, it is another thing to prove
- that it actually is. A lot of experienced programmers talk about 'premature
- optimisation', and here is what it means: if you have a piece of code called
- once on startup that takes 10 seconds instead of one second to run, and a
- piece of code that takes 0.05 seconds to run when it should take 0.01, and
- it is called once per second, the second piece of code is the priority.
-
- In other words, make sure that what you think is slow, and a performance
- problem in Insp actually is.
- To do this, use the callgrind tool from Valgrind (valgrind --tool=cachegrind
- bin/inspircd -nofork -debug), and kcachegrind (or similar) to view the output
- files.
diff --git a/docs/Changes b/docs/Changes
index 6ac23ce64..ee69c3308 100644
--- a/docs/Changes
+++ b/docs/Changes
@@ -1,490 +1,177 @@
-Anope Version 2.0.18-git
+Anope Version 2.1.12-git
------------------------
No significant changes.
-Anope Version 2.0.17
+Anope Version 2.1.11
--------------------
-Fixed importing large flatfile databases into SQL.
-Fixed marking channels as permanent.
-Fixed serialising unset boolean extension items.
-Fixed the documentation about how to import SQL databases.
-Fixed the documentation of options:usemail.
-Fixed the location of the geoipupdate CSV files.
-Fixed translating memo emails.
-Fixed unnecessary SQL updates caused by dereferencing user accounts.
-Increased the size of the chanstats letter and word count columns.
-Updated the location of the Anope IRC channels.
-
-Anope Version 2.0.16
---------------------
-Added a workaround for users matching expired sqlines.
-Fixed a copy/paste error in webcpanel.
-Fixed a crash in db_flatfile caused by trying to serialize data without a type.
-Fixed duplicate messages when synconset/syncongroup is set.
-Fixed expiring channel suspensions.
-Fixed expiring forbids.
-Fixed expiring nick suspensions.
-Fixed feature detection on InspIRCd.
-Fixed InspIRCd account cloaks causing CHGHOST spam when a user also has a services vhost.
-Fixed joining users to channels with a key set on InspIRCd.
-Fixed logging users out fully when their nick gets suspended.
-Fixed marking boolean columns in SQL as TEXT instead of INT.
-Fixed matching extbans on InspIRCd and implement missing matchers.
-Fixed operserv/sqline expiry on UnrealIRCd
-Fixed respecting --noexpire in cs_suspend and ns_suspend.
-Fixed sending emails to nicks ending with a backslash.
-Fixed sending SVSTOPIC when topiclock is loaded on InspIRCd.
-Fixed some SQL tables taking up too much space on disk.
-Fixed the default config for channel suspensions.
-Fixed the TIME message on InspIRCd.
-Fixed trying to escape SQL data when not connected to MySQL.
-Fixed {ldap,sql}_authentication creating zombie accounts on expiry.
-
-Anope Version 2.0.15
+Added support for database migrations to the mysql module.
+Added support for renicking users to their UID when enforcing nickname protection.
+Added support for sending channel URLs to joining users.
+Allowed selecting languages using a shorter version of their name.
+Changed various messages to use human-readable durations instead of seconds.
+Improved the creation of expiry and duration messages.
+Improved the translation system with support for plural forms.
+Reworked how guest nicknames are generated.
+Simplified how account identifiers are allocated.
+
+Anope Version 2.1.10
--------------------
-Fixed a race condition in changing the nick of a user.
-Fixed being able to reset the password of suspended accounts.
-Fixed chanserv/suspend info not being visible to regular users.
-Fixed removing entries by an alias in chanserv/access and chanserv/xop.
-Fixed various grammar issues in messages.
-Made the SASL PLAIN implementation more robust.
-Updated the Dutch translation.
-Updated the French translation.
+Added support for NEXTBANS on UnrealIRCd.
+Changed hostmask access entries added by nick to use that nick as the default description.
+Changed modes to be handled internally in their split form.
+Changed ns_cert to notify a user that their certificate is being automatically added to their account.
+Fixed matching users against extended bans.
+Fixed parsing name-only extended bans on InspIRCd.
+Fixed respecting the preferred extended ban format on InspIRCd.
+Fixed the name of the cron script in the docs.
+Updated the list of supported IRCds.
+Updated the location of the Anope IRC channels
+
+Anope Version 2.1.9
+-------------------
+Bumped the minimum supported version of UnrealIRCd to 6.
+Fixed granting IRC operator status to services operators.
+Fixed making users an IRC operator on InspIRCd.
+Fixed nonicknameownership on InspIRCd v4.
+Fixed some messages not being translatable.
+Fixed the Argon2 module not having test vectors.
+Increased the default nickname expiry period to one year.
+
+Anope Version 2.1.8
+-------------------
+Added account identifiers to the nickserv/info output.
+Added support for bool, float, and uint SQL columns.
+Added the ability to automatically determine SQL column types based on the native type.
+Added UNIX socket support to mysql module.
+Changed smartjoin to use SendClearBans where available.
+Dropped support for MinGW in favour of native builds.
+Fixed parsing named extbans on InspIRCd.
+Fixed parsing SVSMODE and SVS2MODE from UnrealIRCd.
+Fixed sending global messages to remotely linked servers.
+Removed the services server name from the CTCP version response.
+
+Anope Version 2.1.7
+-------------------
+Added importing of akick reasons, forbid reasons, opers and session exceptions to db_atheme.
+Added support for sending tag messages.
+Added the ability to look up account information of an authenticated user.
+Fixed a crash in ns_cert when an IRC user is not present during a nick registration.
+Fixed a null pointer dereference in the global module.
+Fixed a rare memory leak in os_akill and os_sxline.
+Improved the performance of some code that looks up the primary nick from an account.
+Removed the broken Catalan, Hungarian, and Russian translations.
+Reworked the protocol interface for sending messages.
Updated the Turkish translation.
-Anope Version 2.0.14
---------------------
-Added support for sqlining channels on UnrealIRCd.
-Fixed a crash when trying to access config for non-loaded modules.
-Fixed detection of the InspIRCd nopartmsg module.
-Fixed not getting memo notifications when authing with SASL.
-Fixed not serialising dontkickops/dontkickvoices in botserv/kick.
-Fixed sending emails with the wrong kind of line terminator.
-Fixed sending log messages from a renamed pseudoclient.
-Fixed telling users their passcode is incorrect when they need to authenticate in nickserv/confirm.
-Fixed the Config script freezing on some versions of util-linux.
-Updated the Windows packaging scripts to use dependencies from Conan.
-
-Anope Version 2.0.13
---------------------
-Fixed a crash on some compilers when trying to call methods on a null pointer
-Fixed a crash when encountering an unterminated commented config block
-Fixed erroneously rejecting spaces in fantasy:name
-Fixed marking services pseudoclients as an oper on InspIRCd
-Fixed not checking user@ip as well as user@host when logging into an operator account
-Fixed setting the vhost/vident during SASL on UnrealIRCd
-Updated the German translation
-Updated the Italian translation
-
-Anope Version 2.0.12
---------------------
-Added account confirmation to the web panel
-Added the regex_pcre2 module which provides regex/pcre with PCRE2
-Documented the cs_no_expire channel default
-Fixed config validation mistakenly allowing spaces in some fields
-Fixed the bahamut protocol module not knowing about halfops
-Fixed writing a flatfile database not being atomic
-Updated the hybrid protocol module for recent protocol changes
-
-Anope Version 2.0.11
---------------------
-Fixed ldap on OpenLDAP 2.5+
-Fixed not using utf-8 encoding for outgoing email
-Fixed ns_resetpass not returning a response for XMLRPC
-Fixed some message params being sent as <middle> instead of <trailing>
-Fixed unsetting vhosts on unreal4
-Fixed username validity checking on ircd-hybrid
-Send the oper mode for services pseudoclients on InspIRCd
-Updated the pl_PL translation
-Updated unreal4 for various protocol changes
-
-Anope Version 2.0.10
---------------------
-Add support for channel SQLines on InspIRCd
-Change default protocol module from inspircd20 to inspircd3
-Change the character set used by chanstats and irc2sql to utf8mb4
-Fix a ton of typos in messages
-Fix being able to override MAXLIST on InspIRCd
-Fix blocking on boot when trying to upgrade SQL databases without account identifiers
-Fix not flushing the ERROR message on squit
-Fix using an invalidated iterator when deleting bots
-Fix various harmless compiler warnings
-Fix webcpanel not using the forwarded IP
-Show the account name in nickserv/info
-
-Anope Version 2.0.9
--------------------
-Fix a regression from 2.0.8 that prevented serialising to MySQL
-Send account identifiers to InspIRCd on SASL logins too
-Fix a query bug in irc2sql
-
-Anope Version 2.0.8
--------------------
-Add +K channel mode for ircd-hybrid
-Add immutable identifiers to user accounts
-Fix build on systems that use musl libc
-Fix help of global/global not showing the correct origin nick
-Fix not removing vhosts when an nick is dropped
-Fix parsing channel metadata on InspIRCd 3+
-Fix parsing kicks on InspIRCd 3+
-Fix parsing topic changes on InspIRCd 3+
-Fix topiclock on InspIRCd
-Modernize the ircd-hybrid protocol module
-
-
-Anope Version 2.0.7
--------------------
-Fix not sending login data on successful NickServ GROUP
-Fix m_httpd to not consider headers to be case sensitive
-Add InspIRCd 3 protocol support
-Add 'n' email token for use in the email change template
-Add logging for NickServ UNGROUP
-Fix setting swhois on UnrealIRCd
-Add nickserv/recover permission to allow opers to recover other users
-Fix superadmin not being removed when deopering
-Fix setting nickserv access list in webcpanel
-Add support for post-handshake SASL in Unreal 4.2.2+
-Add logging for channel memo deletionso
-
-Anope Version 2.0.6
--------------------
-Log client IP for web clients running commands via webcpanel
-Fix log file path for the config file could not be opened log message
-Allow nickserv/group to be used via XMLRPC
-Fix logsearch without wildcards
-Support cidr exempts in m_dnsbl
-Add support for IPv6 dnsbls
-Add +u and +L channel modes for ircd-hybrid
-Set +x after hostserv/off on InspIRCd and UnrealIRCd
-Fix chanserv/mode not being able to set extbans
-Send CHGIDENT/CHGHOST on SVSLOGIN on InspIRCd
-Fix escaping replies from commands in webcpanel
-Enable require_oper for all opers added via operserv/oper
-Advertise SASL mechanisms to UnrealIRCd servers
-
-Anope Version 2.0.5
--------------------
-Fix negative levels to not match users with negative access
-Fix memo sender to always be the account name of the sender
-Allow unregistered users to use the ChanServ seen command
-Fix secureops to not be enforced on operators with the chanserv/administration privilege
-Fix command name in HELP syntax messages to always be upper case
-Show unconfirmed nickname messages on registration in webcpanel
-Fix NickServ SET EMAIL to be executable via XMLRPC
-Fix OperServ USERLIST/CHANLIST to accept regexes
-Allow OperServ USERLIST to also match realname syntax (n!u@h#r)
-Fix db_old importing languages to use the UTF-8 version
-Fix m_dns to return REFUSED if no answers could be found
-Fix ns_maxemail to be case insensitive
-Add MemoServ READ ALL command
-Add support for NickServ GROUP to be executed via XMLRPC
-Add support for logging hostname/ip of SASL authentication attempts, if supported by IRCd
-
-Anope Version 2.0.4
--------------------
-Add notice rpc method to XMLRPC
-Fix access check in cs_updown to not allow actions on users with equal access
-Fix randomnews to work when there are more than 'newscount' random news
-Fix crash from handling nick introduction collisions on unreal4
-Add support for GCC6
-Fix handling /join 0 on ratbox
-Fix saset display to update the account of the proper user
-Fix nickserv/confirm to send account and +r when appropriate
-Fix chankill to not add duplicate akills
-Allow nickserv/maxemail to disregard gmail style aliases when comparing emails
-Fix chanserv/mode when setting listmodes with CIDR ranges
-Fix reported expiry time when the time is divisible by 1 year
-Clarify botserv repeat kicker help and allow setting repeat times to 1
-Send vident/vhost with SASL login
-Add support for SASL reauth
-Fix log and database backup directories to be properly created by the installer
-
-Anope Version 2.0.3
--------------------
-Add support for UnrealIRCd 4
-Fix cs_access to respect chanserv/access/list privilege
-Fix cs_access to match level -1 as every user, not any level <0
-Fix problems related to object destruction order when using db_sql_live
-Show memo notify settings in ms_info
-Fix some actions bumping channels last used time that shouldn't have
-Add maxlogins configuration directive to limit the number of concurrent logins to one account
-Fix race with auto svsnick on ghost sometimes causing nick collisions instead
-Fix saset language reply
-Show akill/sxlines ids in VIEW
-Fix crash when an oper is configured in both the configuration and via os_oper
-Fix m_ldap reconnect logic not properly setting protocol and network timeout settings
-Fix crash from unloading regex modules when regex xlines exist
-Fix irc2sql to store away messages
-Add notice method to m_xmlrpc_main
-Fix numerics on InspIRCd from being sent to user UID
-Fix usermode +I on UnrealIRCd to be considered oper only
-Fix crash in webcpanel when deleting your own access on a channel
-Fix webcpanel allowing suspended users to login
-Fix hs_off on InspIRCd to not desync active user host
-Fix bs_bot to not allow colliding bots into users
-Don't allow hostserv modules to load if there is no hostserv
-Fix ns_register allowing bot nicks to be registered through webcpanel
-Don't update chanserv keepmodes during inhabit
-Fix build on cmake 2.4
-Allow searching emails by wildcard in ns_getemail
-
-Anope Version 2.0.2
--------------------
-Fix keepmodes preventing the first user of a channel from being deopped
-Fix SQlines that don't begin with # from matching channels
-Made cs_clone behave like the help describes, copying many settings and lists by default
-Allow cs_clone to clone levels, too
-Update Hybrid protocol module for 8.2
-Fix not unescaping all characters sent over XMLRPC
-Fix crash when os_mode is used to destroy channels, like when unsetting permanent channel mode from an empty channel
-Allow users with topic change privilege to change the topic instead of requiring them to use ChanServ's topic command
-Fix negatively locking param modes in default mlock
-Change entrymsg to check for the SET privilege, not real founder
-Allow configuring characters allowed in nicknames
-Fix crash when non users register channels externally (like XMLRPC)
-Remove operserv/exception MOVE, it did not function correctly. Instead reorder the list by deleting/adding entries.
-Allow flood ttb to be 0.
-Enforce mlock when disabling defcon modes
-Fix cs_mode not being able to apply mlock on register
-Add log message when users send memos
-Fix old collide timers from staying around after successful identify. Fixes being able to identify and logout and still being hit by the old timers.
-Fix undefined behavior in cs_mode which usually crashes when clearing large list modes
-Show all opertypes in operserv/info, even if no opers use them
-
-Anope Version 2.0.1
--------------------
-Fix access entries on accounts sometimes not updating when a user's display name changes
-Fix ns_group to properly validate the account of the user against the target
-Fix os_stats not saving max user count and time when using SQL
-Fix nickalias's 'nc' field sometimes not being updated when using SQL
-Fix several crashes on Windows related to being unable to load modules
-Fix bs_bot change not properly reintroducing bots after changing their ident, host, or realname
-
-Add English language file to allow users to easily modify language strings
-Add configuring which mode cs_ban sets, and added a MUTE command to BotServ's fantasy
-Allow SVSPART to take an optional reason
-Allow cs_list to search channel topics and descriptions
-
-Anope Version 2.0.0
--------------------
-Added irc2sql stats module
-
-Anope Version 1.9.9
--------------------
-A Added a better webpanel template, removed the old one
-A Added SQL logging support
-A Added Redis database support
-A Added ability to configure what privileges XOP commands give
-U Updated Dutch language file, from Robby <robby@chat.be>
-U Updated Spanish language file, from Isaac Fontal <i_fontal@hotmail.com>
-F Fix build on Solaris and OSX
-F Fixed setting BotServ's default settings in the config
-F Fixed some names of config items, including NickServ's kill protect
-
-Anope Version 1.9.8
--------------------
-A Ability to configure fantasy commands in the config
-A Add SVSJOIN and SVSPART commands
-F Fix "leave" channel log level from not logging
-F Fix users able to "resend" their registration mail with registration set to admin only
-F Fix build on OpenBSD
-F Fix not logging debug logs to the logfile when debug mode is enabled
-F Fix defcon timeout timer
-F Fix crash in os_forbid with expiring entries
-F Fix several issues with db_sql_live
-
-Anope Version 1.9.7
--------------------
-A Added ability for using regex as patterns for various commands
-A Extended ability of operserv/akill to also match against nick and realname
-A Added chanserv:require configuration option
-A Added nickserv:unregistered_notice and nickserv:registration configuration option
-A Added options:casemap configuration option
-A Added a web panel
-A db_sql_live now allows all tables to be "live", not just a select few
-
-Anope Version 1.9.6
--------------------
-A Added ability to configure emails sent by services
-A Added chanserv/up and chanserv/down
-A Added m_proxyscan
-A Added more configurability for what vhosts are valid
-A Added chanserv/log
-A Added ability to configure ChanServ privileges
-A Added a new database format
-A Added SQLite support
-A Added more verbose messages on startup
-A Added ability for chanserv/suspend and nickserv/suspend to take an expiry time
-A Added no nickname ownership config option
-A Added m_rewrite
-A Added akill IDs
-F Fixed crash in clearusers
-F Fixed crash in /os oper info
-F Fixed eventfd Config check to work properly on OpenVZ
-
-Anope Version 1.9.5
--------------------
-A Extended LDAP support
-A Added os_oper, os_kill, os_forbid, m_statusupdate, cs_sync, and bs_autoassign
-A Added a new configuration file format
-A Added a new commands system
-A Added a new access system, and cs_flags
-F Fixed not logging debug logs to file
-F Fixed the mail delay time
-F Fixed sending account data for unconfirmed nicks
-F Fixed poll() engine build on FreeBSD
-F Fixed really large HELP replies being truncated
-F Fixed sometimes appending !*@* to valid hosts on access lists
-F Fixed m_ssl sometimes failing connecting for no reason
-F Fixed crash in cs_entrymsg
-F Fixed setting -P on channels with only a botserv bot in it
-F Fixed modemanager complaining about prefixless modes on InspIRCd
-
-Anope Version 1.9.4
--------------------
-A Automatically set channel founder to the user with the highest access if there is no successor
-A /chanserv clone command to copy settings from one channel to another.
-A /chanserv mode command
-A Ability for users to delete their own access in channels
-A Added support for Plexus 3
-A Readded in support for /cs op/deop/etc to op/deop you in all channels
-A Added LDAP support
-A Added live SQL support
-A Added support for learning tracking/storing/locking all modes at runtime
-A Added m_alias
-A Added support for XMLRPC queries
-A Added /botserv set msg
-A Added /operserv config
-A Added /ns cert
-A Added /operserv login
-F Changed the GHOST command to not allow ghosting unidentified users if the RECOVER command exists
-F Some failed logic in /operserv exception that prevents proper exceptions from being added
-F Fixed the anope_os_sxlines MySQL table and code to work after restarting
-
-Anope Version 1.9.3
--------------------
-A Added italics BotServ kicks support
-A Tell users when their nicks expire in /ns glist and /ns info
-A Added SSL support
-A Prevent negative mode changes, kicks, bans, and autokicks from affecting people with the 'god' user mode (On UnrealIRCd, usermode +q)
-A Added nickserv/auxpex permission
-A Added nickserv ungroup command
-A Renamed the SGLINE to be SNLINE
-A Added /chanserv saset command
-A Added threads for mail sending
-A Added m_dnsbl and an asynchronous DNS system
-A Added a new language system that uses gettext
-A Added m_mysql which uses threads to execute queries
-A Added many subcommand modules for some commands, eg ns_set_autoop, ns_set_email, etc
-A Added a new logging system that is a bit more flexible
-A Added cs_set_misc and ns_set_misc to add miscellaneous set commands
-A Added os_modreload, which allows reloading some modules not normally unloadable, like the protocol module
-A Added FOUNDER access level
-A Made OperServ, Global, MemoServ, and ChanServ optional
-F Shutting down if a config reload fails
-F Autoid to live through restarts on Unreal
-F Storing vhosts in MySQL
-F Not flushing the anope_extra table before rewriting database
-F Anoperc start/stop to send the globaloncycle global, and fixed anoperc rehash to really rehash
-F Fixed a potential crash if HostServ or BotServ was disabled
-
-Anope Version 1.9.2
--------------------
-A K alias to chanserv kick command
-A KB alias to chanserv ban command
-A The ability to register empty nonregistered channels
-A Flatfile plaintext databases and removed old binary ones
-A Added in live updating SQL and the ability to execute commands through SQL (see docs/MYSQL)
-A Added support for many more modes into Anope and the ability to have generic support for modes unknown to Anope
-A Added a mode stacker to combine many mode changes into fewer
-A Added in the CS SET PERSIST command which can be used to keep service bots in channels even when the channel is empty
-A Added AUTOOWNER OWNER and OWNERME into CS LEVELS
-A Added ns_resetpass module to the core
-A CS ACCESS VIEW which shows who added the access and last time used
-A Last used time to CS AKICK VIEW
-A Added a sha_256 encryption module
-A Added the ability to load multiple encryption modules, and the ability to seamlessly convert your database between different encryptions
-A Added configuration options to allow Anope to reconnect if it disconnects from the uplink instead of dying
-A Added support for linking with IPv6
-F Unban command to accept an optional nick arg
-F Some typos in services.conf
-F Crash when users change their host that are identified to a group, but not a nick
-F Host length checking in HS SET(ALL) and HS REQUEST
-F Only show if a user is online in NS INFO if they are really identified for the group of the nick they are on
-F Crash when using BSSmartJoin
-F Converting access entries to access from xop when a users access is below voice
-F A bad pointer passed to the OnDelEvent which could cause some 3rd party modules to crash
-F CS FORBID allows to you forbid unregistered channels
-F The -nothird command line option to work
-F ms_rsend to really work
-F SQUITing juped servers on InspIRCd1.2+
-
-Anope Version 1.9.1
--------------------
-F Don't enforce akick/forbidden/etc.-restrictions on clients on ulined servers.
-F Remove modules_unload_all fini + hack that goes with it.
-F Signal handling cleanup.
-A Seamless fantasy support on all ChanServ commands, instead of requiring bs_fantasy_*.
-F Allow fantasy to be disabled on some commands (e.g. FORBID).
-F Some commands (e.g. !help) need to strip the pre-provided channelname from them.
-D HelpServ removed
-F Command parser cleanup: mod_current_buffer removed and replaced with proper parser. Commands now indicate how they want the buffer split.
-F Make NS ENFORCE/RELEASE stuff more sane, redo timers.
-A Opertypes (similar to InspIRCd's opertypes)
-
-Provided by Ankit <ankit@nevitus.com> - 2009
-F Segfault on shutdown
-
-Provided by Adam <adam@anope.org> - 2009
-F NickServ registration is sometimes denied.
-F Applied patch from Adam to fix some potential screwups
-F More fixes to bs_bot from Adam, plus an extra fix within DoAdd not covered in Adam's patch.
-F Fix bs_bot to use the correct parameters, patch from Adam.
-F Fix for bug #1004, based from second half of patch from Adam.
-F Partial patch by Adam, commenting fix for #1006 for future reference.
-F Forward-port r1946: Patch by Adam fixing #1006 (originally caused by #922): modes set by ChanServ are reversed. Thanks!
-
-Provided by DukePyrolator <dukepyrolator@gmx.de> - 2009
-F Patch converting all match calls to new method, thanks!
-F Add 'w' and 'y' support to dotime(), also prevent an overflow.
-F Allow NS STATUS from unregistered users, thanks DP!
-F Wild pointers do not a happy Anope make. Thanks DP :)
-F Allow NS REGISTER to unregistered nicks, silly oversight. Thanks DP! :)
-F Fix call order, thanks to DP
-F Pass the right array to do_umode(), fixes mode tracking on Unreal. Thanks to DukePyrolator (yet again :P)
-F Fix bs_set help, thanks to DukePyrolator! :)
-F Fix two segfaults, noted by DukePyrolator. Thanks!
-F Fix part one of #1010, reported by DukePyrolator. (Language settings are not respected in message sending.) Thanks!
-F Memory leak on +beI modes.
-
-Provided by Liber <Liber@jasonirc.net> - 2009
-F Support operoverride and such things (stop reversing changes from nonopped people where unnecessary)
+Anope Version 2.1.6
+-------------------
+Added opportunistic upgrading of TLS fingerprints to more secure algorithms on InspIRCd.
+Added support for logging out partially connected users on Plexus.
+Added the account registration time to nickserv/info.
+Changed ns_cert to automatically add a TLS fingerprint to new accounts if available.
+Clarified that a non-deprecated encryption module must be loaded.
+Fixed creating the runtime directory on Windows.
+Fixed mistakenly allowing badpasslimit to be set to a negative value.
+Fixed parsing backup TLS fingerprints on InspIRCd.
+Fixed parsing the flood mode on UnrealIRCd.
+Fixed parsing the history mode on UnrealIRCd.
+Fixed various iterator invalidation issues.
+Partially rewrote the Portuguese translation.
+Removed some incorrect strings from the Turkish translation.
+Renamed the --modulesdir option to --moduledir to match the name of other path options.
+
+Anope Version 2.1.5
+-------------------
+Added an example systemd unit file.
+Added support for BIGLINES on UnrealIRCd.
+Bumped the minimum supported version of Bahamut to 2.0.
+Fixed truncating messages in global/global and global/server.
+Improved building Anope for use as a system package.
+Updated the Turkish translation.
-Anope Version 1.9.0
--------------------
-F Modified compile to use g++
-F Improve protocol modules support (classes, virtual methods, etc)
-F Move core services to use BotInfo
-F Move BotInfo and related methods into a class
-F Move modules into a class
-F Fixed ns resending of passcode issue
-F Modules now delete themselves
-F additional field where users' masked host can be stored so both masked IP and vhost are available instead of just one.
-F No struct Uid, ugly, and, unnecessary that we store UID in BotInfo.
-F Prevent deletion of core services via /bs bot
-F Module subsystem cleanup ('modules' branch)
-F Move modules to use classes somewhat (AnopeInit, AnopeFini)
-F Change MODULE_INIT to return a pointer
-F Remove duplicate module creation.. have loadModule return a pointer rather than creating one
-F Remove buffered loading/unloading, this makes os_modunload perm, but who cares
-F Remove 'delayed' loading, this is necessary because of before/after connected to ircd (ircd is before, rest after), I'm sure this can be done better.
-A Remove old config, replace with insp-inspired (albeit bind format) config (CBX)
-F Clean up protocol modules a bit
-A InspIRCd 1.2 support
-F Remove old (prior to 1.8.0) db compat
-F Establish a proper base for services pseudoclients
-F Add ss_main StatServ Hal9000 to play with :)
-F Burn automake with fire (CBX)
+Anope Version 2.1.4
+-------------------
+Added a check for a non-deprecated encryption module on start.
+Added a way for protocol modules to report an error to the uplink.
+Added more account settings to the webcpanel.
+Added self-test functionality for all encryption modules.
+Added support for challenge authentication on InspIRCd.
+Added support for importing databases from Atheme.
+Added support for sending client tags on UnrealIRCd.
+Added support for the InspIRCd 1206 (v4) protocol.
+Added the --nopid option to disable writing a pid file.
+Added the enc_argon2 module to encrypt passwords with Argon2.
+Added the enc_sha2 module to encrypt passwords with HMAC-SHA-2.
+Added the global/queue command for queueing multi-line messages.
+Added the global/server command for sending messages to an individual server.
+Added the PASSWORD category to operserv/stats to view password encryption methods.
+Added the verify-only enc_posix module to validate passwords from Atheme that were encrypted with Argon2.
+Changed nickserv/drop to use confirmation codes to confirm a nickname drop.
+Changed various paths to be relative to the data and config directories.
+Converted some IRCDProto member functions to variables.
+Converted the enc_md5, enc_none, enc_old, enc_sha1, and enc_sha256 modules to be verify-only.
+Deduplicated page headers and footers in the webcpanel templates.
+Deprecated the enc_sha256 module.
+Fixed inconsistent spelling/casing of email, vhost, and vident.
+Fixed various bugs in the inspircd module.
+Improved portability of email sending.
+Improved protocol debug messages.
+Improved the performance and reliability of internal conversion logic.
+Improved the randomness of randomly generated numbers.
+Refactored the enc_bcrypt module and exposed it as an encryption context.
+Removed several duplicate translation strings.
+Replaced the custom MD5 implementation in enc_md5 with a vendored one.
+Replaced the custom SHA256 implementation in enc_sha256 with a vendored one.
+The ldap_authentication, ldap_oper, sql_authentication, sql_log, and sql_oper modules are now always enabled.
+
+Anope Version 2.1.3
+-------------------
+Added alternate command suggestions when a user runs an invalid command.
+Added support for the IRCv3 +draft/channel-context tag.
+Added support for the IRCv3 +draft/reply tag.
+Allow using more than one fingerprint in an oper block.
+Changed chanserv/drop to use confirmation codes to confirm a channel drop.
+Cleaned up more of the codebase to use Modern C++17.
+Enabled using more field limits sent by the IRC server instead of requiring the user to configure them.
+Fixed NickServ lying about the minimum password length.
+Fixed a crash when sending emails.
+Fixed bs_kick not using the correct kick message for automatic kicks.
+Increased the security of randomly generated confirmation codes.
+Removed the ns_access module and associated cs_secure and ns_secure options.
+Removed the ns_status module.
+Reworked how messages are sent in protocol modules to allow sending message tags.
+
+Anope Version 2.1.2
+-------------------
+Bumped the minimum OpenSSL version to 1.1.0.
+Bumped the minimum GnuTLS version to 3.0.0.
+Disabled SSLv3 support in the m_ssl_openssl module.
+Modernized mutex and thread code to use Modern C++.
+Normalised the program exit codes.
+Updated the Dutch translation.
+Updated the French translation.
-Provided by mooncup <mooncup@anonnet.org> - 2009
-F Automatically reapply vhost on hs off for unreal.
+Anope Version 2.1.1
+-------------------
+Added the UNBANME privilege to allow users to unban themselves.
+Fixed building on Windows systems without chgrp/chmod.
+Fixed creating sockets in the m_dns, m_httpd, m_proxyscan, and m_redis modules.
+Fixed reading the values of command line arguments.
+Moved core privilege descriptions to the example configs.
+Updated the Italian translation.
+Updated the Polish translation.
+
+Anope Version 2.1.0
+-------------------
+Added support for access list entry descriptions.
+Added support for linking over a UNIX socket.
+Added support for server-initiated logins and logouts on UnrealIRCd.
+Added support for server-initiated logouts on InspIRCd.
+Added support for the ANONYMOUS SASL mechanism.
+Allowed users to opt-out of being added to channel access lists.
+Cleaned up the codebase to use Modern C++17.
+Modernized the build system to use a modern version of CMake.
+Removed support for using insecure encryption methods as the primary method.
+Removed the Windows-only anopesmtp tool.
+Removed the two day X-line cap.
+Updated all references to IRCServices to refer to Anope instead.
diff --git a/docs/Changes.conf b/docs/Changes.conf
index 14574cc88..c1a1c118b 100644
--- a/docs/Changes.conf
+++ b/docs/Changes.conf
@@ -1,244 +1,109 @@
-Anope Version 2.0.18-git
+Anope Version 2.1.12-git
------------------------
No significant changes.
-Anope Version 2.0.17
+Anope Version 2.1.11
--------------------
-No significant changes.
-
-Anope Version 2.0.16
---------------------
-No significant changes.
-
-Anope Version 2.0.15
---------------------
-No significant changes.
-
-Anope Version 2.0.14
---------------------
-Added mail:content_type to allow customizing the content type of emails.
-
-Anope Version 2.0.13
---------------------
-No significant changes.
+Moved {ns_set}:allowkillimmed to {ns_set_kill}:allowkillimmed.
+Moved nickserv/set/kill and nickserv/saset/kill to the ns_set_kill module.
+Replaced {nickserv}:guestnickprefix with {nickserv}:guestnick.
-Anope Version 2.0.12
+Anope Version 2.1.10
--------------------
-Added the regex_pcre2 module
+Added options:servicealias.
+Moved nickserv/set/message and nickserv/saset/message to the ns_set_message module.
+Removed options:useprivmsg.
+Removed options:usestrictprivmsg.
-Anope Version 2.0.11
---------------------
-No significant changes.
-
-Anope Version 2.0.10
---------------------
-No significant changes.
-
-Anope Version 2.0.9
+Anope Version 2.1.9
-------------------
No significant changes.
-Anope Version 2.0.8
--------------------
-Fix ns_register:unconfirmedexpire not being used
-
-Anope Version 2.0.7
--------------------
-Add nickserv/recover permission
-Add inspircd3 protocol module
-Add default permission for chanstats saset chanstats command
-
-Anope Version 2.0.6
--------------------
-Mark enc_md5 and enc_sha1 as deprecated. Their use has been discouraged for years, and they will be removed in a future release.
-Exempt all of 127.0.0.0/8 from m_dnsbl by default
-Load m_sasl by default
-Fix documentation for nickserv default option ns_keep_modes
-
-Anope Version 2.0.5
--------------------
-No significant changes.
-
-Anope Version 2.0.4
--------------------
-Removed m_sasl_dh-aes and m_sasl_dh-blowfish
-
-Anope Version 2.0.3
--------------------
-Add operserv/chankill to default globops log
-Add ns_identify:maxlogins to limit the max number of concurrent logins per account
-Document ns_no_expire nickserv default
-Remove default session exception expiry time
-
-Anope Version 2.0.2
--------------------
-Add an operserv/oper/modify privilege, required to use oper add and oper del
-Add a chanserv/access/list privilege, which allow readonly access to ChanServ access and akick lists
-Changed m_dnsbl's result configuration to be more extensible
-Add 'max' setting to cs_mode
-Add 'nickchars' setting to networkinfo
-Add 'botserv/fantasy', 'chanserv/access/list', and 'operserv/oper/modify' oper privileges
-Fix 'emailchange_message' to include the proper email address
-Set a default permission on operserv/defcon
-
-Anope Version 2.0.1
--------------------
-Add MUTE command to BotServ fantasy configuration
-Document memo_mail option in nickserv.conf
-Add 'show' setting to ns_info and cs_info to control which fields are shown to non opers
-
-Anope Version 2.0.0
--------------------
-options:passlen, enforceruser, enforcerhost, releasetimeout, and guestnickprefix moved to nickserv's module configuration
-options:hideregisteredcommands added
-m_ssl renamed to m_ssl_openssl
-mail:restrict removed
-
-Anope Version 1.9.9
--------------------
-There is not many config changes between 1.9.8 and 1.9.9, however many of the
-options have been moved around to make more sense, too many to list here,
-so get a new config.
-
-Anope Version 1.9.8
--------------------
-networkinfo:chanlen added
-options:user and options:group added
-nickserv:modesonid added to set modes on everyone who identifies
-nickserv:kill and nickserv:killquick added to configure NickServ's kill timeout
-nickserv:restoreonrecover added to try to restore a user's session after a ghost
-command:group added
-fantasy block added
-dns block has been moved to modules.conf as a part of m_dns
-
-Anope Version 1.9.7
--------------------
-operserv:notifications removed in favor of log{} blocks
-options:regexengine added
-options:casemap added
-chanserv:require added
-nickserv:registration added, emailregistration removed.
-nickserv:unregistered_notice added
-
-Anope Version 1.9.6
--------------------
-service:channels added to join services to channels
-mail block modified to allow configuring of email messages
-oper:host and oper:vhost added
-oper:require_oper added
-options:nonicknameownership added
-operserv:akillids added
-nickserv/access oper privilege added
-
-Anope Version 1.9.5
--------------------
-Don't even try it, get a new config and start over.
-
-Anope Version 1.9.4
--------------------
-** ADDED CONFIGURATION DIRECTIVES **
-memoserv:modules added ms_ignore
-chanserv:modules added cs_clone and cs_mode
-nickserv:suspendexpire and nickserv:forbidexpire added
-chanserv:suspendexpire and chanserv:forbidexpire added
-module added cs_entrymsg
-nickserv:modules added ns_ajoin, ns_cert
-options:nomlock added
-log:target added globops
-nickserv:confirmemailchanges added
-operserv:modules added os_config, os_login
-
-** MODIFIED CONFIGURATION DIRECTIVES **
-operserv:notifications removed osglobal, osmode, oskick, osakill, ossnline, ossqline, osszline, osnoop, osjupe, getpass, setpass, forbid, drop
-renamed nickserv:preregexpire to nickserv:unconfirmedexpire
-
-** DELETED CONFIGURATION DIRECTIVES **
-opertype:commands removed operserv/umode
-operserv:modules removed os_umode
-
-Anope Version 1.9.3
--------------------
-** ADDED CONFIGURATION DIRECTIVES **
-nickserv/auspex privilege added
-SSL module added for SSL support
-opertype:inherits added to allow opertypes to inherit commands and privs from other opertypes
-Various nickserv/saset/* and chanserv/saset/* opertype command privileges added
-nickserv:modules added many new ns_set_command modules
-chanserv:modules added many new cs_set_command modules
-opertype:commands added nickserv/saset/* and chanserv/saset/*
-options:socketengine added to choose what socket engine to use
-module:cs_set_misc and module:ns_set_misc added to replace the old set url/icq/email modules
-options:hideprivilegedcommands added to hide privileged commands from normal users
-log block added to customize logging
-dns block added to configure dns settings
-m_dnsbl added
-mysql configuration block added
-
-** MODIFIED CONFIGURATION DIRECTIVES **
-opertype:commands changed operserv/sgline to opserv/snline
-operserv:modules changed os_sgline to os_snline
-operserv:modules added os_modreload
-operserv:sglineexpiry changed to operserv:snlineexpiry
-operserv:killonsgline changed to operserv:killonsnline
-operserv:notifications ossgline changed ossnline
-memoserv was made optional
-moved operserv:global configuration into its own global block
-chanserv was made optional
-
-** DELETED CONFIGURATION DIRECTIVES **
-serverinfo:helpchannel removed because it has been readded in m_helpchan
-networkinfo:logchannel, logbot, logusers, logmaxusers, logchannel, and options:keeplogs removed because of the log block
-dumpcore because it really didn't do anything
-
-Anope Version 1.9.2
--------------------
-** ADDED CONFIGURATION DIRECTIVES **
-options:enablelogchannel added to auto turn on the logchannel on startup
-options:mlock added to configure the default mlock modes on new channels
-options:database added for the database modules
-options:botmodes added to configure modes BotServ bots should use
-options:userlen added to configure maximum ident length
-options:hostlen added to configure maximum hostname length
-options:database added to configure what database modules to use
-options:passlen added to specify the maximum length of passwords
-uplink:ipv6 added to enable IPv6 connectivity
-options:maxretries added to specify the number of reconnect attempts allowed
-options:retrywait added to specify how long to wait between reconnect attempts
-opertype command chanserv/aop/list removed as it was unnecessary, use chanserv/access/list instead
-
-** MODIFIED CONFIGURATION DIRECTIVES **
-options:encryption added enc_sha256
-chanserv:modules added cs_unban
-nickserv:modules added ns_resetpass
-
-** DELETED CONFIGURATION DIRECTIVES **
-nickserv:database deleted because of new database system
-nickserv:prenickdatabase deleted because of new database system
-chanserv:database deleted because of the new database system
-botserv:database deleted because of the new database system
-hostserv:database deleted because of the new database system
-operserv:database deleted because of the new database system
-operserv:newsdatabase deleted because of the new database system
-operserv:exceptiondatabase deleted because of the new database system
-hs_request:database deleted because of the new database system
-os_ignore:database deleted because of the new database system
-serverinfo:localport deleted
-
-Anope Version 1.9.1
--------------------
-** ADDED CONFIGURATION DIRECTIVES **
-Opertypes have been added, through the opertype blocks.
-Services Operators are now specified in the oper blocks.
-
-** MODIFIED CONFIGURATION DIRECTIVES **
-botserv:modules no longer contains bs_fantasy* modules, fantasy is now seamless.
-operserv:modules has replaced os_logonnews, os_opernews, and os_randomnews with os_news.
-operserv:modules no longer contains os_admin and os_oper modules, removed in favor of oper blocks.
-operserv:notifications no longer contains osraw due to removal of OS RAW.
-
-** DELETED CONFIGURATION DIRECTIVES **
-Nick tracking has been removed as an option.
-Restricting of NS GETPASS and CS GETPASS removed in favor of opertypes.
-Host Setters were removed in favor of opertypes.
-HelpServ has been removed entirely.
-operserv:disableraw removed due to removal of OS RAW.
+Anope Version 2.1.8
+-------------------
+Added {nickserv}:preservedisplay.
+Added the nickserv/drop/display oper privilege.
+
+Anope Version 2.1.7
+-------------------
+Moved nickserv/set/language and nickserv/saset/language to the ns_set_language module.
+Renamed {cs_suspend}:expire to {cs_suspend}:suspendexpire.
+Renamed the FANTASIA privilege to FANTASY.
+
+Anope Version 2.1.6
+-------------------
+Added {ns_cert}:automatic (defaults to yes).
+Removed {hybrid,inspircd,solanum,unrealircd}:use_server_side_mlock (now always enabled).
+Removed {inspircd}:use_server_side_topiclock (now always enabled).
+
+Anope Version 2.1.5
+-------------------
+Added the nickserv/drop/override and chanserv/drop/override oper privileges.
+
+Anope Version 2.1.4
+-------------------
+Added the db_atheme module.
+Added the enc_argon2 module.
+Added the enc_posix module.
+Added the enc_sha2 module.
+Added the gl_queue module.
+Added the gl_server module.
+Added the global/queue operator privilege.
+Added the global/server operator privilege.
+Changed serverinfo:motd to be relative to the config directory.
+Changed serverinfo:pid to be relative to the data directory.
+Changed the default value of mail:sendmailpath to "/usr/sbin/sendmail -it".
+Changed the default value of {chanserv}:accessmax to 1000.
+Changed the default value of {chanserv}:inhabit to 1 minute.
+Changed the default value of {cs_mode}:max to 50.
+Changed the default value of {ms_ignore}:max to 50.
+Removed options:seed.
+Replaced {webcpanel}:template with {webcpanel}:template_dir.
+
+
+Anope Version 2.1.3
+-------------------
+Added options:didyoumeandifference.
+Added support for multiple SSL fingerprints in oper:certfp.
+Added the chanserv/cert oper privilege for modifying other user's certificate lists.
+Changed networkinfo:chanlen to default to 32 if not set.
+Changed networkinfo:hostlen to default to 64 if not set.
+Changed networkinfo:modelistsize to default to 100 if not set.
+Changed networkinfo:nicklen to default to 31 if not set.
+Changed networkinfo:userlen to default to 10 if not set.
+Increased the default maximum password length to 50 characters.
+Increased the default minimum password length to 10 characters.
+Removed the cs_secure option in {chanserv}:defaults (now always enabled).
+Removed the nickserv/saset/secure command.
+Removed the nickserv/saset/secure oper privilege.
+Removed the nickserv/set/secure command.
+Removed the nickserv/status command.
+Removed the ns_access module.
+Removed the ns_secure option in {nickserv}:defaults (now always enabled).
+
+Anope Version 2.1.2
+-------------------
+Added {ssl_openssl}:tlsv10 for configuring whether TLSv1.0 is usable (defaults to no).
+Added {ssl_openssl}:tlsv11 for configuring whether TLSv1.1 is usable (defaults to yes).
+Added {ssl_openssl}:tlsv12 for configuring whether TLSv1.2 is usable (defaults to yes).
+Removed {ssl_openssl}:sslv3 (now always disabled).
+Removed the m_ prefix from the names of the chanstats, dns, dnsbl, helpchan, httpd, ldap, ldap_oper, mysql, proxyscan, redis, regex_pcre2, regex_posix, regex_stdlib, regex_tre, rewrite, sasl, sql_log, sql_oper, sqlite, ssl_gnutls, ssl_openssl, xmlrpc, and xmlrpc_main modules.
+
+Anope Version 2.1.1
+-------------------
+Added the m_regex_stdlib module.
+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 as it is 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 the charybdis module to solanum.
+Renamed the inspircd3 module to inspircd.
+Renamed the unreal4 module to unrealircd.
+Replaced uplink:ipv6 with uplink:protocol.
diff --git a/docs/DEFCON b/docs/DEFCON
index aaf2d8a26..16fe2388b 100644
--- a/docs/DEFCON
+++ b/docs/DEFCON
@@ -10,7 +10,7 @@ Anope DefCon
1) Introduction
- Anope 1.6 onwards supports a unique protection mechanism based on the
+ Anope supports a unique protection mechanism based on the
military "Defense Readiness Condition" (DefCon) system. It is based on
5 levels of defense readiness defined as:
@@ -23,7 +23,7 @@ Anope DefCon
These are configurable levels that mandates what actions Anope should
take in case of emergency and change in readiness status.
- It is used to prevent abuse to both Services, and the ircd on which they
+ It is used to prevent abuse to both Anope, and the IRCd on which they
are running. Also to protect the users, primarily in the event of Clones
and/or FloodBOT attacks.
@@ -50,8 +50,8 @@ Anope DefCon
Force Chan Mode
Use Reduced Session Limit
KILL any new clients trying to connect
- Services will ignore everyone but opers
- Services will silently ignore everyone but opers
+ Ignore everyone but opers
+ Silently ignore everyone but opers
AKILL all new clients trying to connect
No new memos sent to block MemoServ attacks
diff --git a/docs/EVENTS b/docs/EVENTS
deleted file mode 100644
index 54e9c87a5..000000000
--- a/docs/EVENTS
+++ /dev/null
@@ -1,34 +0,0 @@
-Anope Internal Events
----------------------
-
-1) Intro
-2) Using Events
-
-1) Introduction to Internal Events
-
- Internal Events are setup to give module developers more information
- about what the core is doing at different times. This information can
- be as complex as data we are feeding to the uplink, to simple triggered
- events such as the databases being saved.
-
- Additionally there is a module included with the core
- which can provide some clue as to how to use the code in your modules.
- The rest of this document assumes that you are used to writing modules.
-
-2) Using Events
-
- Each Event in Anope calls a function.
- You must override these functions in your main modules class.
- The full list of functions and parameters are in modules.h. In this
- case, you would be overriding OnJoinChannel() and OnPartChannel() like so:
-
- void OnJoinChannel(User *u, Channel *c) anope_override { }
- void OnPartChannel(User *u, Channel *c) anope_override { }
-
- Some of these event overrides can be used to prevent or allow things to
- happen that would normally not be allowed or denied. You can also use
- ModuleManager (not explained here) to set control which order the modules
- are queried (when multiple modules hook to the same event).
-
- The "anope_override" identifier is for compatibility with C++11.
- Its usage is highly recommended.
diff --git a/docs/INSTALL b/docs/INSTALL
index 6835f24cd..305295331 100644
--- a/docs/INSTALL
+++ b/docs/INSTALL
@@ -37,7 +37,7 @@ Note: You should also read the README and FAQ files!
Next, unpack the package in your home directory, and go into the created
directory.
- If there are any extra modules you want to enable, such as m_mysql, run
+ If there are any extra modules you want to enable, such as mysql, run
the 'extras' script to enable them. If you do not know you can come back
later and enable them.
@@ -52,8 +52,8 @@ Note: You should also read the README and FAQ files!
cause trouble on your network if passwords are not encrypted, or read
the memos of any user.
- Now go into the conf directory (by default, ~/services/conf). Copy the example
- configuration file (example.conf) to services.conf, and open the latter
+ Now go into the conf directory (by default, ~/anope/conf). Copy the example
+ configuration file (anope.example.conf) to anope.conf, and open the latter
with your favorite text editor. It contains all the configuration
directives Anope will use at startup. Read the instructions contained in
the file carefully. Using the default values is NOT a good idea, and will
@@ -71,11 +71,11 @@ Note: You should also read the README and FAQ files!
* IMPORTANT: Back up your old databases!
* If you are upgrading to a new major release, ALWAYS restart a
- fresh configuration file from example.conf.
+ fresh configuration file from anope.example.conf.
3) Setting up the IRCd
- Services acts as an IRC server with pseudo-clients on it. To link them to
+ Anope acts as an IRC server with pseudo-clients on it. To link them to
your network, you'll need to configure your IRCd to allow services to link.
The configuration varies depending on the IRCd, but you will probably need
@@ -83,7 +83,7 @@ Note: You should also read the README and FAQ files!
a shared block), and be sure that the IRCd is listening on the given port
in the link block.
- Example link configurations can be found in example.conf for some of the
+ Example link configurations can be found in anope.example.conf for some of the
popular IRCds.
Don't forget to /rehash your IRCd to apply changes.
@@ -91,16 +91,16 @@ Note: You should also read the README and FAQ files!
4) Starting Anope
Go into the directory where binaries were installed (by default, this is
- ~/services/bin). Type ./services to launch Anope.
+ ~/anope/bin). Type ./anope to launch Anope.
If there are syntax errors in the configuration file they will be
displayed on the screen. Correct them until there are no errors anymore.
A successful startup won't generate any message.
- Give Services at least one minute to link to your network, as certain
+ Give Anope at least one minute to link to your network, as certain
IRCds on some OSes may be really slow for the link process. If nothing
happens after about a minute, it is probably a configuration problem. Try
- to launch Anope with ./services -debug -nofork to see any errors that it
+ to launch Anope with ./anope -debug -nofork to see any errors that it
encounters, and try to correct them.
If you need help to solve errors, feel free to subscribe to the Anope
@@ -111,17 +111,17 @@ Note: You should also read the README and FAQ files!
A crontab entry will allow you to check periodically whether Anope is
still running, and restart it if not.
- First rename the example.chk script that is in Anope path (by default,
- this is ~/services/conf) to services.chk and edit it. You'll need to
+ First rename the cron.example.sh script that is in Anope path (by default,
+ this is ~/anope/conf) to cron.sh and edit it. You'll need to
modify the CONFIGURATION part of the file. Then ensure that the file is
- marked as executable by typing chmod +x services.chk, and try to launch the
+ marked as executable by typing chmod +x cron.sh, and try to launch the
script to see if it works (Anope must not be running when you do this ;))
When this is done, you'll have to add the crontab entry. Type crontab -e.
This will open the default text editor with the crontab file. Enter the
following (with correct path):
- */5 * * * * /home/ircd/services/conf/services.chk >/dev/null 2>&1
+ */5 * * * * /home/ircd/anope/conf/cron.sh >/dev/null 2>&1
The */5 at the beginning means "check every 5 minutes". You may replace
the 5 with other another number if you want (but less than 60). Consult
diff --git a/docs/INSTALL.fr b/docs/INSTALL.fr
index e4fa167dd..e8cfd8feb 100644
--- a/docs/INSTALL.fr
+++ b/docs/INSTALL.fr
@@ -37,7 +37,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
Ensuite, décompressez le package dans votre répertoire home, et allez
dans le répértoire qui vient d'être créé.
- Si il y a des modules facultatifs que vous voulez activer comme m_mysql,
+ Si il y a des modules facultatifs que vous voulez activer comme mysql,
exécuter le script 'extras' pour les activer. Si vous ne savez pas, vous
pouvez les activer plus tard.
@@ -49,15 +49,15 @@ Note : Vous devrez également lire les fichiers README et FAQ !
Allez dans le dossier build (cd build) et tapez make et make install.
Ceci va installer tous les fichiers nécessaires dans les dossiers que
vous avez indiqués avec le script Config et régler les permissions des
- fichiers. Vous devez vous assurer que le répertoire data n'est pas
+ fichiers. Vous devez vous assurer que le répertoire data n'est pas
accessible par les autres utilisateurs, car des utilisateurs
malveillants pourraient causer des problèmes sur votre réseau, si les
mots de passe ne sont pas chiffrés, ou lire les mémos de tous les
utilisateurs.
- Allez maintenant dans le répertoire conf (par défaut, ~/services/conf).
- Copiez l'exemple de fichier de configuration (example.conf) en
- services.conf et ouvrez ce dernier avec votre éditeur de texte favori.
+ Allez maintenant dans le répertoire conf (par défaut, ~/anope/conf).
+ Copiez l'exemple de fichier de configuration (anope.example.conf) en
+ anope.conf et ouvrez ce dernier avec votre éditeur de texte favori.
Il contient toutes les directives de configuration qu'Anope va utiliser
en démarrant. Lisez attentivement les instructions contenues dans le
fichier. L'utilisation des valeurs par défaut n'est pas toujours
@@ -78,11 +78,11 @@ Note : Vous devrez également lire les fichiers README et FAQ !
* IMPORTANT : Sauvegardez vos anciennes bases de données !
* Si vous mettez à jour vers une nouvelle version majeure,
recommencez *toujours* toute votre configuration à partir du
- fichier example.conf.
+ fichier anope.example.conf.
3) Configuration de l'IRCd
- Les Services agissent comme un serveur IRC avec des pseudo-clients.
+ Anope agit comme un serveur IRC avec des pseudo-clients.
Pour les relier à votre réseau, vous aurez besoin de configurer votre
IRCd pour permettre aux services de se connecter.
@@ -92,14 +92,14 @@ Note : Vous devrez également lire les fichiers README et FAQ !
sur le port donné dans le bloc link.
Des exemples de configurations de bloc link peuvent être trouvés dans
- le fichier example.conf pour certains des IRCd les plus populaires.
+ le fichier anope.example.conf pour certains des IRCd les plus populaires.
Souvenez-vous de /rehash votre IRCd pour appliquer les changements.
4) Mettre en route Anope
Allez dans le répertoire où les fichiers binaires ont été installés
- (par défaut, ~/services/bin). Tapez ./services pour lancer Anope.
+ (par défaut, ~/anope/bin). Tapez ./anope pour lancer Anope.
S'il y a des erreurs de syntaxe dans le fichier de configuration, elles
seront affichées à l'écran. Corrigez-les jusqu'à ce qu'il n'y en ait
@@ -109,7 +109,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
réseau, car certains IRCds sur certains systèmes peuvent être très
lents pour le processus de liaison. Si rien ne se passe après environ
une minute, il y a probablement un problème de configuration. Essayez
- de lancer Anope en mode debug avec ./services -debug -nofork pour voir
+ de lancer Anope en mode debug avec ./anope -debug -nofork pour voir
toutes les erreurs rencontrées et essayez de les corriger.
Si vous avez besoin d'aide pour résoudre des erreurs, n'hésitez pas à
@@ -121,11 +121,11 @@ Note : Vous devrez également lire les fichiers README et FAQ !
Une entrée crontab vous permettra de vérifier périodiquement si Anope
est toujours en cours d'exécution et de le redémarrer s'il n'est pas.
- D'abord renommez le script example.chk qui est dans les dossiers
- d'Anope (par défaut, ~/services/conf) en services.chk et modifiez-le.
+ D'abord renommez le script cron.example.sh qui est dans les dossiers
+ d'Anope (par défaut, ~/anope/conf) en cron.sh et modifiez-le.
Vous aurez besoin de modifier la partie CONFIGURATION du fichier.
Assurez-vous ensuite que le fichier est marqué comme exécutable en
- tapant chmod +x services.chk et essayez de lancer le script pour voir
+ tapant chmod +x cron.sh et essayez de lancer le script pour voir
si cela fonctionne (Anope ne doit pas être en marche lorsque vous
testez cela ;))
@@ -133,7 +133,7 @@ Note : Vous devrez également lire les fichiers README et FAQ !
crontab -e. Cela va ouvrir l'éditeur de texte par défaut avec le
fichier crontab. Entrez la ligne suivante (avec le chemin correct) :
- */5 * * * * /home/ircd/services/conf/services.chk > /dev/null 2>&1
+ */5 * * * * /home/ircd/anope/conf/cron.sh > /dev/null 2>&1
Le */5 au début signifie "vérifier toutes les 5 minutes". Vous pouvez
remplacer le 5 par un autre numéro si vous voulez (mais moins de 60).
diff --git a/docs/LANGUAGE b/docs/LANGUAGE
index a98440e8b..ae7dfc6ab 100644
--- a/docs/LANGUAGE
+++ b/docs/LANGUAGE
@@ -28,14 +28,14 @@ Anope Multi Language Support
Anope uses gettext (https://www.gnu.org/software/gettext/) to translate messages for users. To add a new language
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 services.conf.
+ 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).
If you have finished a language file translation and you want others to use it, please send it to team@anope.org
- (don't forget to mention clearly your (nick)name, your e-mail and the language name). You'll of course get full credit for it.
+ (don't forget to mention clearly your (nick)name, your email and the language name). You'll of course get full credit for it.
NOTE: There is no guarantee we will use your work so please do not be offended if we say no thanks.
diff --git a/docs/MODULES b/docs/MODULES
index 845bf25fd..e22ab3d7d 100644
--- a/docs/MODULES
+++ b/docs/MODULES
@@ -12,7 +12,7 @@ Anope Modules
1) Introduction
- Anope 1.6 onwards supports external modules. External modules are pieces
+ Anope supports external modules. External modules are pieces
of code that can be attached to a running Anope process dynamically. These
modules can serve several purposes, and perform all kind of operations to
enhance your network.
@@ -22,7 +22,7 @@ Anope Modules
1. If modules are supported by your system, they will be configured
automatically when you run ./Config. The modules will be installed
to the modules directory in your data path (by default this will
- be ~/services/data/modules).
+ be ~/anope/data/modules).
2. Compile Anope as usual using ./Config. The "make" process will now
compile module support into Anope, and compile the default sample
@@ -98,7 +98,7 @@ Anope Modules
1. Make sure you're in the main source directory. (usually anope-1.X.XX/)
2. Run ./Config to find and configure modules, then `cd build`.
3. Run `make` to compile Anope, and any modules.
- 4. Run `make install` to copy the compiled binaries to the ~/services/
+ 4. Run `make install` to copy the compiled binaries to the ~/anope/
directory.
You can now use /msg OperServ MODLOAD to load the new modules.
diff --git a/docs/NEWS b/docs/NEWS
deleted file mode 100644
index 07911e66c..000000000
--- a/docs/NEWS
+++ /dev/null
@@ -1,6 +0,0 @@
-Highlighted News in Anope 1.9
-=============================
-
-* Added in live updating SQL and the ability to execute commands through SQL
-* Re-designed configuration file
-* Code refresh / rewrite into C++
diff --git a/docs/README b/docs/README
index 68b8ba78d..94883daf0 100644
--- a/docs/README
+++ b/docs/README
@@ -1,7 +1,7 @@
Anope -- a set of IRC services for IRC networks
-----------------------------------------------
-Anope is 2003-2024 Anope Team <team@anope.org>.
+Anope is 2003-2025 Anope Team <team@anope.org>.
Based on Epona 2000-2002 PegSoft <epona@pegsoft.net>.
Based on Services 1996-1999 Andrew Church <achurch@achurch.org>.
@@ -120,7 +120,7 @@ Table of Contents
2) Presentation
- Anope is a set of Services for IRC networks that allows users to manage
+ Anope is a set of services for IRC networks that allows users to manage
their nicks and channels in a secure and efficient way, and administrators
to manage their network with powerful tools.
@@ -166,14 +166,14 @@ Table of Contents
Anope currently works with:
- * Bahamut 1.4.27 or later (including 1.8)
- * Charybdis 3.4 or later
+ * Bahamut 2.0 or later
+ * InspIRCd 3 or later
* ircd-hybrid 8.2.23 or later
- * InspIRCd 1.2 or later
+ * ircd-ratbox 3 or later
* ngIRCd 19.2 or later
* Plexus 3 or later
- * Ratbox 2.0.6 or later
- * UnrealIRCd 3.2 or later
+ * Solanum (all versions)
+ * UnrealIRCd 6 or later
Anope could also work with some of the daemons derived by the ones listed
above, but there's no support for them if they work or don't work.
@@ -225,7 +225,7 @@ Table of Contents
the log file; if you send a bug report, PLEASE include an excerpt from
the log file WITH DEBUGGING ACTIVE; we cannot emphasize enough how
important this is to tracking down problems. (You can also enable
- debugging while Services is running using OperServ's SET DEBUG command.)
+ debugging while Anope is running using OperServ's SET DEBUG command.)
If you repeat use --debug=<level>, the debugging level will be increased,
which provides more detailed information but may also slow Anope down
considerably and make the log file grow dramatically faster. In general,
diff --git a/docs/REDIS b/docs/REDIS
index 8f7a076fd..603fa034a 100644
--- a/docs/REDIS
+++ b/docs/REDIS
@@ -1,4 +1,4 @@
-Starting in Anope 1.9.9, Anope has Redis database support (https://redis.io/).
+Anope has Redis database support (https://redis.io/).
This document explains the data structure used by Anope, and explains how
keyspace notification works.
@@ -149,12 +149,12 @@ Table of Contents
Which returns a new object ID for me, in this example it will be "8".
Now I can create the object:
- HMSET hash:BotInfo:8 nick redis user redis host services.anope.org realname "Services for IRC Networks"
+ HMSET hash:BotInfo:8 nick redis user redis host services.anope.org realname "Anope IRC Services"
Note if you are using HSET instead of HMSET you will need to use a transaction, as shown in the above example.
If you are watching your services logs you will immediately see:
- USERS: redis!redis@services.anope.org (Services for IRC Networks) connected to the network (services.anope.org)
+ USERS: redis!redis@services.anope.org (Anope IRC Services) connected to the network (services.anope.org)
And the bot redis will be in BotServ's bot list.
Notice how ids:BotInfo and the value keys are updated automatically.
diff --git a/docs/XMLRPC/XMLRPC b/docs/RPC/RPC
index 52f2248a6..a93d61af8 100644
--- a/docs/XMLRPC/XMLRPC
+++ b/docs/RPC/RPC
@@ -1,14 +1,15 @@
-Starting with Anope 1.9.4 XMLRPC using PHP's xmlrpc_encode_request and xmlrpc_decode functions is supported.
+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 XMLRPC calls, provided by m_xmlrpc_main:
+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 XMLRPC.
+ 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.
@@ -21,9 +22,9 @@ opers - Takes no parameters, returns opertypes, their privileges and commands.
notice - Takes three parameters, source user, target user, and message. Sends a message to the user.
-XMLRPC was designed to be used with db_sql, and will not return any information that can be pulled from the SQL
+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/XMLRPC.
+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 the parameter named "id" is reserved for query ID. If you pass a query to Anope containing a value for id. it will
+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.
diff --git a/docs/XMLRPC/xmlrpc.php b/docs/RPC/jsonrpc.php
index ac378811c..dda1412b1 100644
--- a/docs/XMLRPC/xmlrpc.php
+++ b/docs/RPC/jsonrpc.php
@@ -1,23 +1,23 @@
<?php
/**
- * XMLRPC Functions
+ * JSON-RPC functions
*
- * (C) 2003-2024 Anope Team
+ * (C) 2003-2025 Anope Team
* Contact us at team@anope.org
*/
-class AnopeXMLRPC
+class AnopeRPC
{
/**
- * The XMLRPC host
+ * The RPC host
*
* @var string
*/
private $host;
/**
- * Initiate a new AnopeXMLRPC instance
+ * Initiate a new AnopeRPC instance
*
* @param $host
*/
@@ -27,7 +27,7 @@ class AnopeXMLRPC
}
/**
- * Run an XMLRPC command. Name should be a query name and params an array of parameters, eg:
+ * 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.
*
@@ -40,14 +40,19 @@ class AnopeXMLRPC
*/
public function run($name, $params)
{
- $xmlquery = xmlrpc_encode_request($name, $params);
+ $request = json_encode([
+ "jsonrpc" => "2.0",
+ "id" => uniqid(),
+ "method" => $name,
+ "params" => $params,
+ ]);
$context = stream_context_create(["http" => [
"method" => "POST",
- "header" => "Content-Type: text/xml",
- "content" => $xmlquery]]);
+ "header" => "Content-Type: application/json",
+ "content" => $request]]);
$inbuf = file_get_contents($this->host, false, $context);
- $response = xmlrpc_decode($inbuf);
+ $response = json_decode($inbuf, true);
if ($response) {
return $response;
@@ -85,7 +90,7 @@ class AnopeXMLRPC
{
$ret = $this->run("checkAuthentication", [$account, $pass]);
- if ($ret && $ret["result"] == "Success") {
+ if ($ret && array_key_exists("account", $ret)) {
return $ret["account"];
}
@@ -142,4 +147,4 @@ class AnopeXMLRPC
}
}
-$anope = new AnopeXMLRPC("http://127.0.0.1:8080/xmlrpc");
+$anope = new AnopeRPC("http://127.0.0.1:8080/jsonrpc");
diff --git a/docs/TOOLS b/docs/TOOLS
deleted file mode 100644
index 5e8f139cb..000000000
--- a/docs/TOOLS
+++ /dev/null
@@ -1,25 +0,0 @@
-Anope Bundled Tools
--------------------
-
-1) Anope SMTP Client
-
- Provided with Anope is a simple SMTP client which can be used instead of
- programs like SendMail in some cases.
-
- The SMTP client can be used instead of sendmail for use with Anope's mail
- options. To use the SMTP client instead of sendmail, find the line in your
- services configuration file (services.conf) that defines sendmailpath. On
- that line, change the path to your services installation directory, then
- followed by "bin/anopesmtp" and the IP address of a valid SMTP server. It
- should look like this:
-
- sendmailpath = "/home/anope/services/bin/anopesmtp 127.0.0.1"
-
- If the SMTP client doesn't send mail, or if there's an other problem with
- it, you can enable debug mode by passing the --debug flag after the server
- address. This should generate a log file of what happened when it tried
- to connect to the SMTP server.
-
- Credits:
- Originally written by Dominick Meglio <codemastr@unrealircd.com>
- Ported to *nix by Trystan Scott Lee <trystan@nomadirc.net>
diff --git a/docs/WIN32.txt b/docs/WIN32.txt
index 2880cb0e0..bf7153010 100644
--- a/docs/WIN32.txt
+++ b/docs/WIN32.txt
@@ -70,7 +70,7 @@ Anope for Windows
If you cannot find whats causing the error, please visit our forums or
our IRC Support channel for assistance.
- Some Anope modules require third party libraries, such as m_mysql and
+ Some Anope modules require third party libraries, such as mysql and
the SSL modules. If these libraries are installed in nonstandard
locations, cmake will probably not find them and should be told where
they are by passing their location to Config.
@@ -103,7 +103,7 @@ Anope for Windows
INSTALL within the Solution Explorer. Right-click on INSTALL and choose Build.
When you have done this, all the files will be installed to where they belong.
- The only thing you need to do is rename "data/example.conf" to be "data/services.conf",
+ The only thing you need to do is rename "data/anope.example.conf" to be "data/anope.conf",
and then follow the steps to set up Anope.
You have now completed the building phase of Anope for Windows. You can
@@ -120,7 +120,7 @@ Anope for Windows
Notepad will cause strange characters to appear, and you may not be able to
edit the file correctly.
- Open services.conf, and read through it carefully and adjust the settings
+ Open anope.conf, and read through it carefully and adjust the settings
you think you need to adjust.
If you are unsure of the settings, you can go to the dos command prompt
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index a434be6e1..763826344 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -3,7 +3,7 @@ set_source_files_properties(version.cpp PROPERTIES LANGUAGE CXX COMPILE_FLAGS "$
# Generate version-bin executable to modify version.h, setting it's linker flags as well
add_executable(version-bin version.cpp)
set_target_properties(version-bin PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}")
-get_target_property(version_BINARY version-bin LOCATION)
+set(version_BINARY "$<TARGET_FILE:version-bin>")
# Modify version.h from the above executable, with dependencies to version.cpp
# and all of the source files in the main build
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h
@@ -16,49 +16,7 @@ add_to_cpack_ignored_files("${version_BINARY}$" TRUE)
if(NOT WIN32)
add_to_cpack_ignored_files("version.h$" TRUE)
add_to_cpack_ignored_files("build.h$" TRUE)
-endif(NOT WIN32)
-
-set(PCH_SOURCES_GCH "")
-if(USE_PCH AND CMAKE_COMPILER_IS_GNUCXX)
- string(REPLACE " " ";" PCH_CXXFLAGS "${CXXFLAGS} ${CMAKE_CXX_FLAGS}")
-
- file(GLOB PCH_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
- sort_list(PCH_SOURCES)
-
- foreach(PCH_SOURCE ${PCH_SOURCES})
- find_includes(${PCH_SOURCE} INCLUDES)
- set(INCLUDES_LIST)
- append_to_list(INCLUDES_LIST ${PCH_SOURCE})
- foreach(INCLUDE ${INCLUDES})
- # Extract the filename from the #include line
- extract_include_filename(${INCLUDE} FILENAME QUOTE_TYPE)
- if(QUOTE_TYPE STREQUAL "quotes")
- find_in_list(PCH_SOURCES "${FILENAME}" FOUND)
- if(NOT FOUND EQUAL -1)
- append_to_list(INCLUDES_LIST ${FILENAME})
- endif(NOT FOUND EQUAL -1)
- endif(QUOTE_TYPE STREQUAL "quotes")
- endforeach(INCLUDE)
-
- set(PCH_EXTRAFLAGS "")
- if(DEBUG_BUILD)
- set(PCH_EXTRAFLAGS "-g")
- endif(DEBUG_BUILD)
- if(PCH_SOURCE STREQUAL "module.h")
- set(PCH_EXTRAFLAGS ${PCH_EXTRAFLAGS} -fPIC)
- endif(PCH_SOURCE STREQUAL "module.h")
- if(GETTEXT_INCLUDE)
- set(PCH_GETTEXT_INCLUDE "-I${GETTEXT_INCLUDE}")
- endif(GETTEXT_INCLUDE)
-
- set(PCH_SOURCES_GCH "${PCH_SOURCES_GCH};${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch")
- add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch
- COMMAND ${CMAKE_CXX_COMPILER} ARGS ${PCH_CXXFLAGS} ${PCH_EXTRAFLAGS}
- ${PCH_GETTEXT_INCLUDE} -I${CMAKE_CURRENT_BINARY_DIR} -I${Anope_SOURCE_DIR}/modules/pseudoclients ${CMAKE_CURRENT_SOURCE_DIR}/${PCH_SOURCE} -o ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch
- DEPENDS ${INCLUDES_LIST} VERBATIM
- )
- endforeach(PCH_SOURCE ${PCH_SOURCES})
-endif(USE_PCH AND CMAKE_COMPILER_IS_GNUCXX)
+endif()
# Add a custom target to the above file
-add_custom_target(headers DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h ${PCH_SOURCES_GCH})
+add_custom_target(headers DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h)
diff --git a/include/access.h b/include/access.h
index 6b9a2ec63..ad420d785 100644
--- a/include/access.h
+++ b/include/access.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef ACCESS_H
-#define ACCESS_H
+#pragma once
#include "services.h"
#include "anope.h"
@@ -28,7 +27,7 @@ enum
* backing each ChanAccess determines whether that ChanAccess has a given
* privilege.
*/
-struct CoreExport Privilege
+struct CoreExport Privilege final
{
Anope::string name;
Anope::string desc;
@@ -39,10 +38,10 @@ struct CoreExport Privilege
bool operator==(const Privilege &other) const;
};
-class CoreExport PrivilegeManager
+class CoreExport PrivilegeManager final
{
static std::vector<Privilege> Privileges;
- public:
+public:
static void AddPrivilege(Privilege p);
static void RemovePrivilege(Privilege &p);
static Privilege *FindPrivilege(const Anope::string &name);
@@ -53,9 +52,10 @@ class CoreExport PrivilegeManager
/* A provider of access. Only used for creating ChanAccesses, as
* they contain pure virtual functions.
*/
-class CoreExport AccessProvider : public Service
+class CoreExport AccessProvider
+ : public Service
{
- public:
+public:
AccessProvider(Module *owner, const Anope::string &name);
virtual ~AccessProvider();
@@ -64,20 +64,21 @@ class CoreExport AccessProvider : public Service
*/
virtual ChanAccess *Create() = 0;
- private:
+private:
static std::list<AccessProvider *> Providers;
- public:
+public:
static const std::list<AccessProvider *>& GetProviders();
};
/* Represents one entry of an access list on a channel. */
-class CoreExport ChanAccess : public Serializable
+class CoreExport ChanAccess
+ : public Serializable
{
Anope::string mask;
/* account this access entry is for, if any */
Serialize::Reference<NickCore> nc;
- public:
+public:
typedef std::vector<ChanAccess *> Path;
/* The provider that created this access entry */
@@ -85,6 +86,7 @@ class CoreExport ChanAccess : public Serializable
/* Channel this access entry is on */
Serialize::Reference<ChannelInfo> ci;
Anope::string creator;
+ Anope::string description;
time_t last_seen;
time_t created;
@@ -95,8 +97,8 @@ class CoreExport ChanAccess : public Serializable
const Anope::string &Mask() const;
NickCore *GetAccount() const;
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
static const unsigned int MAX_DEPTH = 4;
@@ -105,7 +107,7 @@ class CoreExport ChanAccess : public Serializable
* @param nc The account
* @param next Next channel to check if any
*/
- virtual bool Matches(const User *u, const NickCore *nc, ChannelInfo* &next) const;
+ virtual bool Matches(const User *u, const NickCore *nc, ChannelInfo *&next) const;
/** Check if this access entry has the given privilege.
* @param name The privilege name
@@ -133,9 +135,9 @@ class CoreExport ChanAccess : public Serializable
/* A group of access entries. This is used commonly, for example with ChannelInfo::AccessFor,
* to show what access a user has on a channel because users can match multiple access entries.
*/
-class CoreExport AccessGroup
+class CoreExport AccessGroup final
{
- public:
+public:
/* access entries + paths */
std::vector<ChanAccess::Path> paths;
/* Channel these access entries are on */
@@ -170,5 +172,3 @@ class CoreExport AccessGroup
inline bool empty() const { return paths.empty(); }
};
-
-#endif
diff --git a/include/account.h b/include/account.h
index d84a53dca..487a79b00 100644
--- a/include/account.h
+++ b/include/account.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef ACCOUNT_H
-#define ACCOUNT_H
+#pragma once
#include "extensible.h"
#include "serialize.h"
@@ -18,23 +17,25 @@
#include "memo.h"
#include "base.h"
-typedef Anope::hash_map<NickAlias *> nickalias_map;
-typedef Anope::hash_map<NickCore *> nickcore_map;
-typedef TR1NS::unordered_map<uint64_t, NickCore *> nickcoreid_map;
+typedef Anope::unordered_map<NickAlias *> nickalias_map;
+typedef Anope::unordered_map<NickCore *> nickcore_map;
+typedef std::unordered_map<uint64_t, NickCore *> nickcoreid_map;
extern CoreExport Serialize::Checker<nickalias_map> NickAliasList;
extern CoreExport Serialize::Checker<nickcore_map> NickCoreList;
-extern CoreExport nickcoreid_map NickCoreIdList;
+extern CoreExport Serialize::Checker<nickcoreid_map> NickCoreIdList;
/* A registered nickname.
* It matters that Base is here before Extensible (it is inherited by Serializable)
*/
-class CoreExport NickAlias : public Serializable, public Extensible
+class CoreExport NickAlias final
+ : public Serializable
+ , public Extensible
{
Anope::string vhost_ident, vhost_host, vhost_creator;
- time_t vhost_created;
+ time_t vhost_created = 0;
- public:
+public:
Anope::string nick;
Anope::string last_quit;
Anope::string last_realname;
@@ -42,8 +43,9 @@ class CoreExport NickAlias : public Serializable, public Extensible
Anope::string last_usermask;
/* Last uncloaked usermask, requires nickserv/auspex to see */
Anope::string last_realhost;
- time_t time_registered;
- time_t last_seen;
+ time_t time_registered = Anope::CurTime;
+ time_t last_seen = Anope::CurTime;
+
/* Account this nick is tied to. Multiple nicks can be tied to a single account. */
Serialize::Reference<NickCore> nc;
@@ -54,8 +56,8 @@ class CoreExport NickAlias : public Serializable, public Extensible
NickAlias(const Anope::string &nickname, NickCore *nickcore);
~NickAlias();
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
/** Set a vhost for the user
* @param ident The ident
@@ -63,36 +65,41 @@ class CoreExport NickAlias : public Serializable, public Extensible
* @param creator Who created the vhost
* @param time When the vhost was created
*/
- void SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created = Anope::CurTime);
+ void SetVHost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created = Anope::CurTime);
/** Remove a users vhost
**/
- void RemoveVhost();
+ void RemoveVHost();
/** Check if the user has a vhost
* @return true or false
*/
- bool HasVhost() const;
+ bool HasVHost() const;
/** Retrieve the vhost ident
* @return the ident
*/
- const Anope::string &GetVhostIdent() const;
+ const Anope::string &GetVHostIdent() const;
/** Retrieve the vhost host
* @return the host
*/
- const Anope::string &GetVhostHost() const;
+ const Anope::string &GetVHostHost() const;
+
+ /** Retrieve the vhost mask
+ * @param the mask
+ */
+ Anope::string GetVHostMask() const;
/** Retrieve the vhost creator
* @return the creator
*/
- const Anope::string &GetVhostCreator() const;
+ const Anope::string &GetVHostCreator() const;
/** Retrieve when the vhost was created
* @return the time it was created
*/
- time_t GetVhostCreated() const;
+ time_t GetVHostCreated() const;
/** Finds a registered nick
* @param nick The nick to lookup
@@ -105,13 +112,15 @@ class CoreExport NickAlias : public Serializable, public Extensible
* account's display.
* It matters that Base is here before Extensible (it is inherited by Serializable)
*/
-class CoreExport NickCore : public Serializable, public Extensible
+class CoreExport NickCore final
+ : public Serializable
+ , public Extensible
{
/* 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;
- public:
+public:
/* Name of the account. Find(display)->nc == this. */
Anope::string display;
/* User password in form of hashm:data */
@@ -119,9 +128,10 @@ class CoreExport NickCore : public Serializable, public Extensible
Anope::string email;
/* Locale name of the language of the user. Empty means default language */
Anope::string language;
- /* Access list, contains user@host masks of users who get certain privileges based
- * on if NI_SECURE is set and what (if any) kill protection is enabled. */
- std::vector<Anope::string> access;
+ /* Last time an email was sent to this user */
+ time_t lastmail = 0;
+ /* The time this account was registered */
+ time_t time_registered = Anope::CurTime;
MemoInfo memos;
std::map<Anope::string, Anope::string> last_modes;
@@ -131,14 +141,14 @@ class CoreExport NickCore : public Serializable, public Extensible
Serialize::Checker<std::vector<NickAlias *> > aliases;
/* Set if this user is a services operator. o->ot must exist. */
- Oper *o;
+ Oper *o = nullptr;
/* Unsaved data */
+ /** The display nick for this account. */
+ NickAlias *na = nullptr;
/* Number of channels registered by this account */
- uint16_t channelcount;
- /* Last time an email was sent to this user */
- time_t lastmail;
+ uint16_t channelcount = 0;
/* Users online now logged into this account */
std::list<User *> users;
@@ -149,79 +159,27 @@ class CoreExport NickCore : public Serializable, public Extensible
NickCore(const Anope::string &nickdisplay, uint64_t nickid = 0);
~NickCore();
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
/** Changes the display for this account
* @param na The new display, must be grouped to this account.
*/
- void SetDisplay(const NickAlias *na);
+ void SetDisplay(NickAlias *na);
/** Checks whether this account is a services oper or not.
* @return True if this account is a services oper, false otherwise.
*/
virtual bool IsServicesOper() const;
- /** Add an entry to the nick's access list
- *
- * @param entry The nick!ident@host entry to add to the access list
- *
- * Adds a new entry into the access list.
- */
- void AddAccess(const Anope::string &entry);
-
- /** Get an entry from the nick's access list by index
- *
- * @param entry Index in the access list vector to retrieve
- * @return The access list entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds
- *
- * Retrieves an entry from the access list corresponding to the given index.
- */
- Anope::string GetAccess(unsigned entry) const;
-
- /** Get the number of entries on the access list for this account.
- */
- unsigned GetAccessCount() const;
-
/** Retrieves the account id for this user */
uint64_t GetId();
- /** Find an entry in the nick's access list
- *
- * @param entry The nick!ident@host entry to search for
- * @return True if the entry is found in the access list, false otherwise
- *
- * Search for an entry within the access list.
- */
- bool FindAccess(const Anope::string &entry);
-
- /** Erase an entry from the nick's access list
- *
- * @param entry The nick!ident@host entry to remove
- *
- * Removes the specified access list entry from the access list.
- */
- void EraseAccess(const Anope::string &entry);
-
- /** Clears the entire nick's access list
- *
- * Deletes all the memory allocated in the access list vector and then clears the vector.
- */
- void ClearAccess();
-
- /** Is the given user on this accounts access list?
- *
- * @param u The user
- *
- * @return true if the user is on the access list
- */
- bool IsOnAccess(const User *u) const;
-
/** Finds an account
* @param nick The account name to find
* @return The account, if it exists
*/
- static NickCore* Find(const Anope::string &nick);
+ static NickCore *Find(const Anope::string &nick);
void AddChannelReference(ChannelInfo *ci);
void RemoveChannelReference(ChannelInfo *ci);
@@ -240,16 +198,16 @@ class CoreExport IdentifyRequest
Anope::string password;
std::set<Module *> holds;
- bool dispatched;
- bool success;
+ bool dispatched = false;
+ bool success = false;
static std::set<IdentifyRequest *> Requests;
- protected:
+protected:
IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass);
virtual ~IdentifyRequest();
- public:
+public:
/* One of these is called when the request goes through */
virtual void OnSuccess() = 0;
virtual void OnFail() = 0;
@@ -286,5 +244,3 @@ class CoreExport IdentifyRequest
static void ModuleUnload(Module *m);
};
-
-#endif // ACCOUNT_H
diff --git a/include/anope.h b/include/anope.h
index 4f599763d..1a9cdd0dd 100644
--- a/include/anope.h
+++ b/include/anope.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef ANOPE_H
-#define ANOPE_H
+#pragma once
#include <signal.h>
@@ -23,15 +22,15 @@ namespace Anope
* allow us to only require one type of string everywhere that can be converted
* at any time to a specific type of string.
*/
- class CoreExport string
+ class CoreExport string final
{
- private:
+ private:
/**
* The actual string is stored in an std::string as it can be converted to
* ci::string, or a C-style string at any time.
*/
std::string _string;
- public:
+ public:
/**
* Extras.
*/
@@ -40,6 +39,7 @@ namespace Anope
typedef std::string::reverse_iterator reverse_iterator;
typedef std::string::const_reverse_iterator const_reverse_iterator;
typedef std::string::size_type size_type;
+ typedef std::string::value_type value_type;
static const size_type npos = static_cast<size_type>(-1);
/**
@@ -54,9 +54,7 @@ namespace Anope
string(const ci::string &_str) : _string(_str.c_str()) { }
string(const string &_str, size_type pos, size_type n = npos) : _string(_str._string, pos, n) { }
template <class InputIterator> string(InputIterator first, InputIterator last) : _string(first, last) { }
-#if __cplusplus >= 201103L
string(const string &) = default;
-#endif
/**
* Assignment operators, so any type of string can be assigned to this class.
@@ -143,8 +141,8 @@ namespace Anope
*/
inline void push_back(char c) { return this->_string.push_back(c); }
- inline string& append(const string &s) { this->_string.append(s.str()); return *this; }
- inline string& append(const char *s, size_t n) { this->_string.append(s, n); return *this; }
+ inline string &append(const string &s) { this->_string.append(s.str()); return *this; }
+ inline string &append(const char *s, size_t n) { this->_string.append(s, n); return *this; }
/**
* Resizes the string content to n characters.
@@ -162,21 +160,21 @@ namespace Anope
* Trim leading and trailing white spaces from the string.
*/
- inline string& ltrim(const Anope::string &what = " \t\r\n")
+ inline string &ltrim(const Anope::string &what = " \t\r\n")
{
while (!this->_string.empty() && what.find(this->_string[0]) != Anope::string::npos)
this->_string.erase(this->_string.begin());
return *this;
}
- inline string& rtrim(const Anope::string &what = " \t\r\n")
+ inline string &rtrim(const Anope::string &what = " \t\r\n")
{
while (!this->_string.empty() && what.find(this->_string[this->_string.length() - 1]) != Anope::string::npos)
this->_string.erase(this->_string.length() - 1);
return *this;
}
- inline string& trim(const Anope::string &what = " \t\r\n")
+ inline string &trim(const Anope::string &what = " \t\r\n")
{
this->ltrim(what);
this->rtrim(what);
@@ -213,6 +211,10 @@ namespace Anope
inline size_type find_last_not_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_not_of(_str._string, pos); }
inline size_type find_last_not_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_not_of(ci::string(_str._string.c_str()), pos); }
+ inline int compare(size_t pos, size_t len, const string &str) const { return ci::string(this->_string.c_str()).compare(pos, len, ci::string(str.c_str())); }
+ inline int compare(size_t pos, size_t len, const string &str, size_t subpos, size_type sublen = npos) const { return ci::string(this->_string.c_str()).compare(pos, len, ci::string(str.c_str()), subpos, sublen); }
+ inline int compare(size_t pos, size_t len, const char *s, size_type n = npos) const { return ci::string(this->_string.c_str()).compare(pos, len, s, n); }
+
/**
* Determine if string consists of only numbers.
*/
@@ -257,8 +259,8 @@ namespace Anope
inline string lower() const
{
Anope::string new_string = *this;
- for (size_type i = 0; i < new_string.length(); ++i)
- new_string[i] = Anope::tolower(new_string[i]);
+ for (auto &chr : new_string)
+ chr = Anope::tolower(chr);
return new_string;
}
@@ -268,8 +270,8 @@ namespace Anope
inline string upper() const
{
Anope::string new_string = *this;
- for (size_type i = 0; i < new_string.length(); ++i)
- new_string[i] = Anope::toupper(new_string[i]);
+ for (auto &chr : new_string)
+ chr = Anope::toupper(chr);
return new_string;
}
@@ -311,23 +313,23 @@ namespace Anope
inline const string operator+(const char *_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
inline const string operator+(const std::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
- struct hash_ci
+ struct hash_ci final
{
inline size_t operator()(const string &s) const
{
- return TR1NS::hash<std::string>()(s.lower().str());
+ return std::hash<std::string>()(s.lower().str());
}
};
- struct hash_cs
+ struct hash_cs final
{
inline size_t operator()(const string &s) const
{
- return TR1NS::hash<std::string>()(s.str());
+ return std::hash<std::string>()(s.str());
}
};
- struct compare
+ struct compare final
{
inline bool operator()(const string &s1, const string &s2) const
{
@@ -335,9 +337,14 @@ namespace Anope
}
};
- template<typename T> class map : public std::map<string, T, ci::less> { };
- template<typename T> class multimap : public std::multimap<string, T, ci::less> { };
- template<typename T> class hash_map : public TR1NS::unordered_map<string, T, hash_ci, compare> { };
+ template<typename T>
+ using map = std::map<string, T, ci::less>;
+
+ template<typename T>
+ using multimap = std::multimap<string, T, ci::less>;
+
+ template<typename T>
+ using unordered_map = std::unordered_map<string, T, hash_ci, compare>;
#ifndef REPRODUCIBLE_BUILD
static const char *const compiled = __TIME__ " " __DATE__;
@@ -360,6 +367,7 @@ namespace Anope
* Use this unless you need very specific time checks
*/
extern CoreExport time_t CurTime;
+ extern CoreExport long long CurTimeNs;
/** The debug level we are running at.
*/
@@ -367,13 +375,13 @@ namespace Anope
/** Other command line options.
*/
- extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug;
+ extern CoreExport bool ReadOnly, NoFork, NoThird, NoPID, NoExpire, ProtocolDebug;
- /** The root of the services installation. Usually ~/services
+ /** The root of the Anope installation. Usually ~/anope
*/
extern CoreExport Anope::string ServicesDir;
- /** Services binary name (eg services)
+ /** Anope binary name (eg anope)
*/
extern CoreExport Anope::string ServicesBin;
@@ -387,7 +395,7 @@ namespace Anope
/** The uplink we are currently connected to
*/
- extern CoreExport int CurrentUplink;
+ extern CoreExport size_t CurrentUplink;
/** Various methods to determine the Anope version running
*/
@@ -419,7 +427,7 @@ namespace Anope
* initializing language support, loading modules, and loading databases.
* @throws CoreException if something bad went wrong
*/
- extern void Init(int ac, char **av);
+ extern bool Init(int ac, char **av);
/** Calls the save database event
*/
@@ -463,22 +471,7 @@ namespace Anope
* @param src The source string to encrypt
* @param dest The destination where the encrypted string is placed
*/
- extern CoreExport void Encrypt(const Anope::string &src, Anope::string &dest);
-
- /** Decrypts what is in 'src' to 'dest'.
- * @param src The source string to decrypt
- * @param dest The destination where the decrypted string is placed
- * @return true if decryption was successful. This is usually not the case
- * as most encryption methods we use are one way.
- */
- extern CoreExport bool Decrypt(const Anope::string &src, Anope::string &dest);
-
- /** Hashes a buffer with SipHash-2-4
- * @param src The start of the buffer to hash
- * @param src_sz The total number of bytes in the buffer
- * @param key A 16 byte key to hash the buffer with.
- */
- extern CoreExport uint64_t SipHash24(const void *src, unsigned long src_sz, const char key[16]);
+ 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
@@ -487,7 +480,7 @@ namespace Anope
* @param ... any number of parameters
* @return a Anope::string
*/
- extern CoreExport string printf(const char *fmt, ...);
+ extern CoreExport string printf(const char *fmt, ...) ATTR_FORMAT(1, 2);
/** Return the last error code
* @return The error code
@@ -497,7 +490,7 @@ namespace Anope
/** Return the last error, uses errno/GetLastError() to determine this
* @return An error message
*/
- extern CoreExport const string LastError();
+ extern CoreExport string LastError();
/** Determines if a path is a file
*/
@@ -536,10 +529,18 @@ namespace Anope
*/
extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
- /** Main processing routine. Parses the message and takes the appropriate action.
- * @param Raw message from the uplink
+ /** Parses a raw message from the uplink and calls its command handler.
+ * @param message Raw message from the uplink
+ */
+ extern void Process(const Anope::string &message);
+
+ /** Calls the command handler for an already parsed message.
+ * @param source Source of the message.
+ * @param command Command name.
+ * @param params Any extra parameters.
+ * @param tags IRCv3 message tags.
*/
- extern void Process(const Anope::string &);
+ extern CoreExport void ProcessInternal(MessageSource &src, const Anope::string &command, const std::vector<Anope::string> &params, const Anope::map<Anope::string> & tags);
/** Does a blocking dns query and returns the first IP.
* @param host host to look up
@@ -559,6 +560,54 @@ namespace Anope
* @param len The length of the string returned
*/
extern CoreExport Anope::string Random(size_t len);
+
+ /** 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);
}
/** sepstream allows for splitting token separated lists.
@@ -568,7 +617,7 @@ namespace Anope
*/
class CoreExport sepstream
{
- private:
+private:
/** Original string.
*/
Anope::string tokens;
@@ -577,15 +626,18 @@ class CoreExport sepstream
char sep;
/** Current string position
*/
- size_t pos;
+ size_t pos = 0;
/** If set then GetToken() can return an empty string
*/
bool allow_empty;
- public:
+public:
/** Create a sepstream and fill it with the provided data
*/
sepstream(const Anope::string &source, char separator, bool allowempty = false);
+ /** Retrieves the underlying string. */
+ const auto &GetString() const { return tokens; }
+
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
@@ -602,7 +654,7 @@ class CoreExport sepstream
/** Gets every token from this stream
* @param token Tokens are pushed back here
*/
- template<typename T> void GetTokens(T& token)
+ template<typename T> void GetTokens(T &token)
{
token.clear();
Anope::string t;
@@ -625,7 +677,7 @@ class CoreExport sepstream
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
- const Anope::string GetRemaining();
+ Anope::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
@@ -635,9 +687,10 @@ class CoreExport sepstream
/** A derived form of sepstream, which separates on commas
*/
-class commasepstream : public sepstream
+class commasepstream final
+ : public sepstream
{
- public:
+public:
/** Initialize with comma separator
*/
commasepstream(const Anope::string &source, bool allowempty = false) : sepstream(source, ',', allowempty) { }
@@ -645,9 +698,10 @@ class commasepstream : public sepstream
/** A derived form of sepstream, which separates on spaces
*/
-class spacesepstream : public sepstream
+class spacesepstream final
+ : public sepstream
{
- public:
+public:
/** Initialize with space separator
*/
spacesepstream(const Anope::string &source) : sepstream(source, ' ') { }
@@ -659,19 +713,17 @@ class spacesepstream : public sepstream
* be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
* attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
*/
-class CoreException : public std::exception
+class CoreExport CoreException
+ : public std::exception
{
- protected:
+protected:
/** Holds the error message to be displayed
*/
Anope::string err;
/** Source of the exception
*/
Anope::string source;
- public:
- /** Default constructor, just uses the error message 'Core threw an exception'.
- */
- CoreException() : err("Core threw an exception"), source("The core") { }
+public:
/** This constructor can be used to specify an error message before throwing.
*/
CoreException(const Anope::string &message) : err(message), source("The core") { }
@@ -683,7 +735,7 @@ class CoreException : public std::exception
* Actually no, it does nothing. Never mind.
* @throws Nothing!
*/
- virtual ~CoreException() throw() { }
+ virtual ~CoreException() noexcept = default;
/** Returns the reason for the exception.
* The module should probably put something informative here as the user will see this upon failure.
*/
@@ -698,13 +750,10 @@ class CoreException : public std::exception
}
};
-class ModuleException : public CoreException
+class CoreExport ModuleException
+ : public CoreException
{
- public:
- /** Default constructor, just uses the error message 'Module threw an exception'.
- */
- ModuleException() : CoreException("Module threw an exception", "A Module") { }
-
+public:
/** This constructor can be used to specify an error message before throwing.
*/
ModuleException(const Anope::string &message) : CoreException(message, "A Module") { }
@@ -712,69 +761,9 @@ class ModuleException : public CoreException
* Actually no, it does nothing. Never mind.
* @throws Nothing!
*/
- virtual ~ModuleException() throw() { }
+ virtual ~ModuleException() noexcept = default;
};
-class ConvertException : public CoreException
-{
- public:
- ConvertException(const Anope::string &reason = "") : CoreException(reason) { }
-
- virtual ~ConvertException() throw() { }
-};
-
-/** Convert something to a string
- */
-template<typename T> inline Anope::string stringify(const T &x)
-{
- std::ostringstream stream;
-
- if (!(stream << x))
- throw ConvertException("Stringify fail");
-
- return stream.str();
-}
-
-template<typename T> inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true)
-{
- leftover.clear();
- std::istringstream i(s.str());
- char c;
- if (!(i >> x))
- throw ConvertException("Convert fail");
- if (failIfLeftoverChars)
- {
- if (i.get(c))
- throw ConvertException("Convert fail");
- }
- else
- {
- std::string left;
- getline(i, left);
- leftover = left;
- }
-}
-
-template<typename T> inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true)
-{
- Anope::string Unused;
- convert(s, x, Unused, failIfLeftoverChars);
-}
-
-template<typename T> inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true)
-{
- T x;
- convert(s, x, leftover, failIfLeftoverChars);
- return x;
-}
-
-template<typename T> inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true)
-{
- T x;
- convert(s, x, failIfLeftoverChars);
- return x;
-}
-
/** Casts to be used instead of dynamic_cast, this uses dynamic_cast
* for debug builds and static_cast on release builds
* to speed up the program because dynamic_cast relies on RTTI.
@@ -795,4 +784,4 @@ template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
}
#endif
-#endif // ANOPE_H
+#include "convert.h"
diff --git a/include/base.h b/include/base.h
index 20a48e225..cfac283f5 100644
--- a/include/base.h
+++ b/include/base.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef BASE_H
-#define BASE_H
+#pragma once
#include "services.h"
@@ -16,9 +15,8 @@
class CoreExport Base
{
/* References to this base class */
- std::set<ReferenceBase *> *references;
- public:
- Base();
+ std::set<ReferenceBase *> *references = nullptr;
+public:
virtual ~Base();
/** Adds a reference to this object. Eg, when a Reference
@@ -32,12 +30,12 @@ class CoreExport Base
class ReferenceBase
{
- protected:
- bool invalid;
- public:
- ReferenceBase() : invalid(false) { }
+protected:
+ bool invalid = false;
+public:
+ ReferenceBase() = default;
ReferenceBase(const ReferenceBase &other) : invalid(other.invalid) { }
- virtual ~ReferenceBase() { }
+ virtual ~ReferenceBase() = default;
inline void Invalidate() { this->invalid = true; }
};
@@ -45,14 +43,13 @@ class ReferenceBase
* no longer be valid once the object it refers is destructed.
*/
template<typename T>
-class Reference : public ReferenceBase
+class Reference
+ : public ReferenceBase
{
- protected:
- T *ref;
- public:
- Reference() : ref(NULL)
- {
- }
+protected:
+ T *ref = nullptr;
+public:
+ Reference() = default;
Reference(T *obj) : ref(obj)
{
@@ -106,14 +103,14 @@ class Reference : public ReferenceBase
return NULL;
}
- inline T* operator->()
+ inline T *operator->()
{
if (operator bool())
return this->ref;
return NULL;
}
- inline T* operator*()
+ inline T *operator*()
{
if (operator bool())
return this->ref;
@@ -139,5 +136,3 @@ class Reference : public ReferenceBase
return false;
}
};
-
-#endif // BASE_H
diff --git a/include/bots.h b/include/bots.h
index e0f8f60dd..5a9c54a3e 100644
--- a/include/bots.h
+++ b/include/bots.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef BOTS_H
-#define BOTS_H
+#pragma once
#include "users.h"
#include "anope.h"
@@ -20,16 +19,20 @@ typedef Anope::map<BotInfo *> botinfo_map;
extern CoreExport Serialize::Checker<botinfo_map> BotListByNick, BotListByUID;
/* A service bot (NickServ, ChanServ, a BotServ bot, etc). */
-class CoreExport BotInfo : public User, public Serializable
+class CoreExport BotInfo final
+ : public User
+ , public Serializable
{
/* Channels this bot is assigned to */
Serialize::Checker<std::set<ChannelInfo *> > channels;
- public:
+public:
time_t created;
/* Last time this bot said something (via privmsg) */
time_t lastmsg;
/* Map of actual command names -> service name/permission required */
CommandInfo::map commands;
+ /* The server-side alias used to message this bot. */
+ Anope::string alias;
/* Modes the bot should have as configured in service:modes */
Anope::string botmodes;
/* Channels the bot should be in as configured in service:channels */
@@ -55,7 +58,7 @@ class CoreExport BotInfo : public User, public Serializable
virtual ~BotInfo();
void Serialize(Serialize::Data &data) const;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
void GenerateUID();
@@ -107,8 +110,9 @@ class CoreExport BotInfo : public User, public Serializable
/** Called when a user messages this bot
* @param u The user
* @param message The users' message
+ * @params tags Message tags
*/
- virtual void OnMessage(User *u, const Anope::string &message);
+ virtual void OnMessage(User *u, const Anope::string &message, const Anope::map<Anope::string> &tags);
/** Link a command name to a command in services
* @param cname The command name
@@ -116,7 +120,7 @@ class CoreExport BotInfo : public User, public Serializable
* @param permission Permission required to execute the command, if any
* @return The commandinfo for the newly created command
*/
- CommandInfo& SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission = "");
+ CommandInfo &SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission = "");
/** Get command info for a command
* @param cname The command name
@@ -124,12 +128,13 @@ class CoreExport BotInfo : public User, public Serializable
*/
CommandInfo *GetCommand(const Anope::string &cname);
+ /** Get the command that users can use to send a message to this bot. */
+ Anope::string GetQueryCommand() const;
+
/** Find a bot by nick
* @param nick The nick
* @param nick_only True to only look by nick, and not by UID
* @return The bot, if it exists
*/
- static BotInfo* Find(const Anope::string &nick, bool nick_only = false);
+ static BotInfo *Find(const Anope::string &nick, bool nick_only = false);
};
-
-#endif // BOTS_H
diff --git a/include/channels.h b/include/channels.h
index 6cb612103..8bea70fc9 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -6,20 +6,20 @@
* Please read COPYING and README for further details.
*/
-#ifndef CHANNELS_H
-#define CHANNELS_H
+#pragma once
#include "anope.h"
#include "extensible.h"
#include "modes.h"
#include "serialize.h"
-typedef Anope::hash_map<Channel *> channel_map;
+typedef Anope::unordered_map<Channel *> channel_map;
extern CoreExport channel_map ChannelList;
/* A user container, there is one of these per user per channel. */
-struct ChanUserContainer : public Extensible
+struct ChanUserContainer final
+ : public Extensible
{
User *user;
Channel *chan;
@@ -29,18 +29,20 @@ struct ChanUserContainer : public Extensible
ChanUserContainer(User *u, Channel *c) : user(u), chan(c) { }
};
-class CoreExport Channel : public Base, public Extensible
+class CoreExport Channel final
+ : public Base
+ , public Extensible
{
static std::vector<Channel *> deleting;
- public:
+public:
typedef std::multimap<Anope::string, Anope::string> ModeList;
- private:
+private:
/** A map of channel modes with their parameters set on this channel
*/
ModeList modes;
- public:
+public:
/* Channel name */
Anope::string name;
/* Set if this channel is registered. ci->c == this. Contains information relevant to the registered channel */
@@ -74,14 +76,14 @@ class CoreExport Channel : public Base, public Extensible
int16_t chanserv_modecount; /* Number of check_mode()'s this sec */
int16_t bouncy_modes; /* Did we fail to set modes here? */
- private:
+private:
/** Constructor
* @param name The channel name
* @param ts The time the channel was created
*/
Channel(const Anope::string &nname, time_t ts = Anope::CurTime);
- public:
+public:
/** Destructor
*/
~Channel();
@@ -108,7 +110,7 @@ class CoreExport Channel : public Base, public Extensible
* @param status The status to give the user, if any
* @return The UserContainer for the user
*/
- ChanUserContainer* JoinUser(User *u, const ChannelStatus *status);
+ ChanUserContainer *JoinUser(User *u, const ChannelStatus *status);
/** Remove a user internally from the channel
* @param u The user
@@ -205,14 +207,15 @@ class CoreExport Channel : public Base, public Extensible
* @param enforce_mlock Should mlock be enforced on this mode change
* @param cmodes The modes to set
*/
- void SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...);
+ void SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...) ATTR_FORMAT(4, 5);
+ void SetModes(BotInfo *bi, bool enforce_mlock, const Anope::string &cmodes);
/** Set a string of modes internally on a channel
* @param source The setter
* @param mode the modes
* @param enforce_mlock true to enforce mlock
*/
- void SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts = 0, bool enforce_mlock = true);
+ void SetModesInternal(MessageSource &source, const Anope::string &modes, const std::vector<Anope::string> &params, time_t ts = 0, bool enforce_mlock = true);
/** Does the given user match the given list? (CMODE_BAN, CMODE_EXCEPT, etc, a list mode)
* @param u The user
@@ -234,7 +237,8 @@ class CoreExport Channel : public Base, public Extensible
* @param reason The reason for the kick
* @return true if the kick was successful, false if a module blocked the kick
*/
- bool Kick(BotInfo *bi, User *u, const char *reason = NULL, ...);
+ bool Kick(BotInfo *bi, User *u, const char *reason = NULL, ...) ATTR_FORMAT(4, 5);
+ bool Kick(BotInfo *bi, User *u, const Anope::string &reason);
/** Get all modes set on this channel, excluding status modes.
* @return a map of modes and their optional parameters.
@@ -298,7 +302,7 @@ class CoreExport Channel : public Base, public Extensible
* @param name The channel to find
* @return The channel, if found
*/
- static Channel* Find(const Anope::string &name);
+ static Channel *Find(const Anope::string &name);
/** Finds or creates a channel
* @param name The channel name
@@ -311,5 +315,3 @@ class CoreExport Channel : public Base, public Extensible
static void DeleteChannels();
};
-
-#endif // CHANNELS_H
diff --git a/include/commands.h b/include/commands.h
index c466e2b18..56ffa4c6f 100644
--- a/include/commands.h
+++ b/include/commands.h
@@ -9,25 +9,22 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef COMMAND_H
-#define COMMAND_H
+#pragma once
#include "service.h"
#include "anope.h"
#include "channels.h"
-struct CommandGroup
+struct CommandGroup final
{
Anope::string name, description;
};
/* Used in BotInfo::commands */
-struct CommandInfo
+struct CommandInfo final
{
typedef Anope::map<CommandInfo> map;
- CommandInfo() : hide(false), prepend_channel(false) { }
-
/* Service name of the command */
Anope::string name;
/* Permission required to execute the command */
@@ -35,9 +32,9 @@ struct CommandInfo
/* Group this command is in */
Anope::string group;
/* whether or not to hide this command in help output */
- bool hide;
+ bool hide = false;
/* Only used with fantasy */
- bool prepend_channel;
+ bool prepend_channel = false;
};
/* Where the replies from commands go to. User inherits from this and is the normal
@@ -45,18 +42,19 @@ struct CommandInfo
*/
struct CoreExport CommandReply
{
- virtual ~CommandReply() { }
+ virtual ~CommandReply() = default;
virtual void SendMessage(BotInfo *source, const Anope::string &msg) = 0;
+ virtual void SendMessage(CommandSource &source, const Anope::string &msg);
};
/* The source for a command */
-class CoreExport CommandSource
+class CoreExport CommandSource final
{
/* The nick executing the command */
Anope::string nick;
/* User executing the command, may be NULL */
Reference<User> u;
- public:
+public:
/* The account executing the command */
Reference<NickCore> nc;
/* for web clients */
@@ -64,15 +62,17 @@ class CoreExport CommandSource
/* Where the reply should go */
CommandReply *reply;
/* Channel the command was executed on (fantasy) */
- Reference<Channel> c;
+ Reference<Channel> c = nullptr;
/* The service this command is on */
Reference<BotInfo> service;
/* The actual name of the command being executed */
Anope::string command;
/* The permission of the command being executed */
Anope::string permission;
+ /* The unique identifier of the executing message. */
+ Anope::string msgid;
- CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *reply, BotInfo *bi);
+ CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *reply, BotInfo *bi, const Anope::string &m = "");
const Anope::string &GetNick() const;
User *GetUser();
@@ -80,7 +80,8 @@ class CoreExport CommandSource
AccessGroup AccessFor(ChannelInfo *ci);
bool IsFounder(ChannelInfo *ci);
- void Reply(const char *message, ...);
+ void Reply(const char *message, ...) ATTR_FORMAT(2, 3);
+ void Reply(int count, const char *singular, const char *plural, ...) ATTR_FORMAT(4, 5);
void Reply(const Anope::string &message);
bool HasCommand(const Anope::string &cmd);
@@ -91,7 +92,8 @@ class CoreExport CommandSource
/** Every services command is a class, inheriting from Command.
*/
-class CoreExport Command : public Service
+class CoreExport Command
+ : public Service
{
Anope::string desc;
std::vector<Anope::string> syntax;
@@ -100,7 +102,7 @@ class CoreExport Command : public Service
/* Command requires that a user is executing it */
bool require_user;
- public:
+public:
/* Maximum parameters accepted by this command */
size_t max_params;
/* Minimum parameters required to use this command */
@@ -109,7 +111,7 @@ class CoreExport Command : public Service
/* Module which owns us */
Module *module;
- protected:
+protected:
/** Create a new command.
* @param owner The owner of the command
* @param sname The command name
@@ -119,10 +121,10 @@ class CoreExport Command : public Service
*/
Command(Module *owner, const Anope::string &sname, size_t min_params, size_t max_params = 0);
- public:
- virtual ~Command();
+public:
+ virtual ~Command() = default;
- protected:
+protected:
void SetDesc(const Anope::string &d);
void ClearSyntax();
@@ -132,7 +134,7 @@ class CoreExport Command : public Service
void AllowUnregistered(bool b);
void RequireUser(bool b);
- public:
+public:
bool AllowUnregistered() const;
bool RequireUser() const;
@@ -181,7 +183,5 @@ class CoreExport Command : public Service
* @param name If found, is set to the command name, eg REGISTER
* @return true if the given command service exists
*/
- static bool FindCommandFromService(const Anope::string &command_service, BotInfo* &bi, Anope::string &name);
+ static bool FindCommandFromService(const Anope::string &command_service, BotInfo *&bi, Anope::string &name);
};
-
-#endif // COMMANDS_H
diff --git a/include/config.h b/include/config.h
index d671bec0d..2f4f1b953 100644
--- a/include/config.h
+++ b/include/config.h
@@ -9,14 +9,12 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef CONFIG_H
-#define CONFIG_H
+#pragma once
#include "account.h"
#include "regchannel.h"
#include "users.h"
#include "opertype.h"
-#include <stack>
namespace Configuration
{
@@ -26,11 +24,11 @@ namespace Configuration
{
friend struct Configuration::Conf;
- public:
+ public:
typedef Anope::map<Anope::string> item_map;
typedef Anope::multimap<Block> block_map;
- private:
+ private:
Anope::string name;
item_map items;
block_map blocks;
@@ -39,37 +37,23 @@ namespace Configuration
/* Represents a missing tag. */
static Block EmptyBlock;
- public:
+ public:
Block(const Anope::string &);
const Anope::string &GetName() const;
int CountBlock(const Anope::string &name) const;
- const Block* GetBlock(const Anope::string &name, int num = 0) const;
- Block* GetMutableBlock(const Anope::string &name, int num = 0);
+ const Block *GetBlock(const Anope::string &name, int num = 0) const;
+ Block *GetMutableBlock(const Anope::string &name, int num = 0);
- template<typename T> inline T Get(const Anope::string &tag) const
+ template<typename T> T Get(const Anope::string &tag, const Anope::string &def = "") const
{
- return this->Get<T>(tag, "");
- }
- /* VS 2008 has an issue with having a default argument here (def = ""), which is why the above
- * function exists.
- */
- template<typename T> T Get(const Anope::string &tag, const Anope::string &def) const
- {
- const Anope::string &value = this->Get<const Anope::string>(tag, def);
- if (!value.empty())
- try
- {
- return convertTo<T>(value);
- }
- catch (const ConvertException &) { }
- return T();
+ return Anope::TryConvert<T>(this->Get<const Anope::string>(tag, def)).value_or(T());
}
bool Set(const Anope::string &tag, const Anope::string &value);
- const item_map* GetItems() const;
+ const item_map &GetItems() const;
};
- template<> CoreExport const Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const;
+ template<> CoreExport const Anope::string Block::Get(const Anope::string &tag, const Anope::string &def) const;
template<> CoreExport time_t Block::Get(const Anope::string &tag, const Anope::string &def) const;
template<> CoreExport bool Block::Get(const Anope::string &tag, const Anope::string &def) const;
} // namespace Internal
@@ -79,12 +63,12 @@ namespace Configuration
/** Represents a configuration file
*/
- class File
+ class File final
{
Anope::string name;
bool executable;
- FILE *fp;
- public:
+ FILE *fp = nullptr;
+ public:
File(const Anope::string &, bool);
~File();
const Anope::string &GetName() const;
@@ -99,25 +83,22 @@ namespace Configuration
struct Uplink;
- struct CoreExport Conf : Block
+ struct CoreExport Conf final
+ : Block
{
/* options:readtimeout */
time_t ReadTimeout;
- /* options:useprivmsg */
- bool UsePrivmsg;
/* If we should default to privmsging clients */
bool DefPrivmsg;
/* Default language */
Anope::string DefLanguage;
/* options:timeoutcheck */
time_t TimeoutCheck;
- /* options:usestrictprivmsg */
- bool UseStrictPrivmsg;
+ /* options:servicealias */
+ bool ServiceAlias;
/* networkinfo:nickchars */
Anope::string NickChars;
- /* either "/msg " or "/" */
- Anope::string StrictPrivmsg;
/* List of uplink servers to try and connect to */
std::vector<Uplink> Uplinks;
/* A vector of our logfile options */
@@ -145,7 +126,7 @@ namespace Configuration
void LoadConf(File &file);
void Post(Conf *old);
- Block *GetModule(Module *);
+ Block *GetModule(const Module *);
Block *GetModule(const Anope::string &name);
BotInfo *GetClient(const Anope::string &name);
@@ -153,15 +134,15 @@ namespace Configuration
const Block *GetCommand(CommandSource &);
};
- struct Uplink
+ struct Uplink final
{
Anope::string host;
unsigned port;
Anope::string password;
- bool ipv6;
+ int protocol;
- Uplink(const Anope::string &_host, int _port, const Anope::string &_password, bool _ipv6) : host(_host), port(_port), password(_password), ipv6(_ipv6) { }
- inline bool operator==(const Uplink &other) const { return host == other.host && port == other.port && password == other.password && ipv6 == other.ipv6; }
+ Uplink(const Anope::string &_host, int _port, const Anope::string &_password, int _protocol) : host(_host), port(_port), password(_password), protocol(_protocol) { }
+ inline bool operator==(const Uplink &other) const { return host == other.host && port == other.port && password == other.password && protocol == other.protocol; }
inline bool operator!=(const Uplink &other) const { return !(*this == other); }
};
}
@@ -172,9 +153,10 @@ namespace Configuration
* be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
* attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
*/
-class ConfigException : public CoreException
+class CoreExport ConfigException final
+ : public CoreException
{
- public:
+public:
/** Default constructor, just uses the error message 'Config threw an exception'.
*/
ConfigException() : CoreException("Config threw an exception", "Config Parser") { }
@@ -185,10 +167,8 @@ class ConfigException : public CoreException
* Actually no, it does nothing. Never mind.
* @throws Nothing!
*/
- virtual ~ConfigException() throw() { }
+ virtual ~ConfigException() noexcept = default;
};
extern Configuration::File ServicesConf;
extern CoreExport Configuration::Conf *Config;
-
-#endif // CONFIG_H
diff --git a/include/convert.h b/include/convert.h
new file mode 100644
index 000000000..7f83e73c0
--- /dev/null
+++ b/include/convert.h
@@ -0,0 +1,132 @@
+/*
+ *
+ * (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.
+ */
+
+#pragma once
+
+#include <optional>
+
+namespace Anope
+{
+ /** Attempts to convert a string to any type.
+ * @param in The value to convert.
+ * @param leftover If non-nullptr then the location to store leftover data.
+ */
+ template<typename T>
+ inline std::optional<T> TryConvert(const Anope::string &in, Anope::string *leftover = nullptr)
+ {
+ std::istringstream tmp(in.str());
+ T out;
+ if (!(tmp >> out))
+ return std::nullopt;
+
+ if (leftover)
+ {
+ leftover->clear();
+ std::getline(tmp, leftover->str());
+ }
+ else
+ {
+ char extra;
+ if (tmp >> extra)
+ return std::nullopt;
+ }
+ return out;
+ }
+
+ /** Converts a string to any type.
+ * @param in The value to convert.
+ * @param def The default to use if the conversion failed.
+ * @param leftover If non-nullptr then the location to store leftover data.
+ */
+ template<typename T>
+ inline T Convert(const Anope::string &in, T def, Anope::string *leftover = nullptr)
+ {
+ return TryConvert<T>(in, leftover).value_or(def);
+ }
+
+ /** Attempts to convert any type to a string.
+ * @param in The value to convert.
+ */
+ template <class T>
+ inline std::optional<Anope::string> TryString(const T &in)
+ {
+ std::ostringstream tmp;
+ if (!(tmp << in))
+ return std::nullopt;
+ return tmp.str();
+ }
+
+ /** No-op function that returns the string that was passed to it.
+ * @param in The string to return.
+ */
+ inline const string &ToString(const string &in)
+ {
+ return in;
+ }
+
+ /** Converts a std::string to a string.
+ * @param in The value to convert.
+ */
+ inline string ToString(const std::string &in)
+ {
+ return in;
+ }
+
+ /** Converts a char array to a string.
+ * @param in The value to convert.
+ */
+ inline string ToString(const char *in)
+ {
+ return string(in);
+ }
+
+ /** Converts a char to a string.
+ * @param in The value to convert.
+ */
+ inline string ToString(char in)
+ {
+ return string(1, static_cast<string::value_type>(in));
+ }
+
+ /** Converts an unsigned char to a string.
+ * @param in The value to convert.
+ */
+ inline string ToString(unsigned char in)
+ {
+ return string(1, static_cast<string::value_type>(in));
+ }
+
+ /** Converts a bool to a string.
+ * @param in The value to convert.
+ */
+ inline string ToString(bool in)
+ {
+ return (in ? "1" : "0");
+ }
+
+ /** Converts a type that std::to_string is implemented for to a string.
+ * @param in The value to convert.
+ */
+ template<typename Stringable>
+ inline std::enable_if_t<std::is_arithmetic_v<Stringable>, string> ToString(const Stringable &in)
+ {
+ return std::to_string(in);
+ }
+
+ /** Converts any type to a string.
+ * @param in The value to convert.
+ */
+ template <class T>
+ inline std::enable_if_t<!std::is_arithmetic_v<T>, string> ToString(const T &in)
+ {
+ return TryString(in).value_or(Anope::string());
+ }
+}
diff --git a/include/defs.h b/include/defs.h
index b49ca79ca..c130a11df 100644
--- a/include/defs.h
+++ b/include/defs.h
@@ -9,6 +9,8 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
class AccessGroup;
class AutoKick;
class BotInfo;
diff --git a/include/extensible.h b/include/extensible.h
index 40f2ecdec..d143b0c81 100644
--- a/include/extensible.h
+++ b/include/extensible.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef EXTENSIBLE_H
-#define EXTENSIBLE_H
+#pragma once
#include "anope.h"
#include "serialize.h"
@@ -16,15 +15,16 @@
class Extensible;
-class CoreExport ExtensibleBase : public Service
+class CoreExport ExtensibleBase
+ : public Service
{
- protected:
+protected:
std::map<Extensible *, void *> items;
ExtensibleBase(Module *m, const Anope::string &n);
~ExtensibleBase();
- public:
+public:
virtual void Unset(Extensible *obj) = 0;
/* called when an object we are keep track of is serializing */
@@ -34,19 +34,19 @@ class CoreExport ExtensibleBase : public Service
class CoreExport Extensible
{
- public:
+public:
std::set<ExtensibleBase *> extension_items;
virtual ~Extensible();
void UnsetExtensibles();
- template<typename T> T* GetExt(const Anope::string &name) const;
+ template<typename T> T *GetExt(const Anope::string &name) const;
bool HasExt(const Anope::string &name) const;
- template<typename T> T* Extend(const Anope::string &name, const T &what);
- template<typename T> T* Extend(const Anope::string &name);
- template<typename T> T* Require(const Anope::string &name);
+ template<typename T> T *Extend(const Anope::string &name, const T &what);
+ template<typename T> T *Extend(const Anope::string &name);
+ template<typename T> T *Require(const Anope::string &name);
template<typename T> void Shrink(const Anope::string &name);
static void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &data);
@@ -54,12 +54,13 @@ class CoreExport Extensible
};
template<typename T>
-class BaseExtensibleItem : public ExtensibleBase
+class BaseExtensibleItem
+ : public ExtensibleBase
{
- protected:
+protected:
virtual T *Create(Extensible *) = 0;
- public:
+public:
BaseExtensibleItem(Module *m, const Anope::string &n) : ExtensibleBase(m, n) { }
~BaseExtensibleItem()
@@ -76,24 +77,24 @@ class BaseExtensibleItem : public ExtensibleBase
}
}
- T* Set(Extensible *obj, const T &value)
+ T *Set(Extensible *obj, const T &value)
{
- T* t = Set(obj);
+ T *t = Set(obj);
if (t)
*t = value;
return t;
}
- T* Set(Extensible *obj)
+ T *Set(Extensible *obj)
{
- T* t = Create(obj);
+ T *t = Create(obj);
Unset(obj);
items[obj] = t;
obj->extension_items.insert(this);
return t;
}
- void Unset(Extensible *obj) anope_override
+ void Unset(Extensible *obj) override
{
T *value = Get(obj);
items.erase(obj);
@@ -101,7 +102,7 @@ class BaseExtensibleItem : public ExtensibleBase
delete value;
}
- T* Get(const Extensible *obj) const
+ T *Get(const Extensible *obj) const
{
std::map<Extensible *, void *>::const_iterator it = items.find(const_cast<Extensible *>(obj));
if (it != items.end())
@@ -114,9 +115,9 @@ class BaseExtensibleItem : public ExtensibleBase
return items.find(const_cast<Extensible *>(obj)) != items.end();
}
- T* Require(Extensible *obj)
+ T *Require(Extensible *obj)
{
- T* t = Get(obj);
+ T *t = Get(obj);
if (t)
return t;
@@ -125,54 +126,57 @@ class BaseExtensibleItem : public ExtensibleBase
};
template<typename T>
-class ExtensibleItem : public BaseExtensibleItem<T>
+class ExtensibleItem
+ : public BaseExtensibleItem<T>
{
- protected:
- T* Create(Extensible *obj) anope_override
+protected:
+ T *Create(Extensible *obj) override
{
return new T(obj);
}
- public:
+public:
ExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { }
};
template<typename T>
-class PrimitiveExtensibleItem : public BaseExtensibleItem<T>
+class PrimitiveExtensibleItem
+ : public BaseExtensibleItem<T>
{
- protected:
- T* Create(Extensible *obj) anope_override
+protected:
+ T *Create(Extensible *obj) override
{
return new T();
}
- public:
+public:
PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { }
};
template<>
class PrimitiveExtensibleItem<bool> : public BaseExtensibleItem<bool>
{
- protected:
- bool* Create(Extensible *) anope_override
+protected:
+ bool *Create(Extensible *) override
{
return NULL;
}
- public:
+public:
PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<bool>(m, n) { }
};
template<typename T>
-class SerializableExtensibleItem : public PrimitiveExtensibleItem<T>
+class SerializableExtensibleItem
+ : public PrimitiveExtensibleItem<T>
{
- public:
+public:
SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<T>(m, n) { }
- void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
- T* t = this->Get(e);
- data[this->name] << *t;
+ T *t = this->Get(e);
+ data.Store(this->name, *t);
}
- void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
{
T t;
if (data[this->name] >> t)
@@ -185,16 +189,15 @@ class SerializableExtensibleItem : public PrimitiveExtensibleItem<T>
template<>
class SerializableExtensibleItem<bool> : public PrimitiveExtensibleItem<bool>
{
- public:
+public:
SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<bool>(m, n) { }
- void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
- data.SetType(this->name, Serialize::Data::DT_INT);
- data[this->name] << this->HasExt(e);
+ data.Store(this->name, this->HasExt(e));
}
- void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
{
bool b = false;
data[this->name] >> b;
@@ -206,13 +209,14 @@ class SerializableExtensibleItem<bool> : public PrimitiveExtensibleItem<bool>
};
template<typename T>
-struct ExtensibleRef : ServiceReference<BaseExtensibleItem<T> >
+struct ExtensibleRef final
+ : ServiceReference<BaseExtensibleItem<T> >
{
ExtensibleRef(const Anope::string &n) : ServiceReference<BaseExtensibleItem<T> >("Extensible", n) { }
};
template<typename T>
-T* Extensible::GetExt(const Anope::string &name) const
+T *Extensible::GetExt(const Anope::string &name) const
{
ExtensibleRef<T> ref(name);
if (ref)
@@ -223,16 +227,16 @@ T* Extensible::GetExt(const Anope::string &name) const
}
template<typename T>
-T* Extensible::Extend(const Anope::string &name, const T &what)
+T *Extensible::Extend(const Anope::string &name, const T &what)
{
- T* t = Extend<T>(name);
+ T *t = Extend<T>(name);
if (t)
*t = what;
return t;
}
template<typename T>
-T* Extensible::Extend(const Anope::string &name)
+T *Extensible::Extend(const Anope::string &name)
{
ExtensibleRef<T> ref(name);
if (ref)
@@ -243,7 +247,7 @@ T* Extensible::Extend(const Anope::string &name)
}
template<typename T>
-T* Extensible::Require(const Anope::string &name)
+T *Extensible::Require(const Anope::string &name)
{
if (HasExt(name))
return GetExt<T>(name);
@@ -260,5 +264,3 @@ void Extensible::Shrink(const Anope::string &name)
else
Log(LOG_DEBUG) << "Shrink for nonexistent type " << name << " on " << static_cast<void *>(this);
}
-
-#endif // EXTENSIBLE_H
diff --git a/include/hashcomp.h b/include/hashcomp.h
index 68e4ad014..6f7720cf3 100644
--- a/include/hashcomp.h
+++ b/include/hashcomp.h
@@ -6,19 +6,11 @@
* Please read COPYING and README for further details.
*/
-#ifndef HASHCOMP_H
-#define HASHCOMP_H
+#pragma once
#include <string>
#include <locale>
-
-#if defined _LIBCPP_VERSION || defined _WIN32
#include <unordered_map>
-#define TR1NS std
-#else
-#include <tr1/unordered_map>
-#define TR1NS std::tr1
-#endif
#include "services.h"
@@ -29,16 +21,17 @@ namespace Anope
/* Casemap in use by Anope. ci::string's comparison functions use this (and thus Anope::string) */
extern std::locale casemap;
- extern void CaseMapRebuild();
- extern unsigned char tolower(unsigned char);
- extern unsigned char toupper(unsigned char);
+ extern CoreExport void CaseMapRebuild();
+ extern CoreExport unsigned char tolower(unsigned char);
+ extern CoreExport unsigned char toupper(unsigned char);
/* ASCII case insensitive ctype. */
template<typename char_type>
- class ascii_ctype : public std::ctype<char_type>
+ class ascii_ctype
+ : public std::ctype<char_type>
{
- public:
- char_type do_toupper(char_type c) const anope_override
+ public:
+ char_type do_toupper(char_type c) const override
{
if (c >= 'a' && c <= 'z')
return c - 32;
@@ -46,7 +39,7 @@ namespace Anope
return c;
}
- char_type do_tolower(char_type c) const anope_override
+ char_type do_tolower(char_type c) const override
{
if (c >= 'A' && c <= 'Z')
return c + 32;
@@ -57,10 +50,11 @@ namespace Anope
/* rfc1459 case insensitive ctype, { = [, } = ], and | = \ */
template<typename char_type>
- class rfc1459_ctype : public ascii_ctype<char_type>
+ class rfc1459_ctype final
+ : public ascii_ctype<char_type>
{
- public:
- char_type do_toupper(char_type c) const anope_override
+ public:
+ char_type do_toupper(char_type c) const override
{
if (c == '{' || c == '}' || c == '|')
return c - 32;
@@ -68,7 +62,7 @@ namespace Anope
return ascii_ctype<char_type>::do_toupper(c);
}
- char_type do_tolower(char_type c) const anope_override
+ char_type do_tolower(char_type c) const override
{
if (c == '[' || c == ']' || c == '\\')
return c + 32;
@@ -86,7 +80,8 @@ namespace ci
* This class is used to implement ci::string, a case-insensitive, ASCII-
* comparing string class.
*/
- struct CoreExport ci_char_traits : std::char_traits<char>
+ struct CoreExport ci_char_traits final
+ : std::char_traits<char>
{
/** Check if two chars match.
* @param c1st First character
@@ -131,7 +126,7 @@ namespace ci
*/
typedef std::basic_string<char, ci_char_traits, std::allocator<char> > string;
- struct CoreExport less
+ struct CoreExport less final
{
/** Compare two Anope::strings as ci::strings and find which one is less
* @param s1 The first string
@@ -195,5 +190,3 @@ inline bool operator!=(const std::string &leftval, const ci::string &rightval)
{
return !(leftval.c_str() == rightval);
}
-
-#endif // HASHCOMP_H
diff --git a/include/language.h b/include/language.h
index 826c44670..f9934e642 100644
--- a/include/language.h
+++ b/include/language.h
@@ -6,12 +6,14 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "anope.h"
namespace Language
{
- /* Languages we support as configured in services.conf. They are
+ /* Languages we support as configured in anope.conf. They are
* added to this list if we detect a language exists in the correct
* location for each language.
*/
@@ -53,27 +55,65 @@ namespace Language
*/
extern CoreExport const char *Translate(const NickCore *nc, const char *string);
- /** Translatesa string to the given language.
+ /** Translates a string to the given language.
* @param lang The language to translate to
* @param string The string to translate
* @return The translated string if found, else the original string.
*/
extern CoreExport const char *Translate(const char *lang, const char *string);
+ /** Translates a plural string to the default language.
+ * @param count The number of items the string is counting.
+ * @param singular The string to translate if there is one of \p count
+ * @param plural The string to translate if there is multiple of \p count
+ * @return The translated string if found, else the original string.
+ */
+ extern CoreExport const char *Translate(int count, const char *singular, const char *plural);
+
+ /** Translates a plural string to the language of the given user.
+ * @param u The user to translate the string for
+ * @param count The number of items the string is counting.
+ * @param singular The string to translate if there is one of \p count
+ * @param plural The string to translate if there is multiple of \p count
+ * @return The translated string if found, else the original string.
+ */
+ extern CoreExport const char *Translate(User *u, int count, const char *singular, const char *plural);
+
+ /** Translates a plural string to the language of the given account.
+ * @param nc The account to translate the string for
+ * @param count The number of items the string is counting.
+ * @param singular The string to translate if there is one of \p count
+ * @param plural The string to translate if there is multiple of \p count
+ * @return The translated string if count, else the original string
+ */
+ extern CoreExport const char *Translate(const NickCore *nc, int count, const char *singular, const char *plural);
+
+ /** Translates a plural string to the given language.
+ * @param lang The language to translate to
+ * @param count The number of items the string is counting.
+ * @param singular The string to translate if there is one of \p count
+ * @param plural The string to translate if there is multiple of \p count
+ * @return The translated string if found, else the original string.
+ */
+ extern CoreExport const char *Translate(const char *lang, int count, const char *singular, const char *plural);
+
} // namespace Language
/* Commonly used language strings */
-#define MORE_INFO _("\002%s%s HELP %s\002 for more information.")
+#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s DROP %s %s\002")
+#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
+#define MORE_INFO _("\002%s HELP %s\002 for more information.")
#define BAD_USERHOST_MASK _("Mask must be in the form \037user\037@\037host\037.")
#define BAD_EXPIRY_TIME _("Invalid expiry time.")
#define USERHOST_MASK_TOO_WIDE _("%s coverage is too wide; Please use a more specific mask.")
-#define READ_ONLY_MODE _("Services are in read-only mode!")
+#define READ_ONLY_MODE _("Services are temporarily in read-only mode.")
#define PASSWORD_INCORRECT _("Password incorrect.")
#define ACCESS_DENIED _("Access denied.")
-#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should be at least\n" \
- "five characters long, should not be something easily guessed\n" \
- "(e.g. your real name or your nick), and cannot contain the space or tab characters.")
-#define PASSWORD_TOO_LONG _("Your password is too long. It must not exceed %u characters.")
+#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should not be\n" \
+ "something that could be easily guessed (e.g. your real name or your nick) and\n" \
+ "cannot contain the space or tab characters.\n")
+#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.")
@@ -83,20 +123,18 @@ namespace Language
#define CHAN_X_NOT_REGISTERED _("Channel \002%s\002 isn't registered.")
#define CHAN_X_NOT_IN_USE _("Channel \002%s\002 doesn't exist.")
#define NICK_IDENTIFY_REQUIRED _("You must be logged into an account to use that command.")
-#define MAIL_X_INVALID _("\002%s\002 is not a valid e-mail address.")
+#define MAIL_X_INVALID _("\002%s\002 is not a valid email address.")
#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_REGISTERED _("This nick is owned by someone else. Please choose another.\n" \
- "(If this is your nick, type \002%s%s IDENTIFY \037password\037\002.)")
#define NICK_IS_SECURE _("This nickname is registered and protected. If it is your\n" \
- "nick, type \002%s%s IDENTIFY \037password\037\002. Otherwise,\n" \
+ "nick, type \002%s IDENTIFY \037password\037\002. Otherwise,\n" \
"please choose a different nick.")
#define FORCENICKCHANGE_NOW _("This nickname has been registered; you may not use it.")
#define NICK_CANNOT_BE_REGISTERED _("Nickname \002%s\002 may not be registered.")
#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 e-mail again, and retry.")
+#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.")
@@ -105,23 +143,22 @@ namespace Language
#define CHAN_SETTING_CHANGED _("%s for %s set to %s.")
#define CHAN_SETTING_UNSET _("%s for %s unset.")
#define CHAN_ACCESS_LEVEL_RANGE _("Access level must be between %d and %d inclusive.")
-#define CHAN_INFO_HEADER _("Information for channel \002%s\002:")
+#define CHAN_INFO_HEADER _("Information about channel \002%s\002:")
#define CHAN_EXCEPTED _("\002%s\002 matches an except on %s and cannot be banned until the except has been removed.")
#define MEMO_NEW_X_MEMO_ARRIVED _("There is a new memo on channel %s.\n" \
- "Type \002%s%s READ %s %d\002 to read it.")
+ "Type \002%s READ %s %zu\002 to read it.")
#define MEMO_NEW_MEMO_ARRIVED _("You have a new memo from %s.\n" \
- "Type \002%s%s READ %d\002 to read it.")
+ "Type \002%s READ %zu\002 to read it.")
#define MEMO_HAVE_NO_MEMOS _("You have no memos.")
#define MEMO_X_HAS_NO_MEMOS _("%s has no memos.")
-#define MEMO_SEND_DISABLED _("Sorry, memo sending is temporarily disabled.")
#define MEMO_HAVE_NO_NEW_MEMOS _("You have no new memos.")
#define MEMO_X_HAS_NO_NEW_MEMOS _("%s has no new memos.")
#define BOT_DOES_NOT_EXIST _("Bot \002%s\002 does not exist.")
#define BOT_NOT_ASSIGNED _("You must assign a bot to the channel before using this command.")
#define BOT_NOT_ON_CHANNEL _("Bot is not on channel \002%s\002.")
-#define HOST_SET_ERROR _("A vHost must be in the format of a valid hostname.")
-#define HOST_SET_IDENT_ERROR _("A vHost ident must be in the format of a valid ident.")
-#define HOST_SET_TOOLONG _("Error! The vHost is too long, please use a hostname shorter than %d characters.")
-#define HOST_SET_IDENTTOOLONG _("Error! The vHost ident is too long, please use an ident shorter than %d characters.")
-#define HOST_NOT_ASSIGNED _("Please contact an Operator to get a vHost assigned to this nick.")
-#define HOST_NO_VIDENT _("Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug")
+#define HOST_SET_ERROR _("A vhost must be in the format of a valid hostname.")
+#define HOST_SET_IDENT_ERROR _("A vident must be in the format of a valid ident.")
+#define HOST_SET_TOOLONG _("Error! The vhost is too long, please use a hostname shorter than %zu characters.")
+#define HOST_SET_IDENTTOOLONG _("Error! The vident is too long, please use an ident shorter than %zu characters.")
+#define HOST_NOT_ASSIGNED _("Please contact an Operator to get a vhost assigned to this nick.")
+#define HOST_NO_VIDENT _("Your IRCd does not support vidents. If this is incorrect please report this as a possible bug.")
diff --git a/include/lists.h b/include/lists.h
index 039ab7758..7bba44907 100644
--- a/include/lists.h
+++ b/include/lists.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef LISTS_H
-#define LISTS_H
+#pragma once
#include "services.h"
#include "anope.h"
@@ -24,13 +23,13 @@
*/
class CoreExport NumberList
{
- private:
- bool is_valid;
+private:
+ bool is_valid = true;
std::set<unsigned> numbers;
bool desc;
- public:
+public:
/** Processes a numbered list
* @param list The list
* @param descending True to make HandleNumber get called with numbers in descending order
@@ -39,7 +38,7 @@ class CoreExport NumberList
/** Destructor, does nothing
*/
- virtual ~NumberList();
+ virtual ~NumberList() = default;
/** Should be called after the constructors are done running. This calls the callbacks.
*/
@@ -61,15 +60,15 @@ class CoreExport NumberList
/** This class handles formatting LIST/VIEW replies.
*/
-class CoreExport ListFormatter
+class CoreExport ListFormatter final
{
- public:
+public:
typedef std::map<Anope::string, Anope::string> ListEntry;
- private:
+private:
NickCore *nc;
std::vector<Anope::string> columns;
std::vector<ListEntry> entries;
- public:
+public:
ListFormatter(NickCore *nc);
ListFormatter &AddColumn(const Anope::string &name);
void AddEntry(const ListEntry &entry);
@@ -79,16 +78,14 @@ class CoreExport ListFormatter
/** This class handles formatting INFO replies
*/
-class CoreExport InfoFormatter
+class CoreExport InfoFormatter final
{
NickCore *nc;
std::vector<std::pair<Anope::string, Anope::string> > replies;
- unsigned longest;
- public:
+ 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);
};
-
-#endif // LISTS_H
diff --git a/include/logger.h b/include/logger.h
index 83b967f76..b73526afe 100644
--- a/include/logger.h
+++ b/include/logger.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef LOGGER_H
-#define LOGGER_H
+#pragma once
#include "anope.h"
#include "defs.h"
@@ -38,7 +37,7 @@ enum LogType
LOG_DEBUG_4
};
-struct LogFile
+struct LogFile final
{
Anope::string filename;
std::ofstream stream;
@@ -49,27 +48,27 @@ struct LogFile
};
/* Represents a single log message */
-class CoreExport Log
+class CoreExport Log final
{
- public:
+public:
/* Bot that should log this message */
- BotInfo *bi;
+ BotInfo *bi = nullptr;
/* For commands, the user executing the command, but might not always exist */
- User *u;
+ User *u = nullptr;
/* For commands, the account executing the command, but will not always exist */
- NickCore *nc;
+ NickCore *nc = nullptr;
/* For commands, the command being executed */
- Command *c;
+ Command *c = nullptr;
/* For commands, the command source */
- CommandSource *source;
+ CommandSource *source = nullptr;
/* Used for LOG_CHANNEL */
- Channel *chan;
+ Channel *chan = nullptr;
/* For commands, the channel the command was executed on, will not always exist */
- const ChannelInfo *ci;
+ const ChannelInfo *ci = nullptr;
/* For LOG_SERVER */
- Server *s;
+ Server *s = nullptr;
/* For LOG_MODULE */
- Module *m;
+ Module *m = nullptr;
LogType type;
Anope::string category;
@@ -95,11 +94,11 @@ class CoreExport Log
~Log();
- private:
+private:
Anope::string FormatSource() const;
Anope::string FormatCommand() const;
- public:
+public:
Anope::string BuildPrefix() const;
template<typename T> Log &operator<<(T val)
@@ -110,13 +109,13 @@ class CoreExport Log
};
/* Configured in the configuration file, actually does the message logging */
-class CoreExport LogInfo
+class CoreExport LogInfo final
{
- public:
- BotInfo *bot;
+public:
+ BotInfo *bot = nullptr;
std::vector<Anope::string> targets;
std::vector<LogFile *> logfiles;
- int last_day;
+ int last_day = 0;
std::vector<Anope::string> sources;
int log_age;
std::vector<Anope::string> admin;
@@ -140,5 +139,3 @@ class CoreExport LogInfo
/* Logs the message l if configured to */
void ProcessMessage(const Log *l);
};
-
-#endif // LOGGER_H
diff --git a/include/mail.h b/include/mail.h
index 347f3bc5b..0a25da3bf 100644
--- a/include/mail.h
+++ b/include/mail.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef MAIL_H
-#define MAIL_H
+#pragma once
#include "anope.h"
#include "threadengine.h"
@@ -23,9 +22,10 @@ namespace Mail
extern CoreExport bool Validate(const Anope::string &email);
/* A email message being sent */
- class Message : public Thread
+ class Message final
+ : public Thread
{
- private:
+ private:
Anope::string error;
Anope::string sendmail_path;
Anope::string send_from;
@@ -36,7 +36,7 @@ namespace Mail
Anope::string content_type;
bool dont_quote_addresses;
- public:
+ public:
/** Construct this message. Once constructed call Thread::Start to launch the mail sending.
* @param sf Config->SendFrom
* @param mailto Name of person being mailed (u->nick, nc->display, etc)
@@ -49,9 +49,7 @@ namespace Mail
~Message();
/* Called from within the thread to actually send the mail */
- void Run() anope_override;
+ void Run() override;
};
} // namespace Mail
-
-#endif // MAIL_H
diff --git a/include/memo.h b/include/memo.h
index d98492e2c..dca35ea8e 100644
--- a/include/memo.h
+++ b/include/memo.h
@@ -9,23 +9,23 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef MEMO_H
-#define MEMO_H
+#pragma once
#include "anope.h"
#include "serialize.h"
-class CoreExport Memo : public Serializable
+class CoreExport Memo final
+ : public Serializable
{
- public:
+public:
MemoInfo *mi;
bool unread;
bool receipt;
Memo();
~Memo();
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
Anope::string owner;
/* When it was sent */
@@ -37,9 +37,9 @@ class CoreExport Memo : public Serializable
/* Memo info structures. Since both nicknames and channels can have memos,
* we encapsulate memo data in a MemoInfo to make it easier to handle.
*/
-struct CoreExport MemoInfo
+struct CoreExport MemoInfo final
{
- int16_t memomax;
+ int16_t memomax = 0;
Serialize::Checker<std::vector<Memo *> > memos;
std::vector<Anope::string> ignores;
@@ -51,5 +51,3 @@ struct CoreExport MemoInfo
static MemoInfo *GetMemoInfo(const Anope::string &targ, bool &is_chan);
};
-
-#endif // MEMO_H
diff --git a/include/messages.h b/include/messages.h
index 7fffce5a0..510f66361 100644
--- a/include/messages.h
+++ b/include/messages.h
@@ -9,6 +9,8 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
#include "protocol.h"
/* Common IRCD messages.
@@ -19,39 +21,44 @@
namespace Message
{
- struct CoreExport Away : IRCDMessage
+ struct CoreExport Away
+ : IRCDMessage
{
- Away(Module *creator, const Anope::string &mname = "AWAY") : IRCDMessage(creator, mname, 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Away(Module *creator, const Anope::string &mname = "AWAY") : IRCDMessage(creator, mname, 0) { SetFlag(FLAG_REQUIRE_USER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Capab : IRCDMessage
+ struct CoreExport Capab
+ : IRCDMessage
{
- Capab(Module *creator, const Anope::string &mname = "CAPAB") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Capab(Module *creator, const Anope::string &mname = "CAPAB") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Error : IRCDMessage
+ struct CoreExport Error
+ : IRCDMessage
{
Error(Module *creator, const Anope::string &mname = "ERROR") : IRCDMessage(creator, mname, 1) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Invite : IRCDMessage
+ struct CoreExport Invite
+ : IRCDMessage
{
- Invite(Module *creator, const Anope::string &mname = "INVITE") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Invite(Module *creator, const Anope::string &mname = "INVITE") : IRCDMessage(creator, mname, 2) { SetFlag(FLAG_REQUIRE_USER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Join : IRCDMessage
+ struct CoreExport Join
+ : IRCDMessage
{
- Join(Module *creator, const Anope::string &mname = "JOIN") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Join(Module *creator, const Anope::string &mname = "JOIN") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_REQUIRE_USER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
typedef std::pair<ChannelStatus, User *> SJoinUser;
@@ -59,115 +66,131 @@ namespace Message
* @param source The source of the SJOIN
* @param chan The channel the users are joining to
* @param ts The TS for the channel
- * @param modes The modes sent with the SJOIN, if any
+ * @param modes The mode letters sent with the SJOIN, if any
+ * @param modeparams The mode parameters sent with the SJOIN, if any
* @param users The users and their status, if any
*/
- static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users);
+ static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users);
};
- struct CoreExport Kick : IRCDMessage
+ struct CoreExport Kick
+ : IRCDMessage
{
- Kick(Module *creator, const Anope::string &mname = "KICK") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Kick(Module *creator, const Anope::string &mname = "KICK") : IRCDMessage(creator, mname, 2) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Kill : IRCDMessage
+ struct CoreExport Kill
+ : IRCDMessage
{
Kill(Module *creator, const Anope::string &mname = "KILL") : IRCDMessage(creator, mname, 2) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Mode : IRCDMessage
+ struct CoreExport Mode
+ : IRCDMessage
{
- Mode(Module *creator, const Anope::string &mname = "MODE") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Mode(Module *creator, const Anope::string &mname = "MODE") : IRCDMessage(creator, mname, 2) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport MOTD : IRCDMessage
+ struct CoreExport MOTD
+ : IRCDMessage
{
MOTD(Module *creator, const Anope::string &mname = "MOTD") : IRCDMessage(creator, mname, 1) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Notice : IRCDMessage
+ struct CoreExport Notice
+ : IRCDMessage
{
- Notice(Module *creator, const Anope::string &mname = "NOTICE") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ Notice(Module *creator, const Anope::string &mname = "NOTICE") : IRCDMessage(creator, mname, 2) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Part : IRCDMessage
+ struct CoreExport Part
+ : IRCDMessage
{
- Part(Module *creator, const Anope::string &mname = "PART") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Part(Module *creator, const Anope::string &mname = "PART") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_REQUIRE_USER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Ping : IRCDMessage
+ struct CoreExport Ping
+ : IRCDMessage
{
- Ping(Module *creator, const Anope::string &mname = "PING") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Ping(Module *creator, const Anope::string &mname = "PING") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Privmsg : IRCDMessage
+ struct CoreExport Privmsg
+ : IRCDMessage
{
- Privmsg(Module *creator, const Anope::string &mname = "PRIVMSG") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ Privmsg(Module *creator, const Anope::string &mname = "PRIVMSG") : IRCDMessage(creator, mname, 2) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Quit : IRCDMessage
+ struct CoreExport Quit
+ : IRCDMessage
{
- Quit(Module *creator, const Anope::string &mname = "QUIT") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ Quit(Module *creator, const Anope::string &mname = "QUIT") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport SQuit : IRCDMessage
+ struct CoreExport SQuit
+ : IRCDMessage
{
SQuit(Module *creator, const Anope::string &mname = "SQUIT") : IRCDMessage(creator, mname, 2) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Stats : IRCDMessage
+ struct CoreExport Stats
+ : IRCDMessage
{
- Stats(Module *creator, const Anope::string &mname = "STATS") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Stats(Module *creator, const Anope::string &mname = "STATS") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_REQUIRE_USER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Time : IRCDMessage
+ struct CoreExport Time
+ : IRCDMessage
{
- Time(Module *creator, const Anope::string &mname = "TIME") : IRCDMessage(creator, mname, 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Time(Module *creator, const Anope::string &mname = "TIME") : IRCDMessage(creator, mname, 0) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Topic : IRCDMessage
+ struct CoreExport Topic
+ : IRCDMessage
{
- Topic(Module *creator, const Anope::string &mname = "TOPIC") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ Topic(Module *creator, const Anope::string &mname = "TOPIC") : IRCDMessage(creator, mname, 2) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Version : IRCDMessage
+ struct CoreExport Version
+ : IRCDMessage
{
- Version(Module *creator, const Anope::string &mname = "VERSION") : IRCDMessage(creator, mname, 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Version(Module *creator, const Anope::string &mname = "VERSION") : IRCDMessage(creator, mname, 0) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
- struct CoreExport Whois : IRCDMessage
+ struct CoreExport Whois
+ : IRCDMessage
{
- Whois(Module *creator, const Anope::string &mname = "WHOIS") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ Whois(Module *creator, const Anope::string &mname = "WHOIS") : IRCDMessage(creator, mname, 1) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override;
};
} // namespace Message
diff --git a/include/modes.h b/include/modes.h
index dd35c533f..db84a64fe 100644
--- a/include/modes.h
+++ b/include/modes.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef MODES_H
-#define MODES_H
+#pragma once
#include "anope.h"
#include "base.h"
@@ -36,9 +35,10 @@ enum ModeClass
/** This class is the basis of all modes in Anope
*/
-class CoreExport Mode : public Base
+class CoreExport Mode
+ : public Base
{
- public:
+public:
/* Mode name */
Anope::string name;
/* Class of mode this is (user/channel) */
@@ -55,7 +55,7 @@ class CoreExport Mode : public Base
* @param type The mode type
*/
Mode(const Anope::string &mname, ModeClass mclass, char mc, ModeType type);
- virtual ~Mode();
+ virtual ~Mode() = default;
/** Can a user set this mode, used for mlock
* @param u The user
@@ -65,9 +65,10 @@ class CoreExport Mode : public Base
/** This class is a user mode, all user modes use this/inherit from this
*/
-class CoreExport UserMode : public Mode
+class CoreExport UserMode
+ : public Mode
{
- public:
+public:
/** constructor
* @param name The mode name
* @param mc The mode char
@@ -75,9 +76,10 @@ class CoreExport UserMode : public Mode
UserMode(const Anope::string &name, char mc);
};
-class CoreExport UserModeParam : public UserMode
+class CoreExport UserModeParam
+ : public UserMode
{
- public:
+public:
/** constructor
* @param name The mode name
* @param mc The mode char
@@ -93,9 +95,10 @@ class CoreExport UserModeParam : public UserMode
/** This class is a channel mode, all channel modes use this/inherit from this
*/
-class CoreExport ChannelMode : public Mode
+class CoreExport ChannelMode
+ : public Mode
{
- public:
+public:
/* channel modes that can possibly unwrap this mode */
std::vector<ChannelMode *> listeners;
@@ -105,7 +108,7 @@ class CoreExport ChannelMode : public Mode
*/
ChannelMode(const Anope::string &name, char mc);
- bool CanSet(User *u) const anope_override;
+ bool CanSet(User *u) const override;
virtual void Check() { }
@@ -124,9 +127,10 @@ class CoreExport ChannelMode : public Mode
/** This is a mode for lists, eg b/e/I. These modes should inherit from this
*/
-class CoreExport ChannelModeList : public ChannelMode
+class CoreExport ChannelModeList
+ : public ChannelMode
{
- public:
+public:
/** constructor
* @param name The mode name
* @param mc The mode char
@@ -162,9 +166,10 @@ class CoreExport ChannelModeList : public ChannelMode
/** This is a mode with a parameter, eg +k/l. These modes should use/inherit from this
*/
-class CoreExport ChannelModeParam : public ChannelMode
+class CoreExport ChannelModeParam
+ : public ChannelMode
{
- public:
+public:
/** constructor
* @param name The mode name
* @param mc The mode char
@@ -184,9 +189,10 @@ class CoreExport ChannelModeParam : public ChannelMode
/** This is a mode that is a channel status, eg +v/h/o/a/q.
*/
-class CoreExport ChannelModeStatus : public ChannelMode
+class CoreExport ChannelModeStatus
+ : public ChannelMode
{
- public:
+public:
/* The symbol, eg @ % + */
char symbol;
/* The "level" of the mode, used to compare with other modes.
@@ -207,29 +213,33 @@ class CoreExport ChannelModeStatus : public ChannelMode
* but we still have a representation for it.
*/
template<typename T>
-class CoreExport ChannelModeVirtual : public T
+class CoreExport ChannelModeVirtual
+ : public T
{
- Anope::string base;
+private:
ChannelMode *basech;
- public:
+protected:
+ Anope::string base;
+
+public:
ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename);
~ChannelModeVirtual();
- void Check() anope_override;
+ void Check() override;
- ChannelMode *Wrap(Anope::string &param) anope_override;
+ ChannelMode *Wrap(Anope::string &param) override;
- ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) anope_override = 0;
+ ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override = 0;
};
/* The status a user has on a channel (+v, +h, +o) etc */
-class CoreExport ChannelStatus
+class CoreExport ChannelStatus final
{
Anope::string modes;
- public:
- ChannelStatus();
+public:
+ ChannelStatus() = default;
ChannelStatus(const Anope::string &modes);
void AddMode(char c);
void DelMode(char c);
@@ -240,51 +250,56 @@ class CoreExport ChannelStatus
Anope::string BuildModePrefixList() const;
};
-class CoreExport UserModeOperOnly : public UserMode
+class CoreExport UserModeOperOnly
+ : public UserMode
{
- public:
+public:
UserModeOperOnly(const Anope::string &mname, char um) : UserMode(mname, um) { }
- bool CanSet(User *u) const anope_override;
+ bool CanSet(User *u) const override;
};
-class CoreExport UserModeNoone : public UserMode
+class CoreExport UserModeNoone
+ : public UserMode
{
- public:
+public:
UserModeNoone(const Anope::string &mname, char um) : UserMode(mname, um) { }
- bool CanSet(User *u) const anope_override;
+ bool CanSet(User *u) const override;
};
/** Channel mode +k (key)
*/
-class CoreExport ChannelModeKey : public ChannelModeParam
+class CoreExport ChannelModeKey
+ : public ChannelModeParam
{
- public:
+public:
ChannelModeKey(char mc) : ChannelModeParam("KEY", mc) { }
- bool IsValid(Anope::string &value) const anope_override;
+ bool IsValid(Anope::string &value) const override;
};
/** This class is used for oper only channel modes
*/
-class CoreExport ChannelModeOperOnly : public ChannelMode
+class CoreExport ChannelModeOperOnly
+ : public ChannelMode
{
- public:
+public:
ChannelModeOperOnly(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
/* Opers only */
- bool CanSet(User *u) const anope_override;
+ bool CanSet(User *u) const override;
};
/** This class is used for channel modes only servers may set
*/
-class CoreExport ChannelModeNoone : public ChannelMode
+class CoreExport ChannelModeNoone
+ : public ChannelMode
{
- public:
+public:
ChannelModeNoone(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
- bool CanSet(User *u) const anope_override;
+ bool CanSet(User *u) const override;
};
/** This is the mode manager
@@ -293,9 +308,9 @@ class CoreExport ChannelModeNoone : public ChannelMode
* This also contains a mode stacker that will combine multiple modes and set
* them on a channel or user at once
*/
-class CoreExport ModeManager
+class CoreExport ModeManager final
{
- public:
+public:
/* Number of generic channel and user modes we are tracking */
static unsigned GenericChannelModes;
@@ -389,13 +404,13 @@ class CoreExport ModeManager
/** Represents a mask set on a channel (b/e/I)
*/
-class CoreExport Entry
+class CoreExport Entry final
{
Anope::string name;
Anope::string mask;
- public:
- unsigned short cidr_len;
- int family;
+public:
+ unsigned short cidr_len = 0;
+ int family = 0;
Anope::string nick, user, host, real;
/** Constructor
@@ -407,9 +422,9 @@ class CoreExport Entry
/** Get the banned mask for this entry
* @return The mask
*/
- const Anope::string GetMask() const;
+ Anope::string GetMask() const;
- const Anope::string GetNUHMask() const;
+ Anope::string GetNUHMask() const;
/** Check if this entry matches a user
* @param u The user
@@ -418,5 +433,3 @@ class CoreExport Entry
*/
bool Matches(User *u, bool full = false) const;
};
-
-#endif // MODES_H
diff --git a/include/module.h b/include/module.h
index 1f140491b..ea500abea 100644
--- a/include/module.h
+++ b/include/module.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef MODULE_H
-#define MODULE_H
+#pragma once
#include "access.h"
#include "account.h"
@@ -50,5 +49,3 @@
#include "modules/pseudoclients/global.h"
#include "modules/pseudoclients/memoserv.h"
#include "modules/pseudoclients/nickserv.h"
-
-#endif // MODULE_H
diff --git a/include/modules.h b/include/modules.h
index 9f8cf6bf5..12637b1b4 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -9,11 +9,10 @@
* Based on the original code of Services by Andy Church.
*/
-#include "serialize.h"
-#ifndef MODULES_H
-#define MODULES_H
+#pragma once
+#include "serialize.h"
#include "base.h"
#include "modes.h"
#include "timers.h"
@@ -25,32 +24,7 @@
* and functions needed to make a module loadable by the OS.
* It defines the class factory and external AnopeInit and AnopeFini functions.
*/
-#ifdef _WIN32
-# define MODULE_INIT(x) \
- extern "C" DllExport Module *AnopeInit(const Anope::string &, const Anope::string &); \
- extern "C" Module *AnopeInit(const Anope::string &modname, const Anope::string &creator) \
- { \
- return new x(modname, creator); \
- } \
- BOOLEAN WINAPI DllMain(HINSTANCE, DWORD, LPVOID) \
- { \
- return TRUE; \
- } \
- extern "C" DllExport void AnopeFini(x *); \
- extern "C" void AnopeFini(x *m) \
- { \
- delete m; \
- } \
- extern "C" DllExport ModuleVersionC AnopeVersion() \
- { \
- ModuleVersionC ver; \
- ver.version_major = VERSION_MAJOR; \
- ver.version_minor = VERSION_MINOR; \
- ver.version_patch = VERSION_PATCH; \
- return ver; \
- }
-#else
-# define MODULE_INIT(x) \
+#define MODULE_INIT(x) \
extern "C" DllExport Module *AnopeInit(const Anope::string &modname, const Anope::string &creator) \
{ \
return new x(modname, creator); \
@@ -67,7 +41,6 @@
ver.version_patch = VERSION_PATCH; \
return ver; \
}
-#endif
/**
* This #define allows us to call a method in all
@@ -189,7 +162,7 @@ enum
};
typedef unsigned short ModType;
-struct ModuleVersionC
+struct ModuleVersionC final
{
int version_major, version_minor, version_patch;
};
@@ -197,14 +170,14 @@ struct ModuleVersionC
/** Returned by Module::GetVersion, used to see what version of Anope
* a module is compiled against.
*/
-class ModuleVersion
+class ModuleVersion final
{
- private:
+private:
int version_major;
int version_minor;
int version_patch;
- public:
+public:
ModuleVersion(const ModuleVersionC &);
/** Get the major version of Anope this was built against
@@ -223,15 +196,21 @@ class ModuleVersion
int GetPatch() const;
};
-class NotImplementedException : public CoreException { };
+class CoreExport NotImplementedException final
+ : public CoreException
+{
+public:
+ NotImplementedException() : CoreException("") { }
+};
/** Every module in Anope is actually a class.
*/
-class CoreExport Module : public Extensible
+class CoreExport Module
+ : public Extensible
{
- private:
+private:
bool permanent;
- public:
+public:
/** The module name (e.g. os_modload)
*/
Anope::string name;
@@ -311,7 +290,7 @@ class CoreExport Module : public Extensible
* @param cu The user, channel, and status of the user being kicked
* @param kickmsg The reason for the kick.
*/
- virtual void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) { throw NotImplementedException(); }
+ virtual void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user has been kicked from a channel.
* @param source The kicker
@@ -320,13 +299,13 @@ class CoreExport Module : public Extensible
* @param status The status the kicked user had on the channel before they were kicked
* @param kickmsg The reason for the kick.
*/
- virtual void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) { throw NotImplementedException(); }
+ virtual void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
- /** Called when Services' configuration is being (re)loaded.
+ /** Called when the configuration is being (re)loaded.
* @param conf The config that is being built now and will replace the global Config object
* @throws A ConfigException to abort the config (re)loading process.
*/
- virtual void OnReload(Configuration::Conf *conf) { throw NotImplementedException(); }
+ virtual void OnReload(Configuration::Conf *conf) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before a bot is assigned to a channel.
* @param sender The user assigning the bot
@@ -334,35 +313,35 @@ class CoreExport Module : public Extensible
* @param bi The bot being assigned.
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the assign.
*/
- virtual EventReturn OnPreBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) { throw NotImplementedException(); }
+ virtual EventReturn OnPreBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called when a bot is assigned ot a channel
*/
- virtual void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) { throw NotImplementedException(); }
+ virtual void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called before a bot is unassigned from a channel.
* @param sender The user unassigning the bot
* @param ci The channel the bot is being removed from
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the unassign.
*/
- virtual EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a new user connects to the network.
* @param u The connecting user.
* @param exempt set to true/is true if the user should be excepted from bans etc
*/
- virtual void OnUserConnect(User *u, bool &exempt) { throw NotImplementedException(); }
+ virtual void OnUserConnect(User *u, bool &exempt) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a new server connects to the network.
* @param s The server that has connected to the network
*/
- virtual void OnNewServer(Server *s) { throw NotImplementedException(); }
+ virtual void OnNewServer(Server *s) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called after a user changed the nick
* @param u The user.
* @param oldnick The old nick of the user
*/
- virtual void OnUserNickChange(User *u, const Anope::string &oldnick) { throw NotImplementedException(); }
+ virtual void OnUserNickChange(User *u, const Anope::string &oldnick) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when someone uses the generic/help command
* @param source Command source
@@ -383,14 +362,14 @@ class CoreExport Module : public Extensible
* @param params The parameters the user is sending
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
- virtual EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) { throw NotImplementedException(); }
+ virtual EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called after a command has been executed.
* @param source The source of the command
* @param command The command the user executed
* @param params The parameters the user sent
*/
- virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params) { throw NotImplementedException(); }
+ virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when the databases are saved
*/
@@ -404,7 +383,6 @@ class CoreExport Module : public Extensible
/** Called when anope needs to check passwords against encryption
*/
virtual EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) { throw NotImplementedException(); }
- virtual EventReturn OnDecrypt(const Anope::string &hashm, const Anope::string &src, Anope::string &dest) { throw NotImplementedException(); }
/** Called on fantasy command
* @param source The source of the command
@@ -413,7 +391,7 @@ class CoreExport Module : public Extensible
* @param params The params
* @return EVENT_STOP to halt processing and not run the command, EVENT_ALLOW to allow the command to be executed
*/
- virtual EventReturn OnBotFantasy(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) { throw NotImplementedException(); }
+ virtual EventReturn OnBotFantasy(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called on fantasy command without access
* @param source The source of the command
@@ -422,31 +400,31 @@ class CoreExport Module : public Extensible
* @param params The params
* @return EVENT_STOP to halt processing and not run the command, EVENT_ALLOW to allow the command to be executed
*/
- virtual EventReturn OnBotNoFantasyAccess(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) { throw NotImplementedException(); }
+ virtual EventReturn OnBotNoFantasyAccess(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called when a bot places a ban
* @param u User being banned
* @param ci Channel the ban is placed on
* @param mask The mask being banned
*/
- virtual void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) { throw NotImplementedException(); }
+ virtual void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called before a badword is added to the badword list
* @param ci The channel
* @param bw The badword
*/
- virtual void OnBadWordAdd(ChannelInfo *ci, const BadWord *bw) { throw NotImplementedException(); }
+ virtual void OnBadWordAdd(ChannelInfo *ci, const BadWord *bw) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called before a badword is deleted from a channel
* @param ci The channel
* @param bw The badword
*/
- virtual void OnBadWordDel(ChannelInfo *ci, const BadWord *bw) { throw NotImplementedException(); }
+ virtual void OnBadWordDel(ChannelInfo *ci, const BadWord *bw) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a bot is created or destroyed
*/
- virtual void OnCreateBot(BotInfo *bi) { throw NotImplementedException(); }
- virtual void OnDelBot(BotInfo *bi) { throw NotImplementedException(); }
+ virtual void OnCreateBot(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
+ virtual void OnDelBot(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before a bot kicks a user
* @param bi The bot sending the kick
@@ -455,13 +433,13 @@ class CoreExport Module : public Extensible
* @param reason The reason
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
- virtual EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason) { throw NotImplementedException(); }
+ virtual EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called before a user parts a channel
* @param u The user
* @param c The channel
*/
- virtual void OnPrePartChannel(User *u, Channel *c) {}
+ virtual void OnPrePartChannel(User *u, Channel *c) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user parts a channel
* @param u The user
@@ -469,14 +447,14 @@ class CoreExport Module : public Extensible
* @param channel The channel name
* @param msg The part reason
*/
- virtual void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) { throw NotImplementedException(); }
+ virtual void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user leaves a channel.
* From either parting, being kicked, or quitting/killed!
* @param u The user
* @param c The channel
*/
- virtual void OnLeaveChannel(User *u, Channel *c) { throw NotImplementedException(); }
+ virtual void OnLeaveChannel(User *u, Channel *c) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called after a user joins a channel
* If this event triggers the user is allowed to be in the channel, and will
@@ -485,7 +463,7 @@ class CoreExport Module : public Extensible
* @param u The user
* @param channel The channel
*/
- virtual void OnJoinChannel(User *u, Channel *c) { throw NotImplementedException(); }
+ virtual void OnJoinChannel(User *u, Channel *c) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a new topic is set
* @param source The user changing the topic, if any
@@ -493,18 +471,18 @@ class CoreExport Module : public Extensible
* @param setter The user who set the new topic, if there is no source
* @param topic The new topic
*/
- virtual void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) { throw NotImplementedException(); }
+ virtual void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called before a channel expires
* @param ci The channel
* @param expire Set to true to allow the chan to expire
*/
- virtual void OnPreChanExpire(ChannelInfo *ci, bool &expire) { throw NotImplementedException(); }
+ virtual void OnPreChanExpire(ChannelInfo *ci, bool &expire) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before a channel expires
* @param ci The channel
*/
- virtual void OnChanExpire(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual void OnChanExpire(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before Anope connects to its uplink
*/
@@ -516,7 +494,7 @@ class CoreExport Module : public Extensible
/** Called when we are almost done synching with the uplink, just before we send the EOB
*/
- virtual void OnPreUplinkSync(Server *serv) { throw NotImplementedException(); }
+ virtual void OnPreUplinkSync(Server *serv) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when Anope disconnects from its uplink, before it tries to reconnect
*/
@@ -534,12 +512,12 @@ class CoreExport Module : public Extensible
* @param na The nick
* @param expire Set to true to allow the nick to expire
*/
- virtual void OnPreNickExpire(NickAlias *na, bool &expire) { throw NotImplementedException(); }
+ virtual void OnPreNickExpire(NickAlias *na, bool &expire) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick drops
* @param na The nick
*/
- virtual void OnNickExpire(NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnNickExpire(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when defcon level changes
* @param level The level
@@ -550,13 +528,13 @@ class CoreExport Module : public Extensible
* @param ex The exception
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
- virtual EventReturn OnExceptionAdd(Exception *ex) { throw NotImplementedException(); }
+ virtual EventReturn OnExceptionAdd(Exception *ex) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before an exception is deleted
* @param source The source deleting it
* @param ex The exception
*/
- virtual void OnExceptionDel(CommandSource &source, Exception *ex) { throw NotImplementedException(); }
+ virtual void OnExceptionDel(CommandSource &source, Exception *ex) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called before a XLine is added
* @param source The source of the XLine
@@ -564,31 +542,31 @@ class CoreExport Module : public Extensible
* @param xlm The xline manager it was added to
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
- virtual EventReturn OnAddXLine(CommandSource &source, const XLine *x, XLineManager *xlm) { throw NotImplementedException(); }
+ virtual EventReturn OnAddXLine(CommandSource &source, const XLine *x, XLineManager *xlm) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called before a XLine is deleted
* @param source The source of the XLine
* @param x The XLine
* @param xlm The xline manager it was deleted from
*/
- virtual void OnDelXLine(CommandSource &source, const XLine *x, XLineManager *xlm) { throw NotImplementedException(); }
+ virtual void OnDelXLine(CommandSource &source, const XLine *x, XLineManager *xlm) ATTR_NOT_NULL(4) { throw NotImplementedException(); }
/** Called when a user is checked for whether they are a services oper
* @param u The user
* @return EVENT_ALLOW to allow, anything else to deny
*/
- virtual EventReturn IsServicesOper(User *u) { throw NotImplementedException(); }
+ virtual EventReturn IsServicesOper(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a server quits
* @param server The server
*/
- virtual void OnServerQuit(Server *server) { throw NotImplementedException(); }
+ virtual void OnServerQuit(Server *server) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user quits, or is killed
* @param u The user
* @param msg The quit message
*/
- virtual void OnUserQuit(User *u, const Anope::string &msg) { throw NotImplementedException(); }
+ virtual void OnUserQuit(User *u, const Anope::string &msg) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user is quit, before and after being internally removed from
* This is different from OnUserQuit, which takes place at the time of the quit.
@@ -596,43 +574,43 @@ class CoreExport Module : public Extensible
* all lists (channels, user list, etc)
* @param u The user
*/
- virtual void OnPreUserLogoff(User *u) { throw NotImplementedException(); }
- virtual void OnPostUserLogoff(User *u) { throw NotImplementedException(); }
+ virtual void OnPreUserLogoff(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
+ virtual void OnPostUserLogoff(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a new bot is made
* @param bi The bot
*/
- virtual void OnBotCreate(BotInfo *bi) { throw NotImplementedException(); }
+ virtual void OnBotCreate(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a bot is changed
* @param bi The bot
*/
- virtual void OnBotChange(BotInfo *bi) { throw NotImplementedException(); }
+ virtual void OnBotChange(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a bot is deleted
* @param bi The bot
*/
- virtual void OnBotDelete(BotInfo *bi) { throw NotImplementedException(); }
+ virtual void OnBotDelete(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called after an access entry is deleted from a channel
* @param ci The channel
* @param source The source of the command
* @param access The access entry that was removed
*/
- virtual void OnAccessDel(ChannelInfo *ci, CommandSource &source, ChanAccess *access) { throw NotImplementedException(); }
+ virtual void OnAccessDel(ChannelInfo *ci, CommandSource &source, ChanAccess *access) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when access is added
* @param ci The channel
* @param source The source of the command
* @param access The access changed
*/
- virtual void OnAccessAdd(ChannelInfo *ci, CommandSource &source, ChanAccess *access) { throw NotImplementedException(); }
+ virtual void OnAccessAdd(ChannelInfo *ci, CommandSource &source, ChanAccess *access) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when the access list is cleared
* @param ci The channel
* @param u The user who cleared the access
*/
- virtual void OnAccessClear(ChannelInfo *ci, CommandSource &source) { throw NotImplementedException(); }
+ virtual void OnAccessClear(ChannelInfo *ci, CommandSource &source) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a level for a channel is changed
* @param source The source of the command
@@ -640,63 +618,63 @@ class CoreExport Module : public Extensible
* @param priv The privilege changed
* @param what The new level
*/
- virtual void OnLevelChange(CommandSource &source, ChannelInfo *ci, const Anope::string &priv, int16_t what) { throw NotImplementedException(); }
+ virtual void OnLevelChange(CommandSource &source, ChannelInfo *ci, const Anope::string &priv, int16_t what) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called right before a channel is dropped
* @param source The user dropping the channel
* @param ci The channel
*/
- virtual EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a channel is registered
* @param ci The channel
*/
- virtual void OnChanRegistered(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual void OnChanRegistered(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is suspended
* @param ci The channel
*/
- virtual void OnChanSuspend(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual void OnChanSuspend(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is unsuspended
* @param ci The channel
*/
- virtual void OnChanUnsuspend(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual void OnChanUnsuspend(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is being created, for any reason
* @param ci The channel
*/
- virtual void OnCreateChan(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual void OnCreateChan(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is being deleted, for any reason
* @param ci The channel
*/
- virtual void OnDelChan(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual void OnDelChan(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a new channel is created
* Note that this channel may not be introduced to the uplink at this point.
* @param c The channel
*/
- virtual void OnChannelCreate(Channel *c) { throw NotImplementedException(); }
+ virtual void OnChannelCreate(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is deleted
* @param c The channel
*/
- virtual void OnChannelDelete(Channel *c) { throw NotImplementedException(); }
+ virtual void OnChannelDelete(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called after adding an akick to a channel
* @param source The source of the command
* @param ci The channel
* @param ak The akick
*/
- virtual void OnAkickAdd(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) { throw NotImplementedException(); }
+ virtual void OnAkickAdd(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called before removing an akick from a channel
* @param source The source of the command
* @param ci The channel
* @param ak The akick
*/
- virtual void OnAkickDel(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) { throw NotImplementedException(); }
+ virtual void OnAkickDel(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called after a user join a channel when we decide whether to kick them or not
* @param u The user
@@ -706,7 +684,7 @@ class CoreExport Module : public Extensible
* @param reason The reason for the kick
* @return EVENT_STOP to prevent the user from joining by kicking/banning the user
*/
- virtual EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) { throw NotImplementedException(); }
+ virtual EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user requests info for a channel
* @param source The user requesting info
@@ -714,126 +692,109 @@ class CoreExport Module : public Extensible
* @param info Data to show the user requesting information
* @param show_hidden true if we should show the user everything
*/
- virtual void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) { throw NotImplementedException(); }
+ virtual void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Checks if access has the channel privilege 'priv'.
* @param access THe access struct
* @param priv The privilege being checked for
* @return EVENT_ALLOW for yes, EVENT_STOP to stop all processing
*/
- virtual EventReturn OnCheckPriv(const ChanAccess *access, const Anope::string &priv) { throw NotImplementedException(); }
+ virtual EventReturn OnCheckPriv(const ChanAccess *access, const Anope::string &priv) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Check whether an access group has a privilege
* @param group The group
* @param priv The privilege
* @return MOD_ALLOW to allow, MOD_STOP to stop
*/
- virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) { throw NotImplementedException(); }
+ virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick is dropped
* @param source The source of the command
* @param na The nick
*/
- virtual void OnNickDrop(CommandSource &source, NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnNickDrop(CommandSource &source, NickAlias *na) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user groups their nick
* @param u The user grouping
* @param target The target they're grouping to
*/
- virtual void OnNickGroup(User *u, NickAlias *target) { throw NotImplementedException(); }
+ virtual void OnNickGroup(User *u, NickAlias *target) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user identifies to a nick
* @param u The user
*/
- virtual void OnNickIdentify(User *u) { throw NotImplementedException(); }
+ virtual void OnNickIdentify(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user is logged into an account
* @param u The user
*/
- virtual void OnUserLogin(User *u) { throw NotImplementedException(); }
+ virtual void OnUserLogin(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick logs out
* @param u The nick
*/
- virtual void OnNickLogout(User *u) { throw NotImplementedException(); }
+ virtual void OnNickLogout(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick is registered
* @param user The user registering the nick, of any
* @param The nick
* @param pass The password of the newly registered nick
*/
- virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) { throw NotImplementedException(); }
+ virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a nick is confirmed. This will never be called if registration confirmation is not enabled.
* @param user The user confirming the nick
- * @param The account being confirmed
+ * @param nc The account being confirmed
*/
- virtual void OnNickConfirm(User *user, NickCore *) { throw NotImplementedException(); }
+ virtual void OnNickConfirm(User *user, NickCore *nc) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a nick is suspended
* @param na The nick alias
*/
- virtual void OnNickSuspend(NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnNickSuspend(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick is unsuspended
* @param na The nick alias
*/
- virtual void OnNickUnsuspended(NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnNickUnsuspended(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called on delnick()
* @ param na pointer to the nickalias
*/
- virtual void OnDelNick(NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnDelNick(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nickcore is created
* @param nc The nickcore
*/
- virtual void OnNickCoreCreate(NickCore *nc) { throw NotImplementedException(); }
+ virtual void OnNickCoreCreate(NickCore *nc) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called on delcore()
* @param nc pointer to the NickCore
*/
- virtual void OnDelCore(NickCore *nc) { throw NotImplementedException(); }
+ virtual void OnDelCore(NickCore *nc) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called on change_core_display()
* @param nc pointer to the NickCore
* @param newdisplay the new display
*/
- virtual void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) { throw NotImplementedException(); }
-
- /** called from NickCore::ClearAccess()
- * @param nc pointer to the NickCore
- */
- virtual void OnNickClearAccess(NickCore *nc) { throw NotImplementedException(); }
-
- /** Called when a user adds an entry to their access list
- * @param nc The nick
- * @param entry The entry
- */
- virtual void OnNickAddAccess(NickCore *nc, const Anope::string &entry) { throw NotImplementedException(); }
-
- /** Called from NickCore::EraseAccess()
- * @param nc pointer to the NickCore
- * @param entry The access mask
- */
- virtual void OnNickEraseAccess(NickCore *nc, const Anope::string &entry) { throw NotImplementedException(); }
+ virtual void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** called from NickCore::ClearCert()
* @param nc pointer to the NickCore
*/
- virtual void OnNickClearCert(NickCore *nc) { throw NotImplementedException(); }
+ virtual void OnNickClearCert(NickCore *nc) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user adds an entry to their cert list
* @param nc The nick
* @param entry The entry
*/
- virtual void OnNickAddCert(NickCore *nc, const Anope::string &entry) { throw NotImplementedException(); }
+ virtual void OnNickAddCert(NickCore *nc, const Anope::string &entry) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called from NickCore::EraseCert()
* @param nc pointer to the NickCore
* @param entry The fingerprint
*/
- virtual void OnNickEraseCert(NickCore *nc, const Anope::string &entry) { throw NotImplementedException(); }
+ virtual void OnNickEraseCert(NickCore *nc, const Anope::string &entry) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user requests info for a nick
* @param source The user requesting info
@@ -841,55 +802,55 @@ class CoreExport Module : public Extensible
* @param info Data to show the user requesting information
* @param show_hidden true if we should show the user everything
*/
- virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) { throw NotImplementedException(); }
+ virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user uses botserv/info on a bot or channel.
*/
- virtual void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) { throw NotImplementedException(); }
+ virtual void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) ATTR_NOT_NULL(4) { throw NotImplementedException(); }
/** Check whether a username and password is correct
* @param u The user trying to identify, if applicable.
* @param req The login request
*/
- virtual void OnCheckAuthentication(User *u, IdentifyRequest *req) { throw NotImplementedException(); }
+ virtual void OnCheckAuthentication(User *u, IdentifyRequest *req) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user does /ns update
* @param u The user
*/
- virtual void OnNickUpdate(User *u) { throw NotImplementedException(); }
+ virtual void OnNickUpdate(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when we get informed about a users SSL fingerprint
* when we call this, the fingerprint should already be stored in the user struct
* @param u pointer to the user
*/
- virtual void OnFingerprint(User *u) { throw NotImplementedException(); }
+ virtual void OnFingerprint(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user becomes (un)away
* @param message The message, is .empty() if unaway
*/
- virtual void OnUserAway(User *u, const Anope::string &message) { throw NotImplementedException(); }
+ virtual void OnUserAway(User *u, const Anope::string &message) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user invites one of our users to a channel
* @param source The user doing the inviting
* @param c The channel the user is inviting to
* @param targ The user being invited
*/
- virtual void OnInvite(User *source, Channel *c, User *targ) { throw NotImplementedException(); }
+ virtual void OnInvite(User *source, Channel *c, User *targ) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called when a vhost is deleted
* @param na The nickalias of the vhost
*/
- virtual void OnDeleteVhost(NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnDeleteVHost(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a vhost is set
* @param na The nickalias of the vhost
*/
- virtual void OnSetVhost(NickAlias *na) { throw NotImplementedException(); }
+ virtual void OnSetVHost(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a users host changes
* @param u The user
*/
- virtual void OnSetDisplayedHost(User *) { throw NotImplementedException(); }
+ virtual void OnSetDisplayedHost(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a memo is sent
* @param source The source of the memo
@@ -897,14 +858,14 @@ class CoreExport Module : public Extensible
* @param mi Memo info for target
* @param m The memo
*/
- virtual void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) { throw NotImplementedException(); }
+ virtual void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) ATTR_NOT_NULL(4, 5) { throw NotImplementedException(); }
/** Called when a memo is deleted
* @param target The target the memo is being deleted from (nick or channel)
* @param mi The memo info
* @param m The memo
*/
- virtual void OnMemoDel(const Anope::string &target, MemoInfo *mi, const Memo *m) { throw NotImplementedException(); }
+ virtual void OnMemoDel(const Anope::string &target, MemoInfo *mi, const Memo *m) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called when a mode is set on a channel
* @param c The channel
@@ -913,7 +874,7 @@ class CoreExport Module : public Extensible
* @param param The mode param, if there is one
* @return EVENT_STOP to make mlock/secureops etc checks not happen
*/
- virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) { throw NotImplementedException(); }
+ virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when a mode is unset on a channel
* @param c The channel
@@ -922,94 +883,97 @@ class CoreExport Module : public Extensible
* @param param The mode param, if there is one
* @return EVENT_STOP to make mlock/secureops etc checks not happen
*/
- virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) { throw NotImplementedException(); }
+ virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when a mode is set on a user
* @param setter who/what is setting the mode
* @param u The user
* @param mname The mode name
*/
- virtual void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) { throw NotImplementedException(); }
+ virtual void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a mode is unset from a user
* @param setter who/what is setting the mode
* @param u The user
* @param mname The mode name
*/
- virtual void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) { throw NotImplementedException(); }
+ virtual void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a channel mode is introduced into Anope
* @param cm The mode
*/
- virtual void OnChannelModeAdd(ChannelMode *cm) { throw NotImplementedException(); }
+ virtual void OnChannelModeAdd(ChannelMode *cm) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user mode is introduced into Anope
* @param um The mode
*/
- virtual void OnUserModeAdd(UserMode *um) { throw NotImplementedException(); }
+ virtual void OnUserModeAdd(UserMode *um) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a mode is about to be mlocked
* @param ci The channel the mode is being locked on
* @param lock The mode lock
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock.
*/
- virtual EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) { throw NotImplementedException(); }
+ virtual EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a mode is about to be unlocked
* @param ci The channel the mode is being unlocked from
* @param lock The mode lock
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock.
*/
- virtual EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) { throw NotImplementedException(); }
+ virtual EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called after a module is loaded
* @param u The user loading the module, can be NULL
* @param m The module
*/
- virtual void OnModuleLoad(User *u, Module *m) { throw NotImplementedException(); }
+ virtual void OnModuleLoad(User *u, Module *m) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called before a module is unloaded
* @param u The user, can be NULL
* @param m The module
*/
- virtual void OnModuleUnload(User *u, Module *m) { throw NotImplementedException(); }
+ virtual void OnModuleUnload(User *u, Module *m) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a server is synced
* @param s The server, can be our uplink server
*/
- virtual void OnServerSync(Server *s) { throw NotImplementedException(); }
+ virtual void OnServerSync(Server *s) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when we sync with our uplink
* @param s Our uplink
*/
- virtual void OnUplinkSync(Server *s) { throw NotImplementedException(); }
+ virtual void OnUplinkSync(Server *s) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when we receive a PRIVMSG for one of our clients
* @param u The user sending the PRIVMSG
* @param bi The target of the PRIVMSG
* @param message The message
+ * @param tags Message tags
* @return EVENT_STOP to halt processing
*/
- virtual EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) { throw NotImplementedException(); }
+ virtual EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when we receive a NOTICE for one of our clients
* @param u The user sending the NOTICE
* @param bi The target of the NOTICE
+ * @param tags Message tags
* @param message The message
*/
- virtual void OnBotNotice(User *u, BotInfo *bi, Anope::string &message) { throw NotImplementedException(); }
+ virtual void OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when we receive a PRIVMSG for a registered channel we are in
* @param u The source of the message
* @param c The channel
* @param msg The message
+ * @param tags Message tags
*/
- virtual void OnPrivmsg(User *u, Channel *c, Anope::string &msg) { throw NotImplementedException(); }
+ virtual void OnPrivmsg(User *u, Channel *c, Anope::string &msg, const Anope::map<Anope::string> &tags) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a message is logged
* @param l The log message
*/
- virtual void OnLog(Log *l) { throw NotImplementedException(); }
+ virtual void OnLog(Log *l) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a log message is actually logged to a given log info
* The message has already passed validation checks by the LogInfo
@@ -1017,13 +981,13 @@ class CoreExport Module : public Extensible
* @param l The log message
* @param msg The final formatted message, derived from 'l'
*/
- virtual void OnLogMessage(LogInfo *li, const Log *l, const Anope::string &msg) { throw NotImplementedException(); }
+ virtual void OnLogMessage(LogInfo *li, const Log *l, const Anope::string &msg) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a DNS request (question) is received.
* @param req The dns request
* @param reply The reply that will be sent
*/
- virtual void OnDnsRequest(DNS::Query &req, DNS::Query *reply) { throw NotImplementedException(); }
+ virtual void OnDnsRequest(DNS::Query &req, DNS::Query *reply) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a channels modes are being checked to see if they are allowed,
* mostly to ensure mlock/+r are set.
@@ -1036,7 +1000,7 @@ class CoreExport Module : public Extensible
* for a newly created channel to set the correct modes, topic,
* set.
*/
- virtual void OnChannelSync(Channel *c) { throw NotImplementedException(); }
+ virtual void OnChannelSync(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called to set the correct modes on the user on the given channel
* @param user The user
@@ -1045,13 +1009,13 @@ class CoreExport Module : public Extensible
* @param give_modes If giving modes is desired
* @param take_modes If taking modes is desired
*/
- virtual void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) { throw NotImplementedException(); }
+ virtual void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
- virtual void OnSerializeCheck(Serialize::Type *) { throw NotImplementedException(); }
- virtual void OnSerializableConstruct(Serializable *) { throw NotImplementedException(); }
- virtual void OnSerializableDestruct(Serializable *) { throw NotImplementedException(); }
- virtual void OnSerializableUpdate(Serializable *) { throw NotImplementedException(); }
- virtual void OnSerializeTypeCreate(Serialize::Type *) { throw NotImplementedException(); }
+ virtual void OnSerializeCheck(Serialize::Type *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
+ virtual void OnSerializableConstruct(Serializable *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
+ virtual void OnSerializableDestruct(Serializable *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
+ virtual void OnSerializableUpdate(Serializable *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
+ virtual void OnSerializeTypeCreate(Serialize::Type *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a chanserv/set command is used
* @param source The source of the command
@@ -1060,7 +1024,7 @@ class CoreExport Module : public Extensible
* @param setting The setting passed to the command. Probably ON/OFF.
* @return EVENT_ALLOW to bypass access checks, EVENT_STOP to halt immediately.
*/
- virtual EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) { throw NotImplementedException(); }
+ virtual EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called when a nickserv/set command is used.
* @param source The source of the command
@@ -1069,23 +1033,24 @@ class CoreExport Module : public Extensible
* @param setting The setting passed to the command. Probably ON/OFF.
* @return EVENT_STOP to halt immediately
*/
- virtual EventReturn OnSetNickOption(CommandSource &source, Command *cmd, NickCore *nc, const Anope::string &setting) { throw NotImplementedException(); }
+ virtual EventReturn OnSetNickOption(CommandSource &source, Command *cmd, NickCore *nc, const Anope::string &setting) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called whenever a message is received from the uplink
* @param source The source of the message
* @param command The command being executed
* @param params Parameters
+ * @param tags Tags
* @return EVENT_STOP to prevent the protocol module from processing this message
*/
- virtual EventReturn OnMessage(MessageSource &source, Anope::string &command, std::vector<Anope::string> &param) { throw NotImplementedException(); }
+ virtual EventReturn OnMessage(MessageSource &source, Anope::string &command, std::vector<Anope::string> &params, Anope::map<Anope::string> &tagss) { throw NotImplementedException(); }
/** Called to determine if a channel mode can be set by a user
* @param u The user
* @param cm The mode
*/
- virtual EventReturn OnCanSet(User *u, const ChannelMode *cm) { throw NotImplementedException(); }
+ virtual EventReturn OnCanSet(User *u, const ChannelMode *cm) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
- virtual EventReturn OnCheckDelete(Channel *) { throw NotImplementedException(); }
+ virtual EventReturn OnCheckDelete(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called every options:expiretimeout seconds. Should be used to expire nicks,
* channels, etc.
@@ -1098,14 +1063,7 @@ class CoreExport Module : public Extensible
* @param na The nick they are on
* @return EVENT_STOP to force the user off of the nick
*/
- virtual EventReturn OnNickValidate(User *u, NickAlias *na) { throw NotImplementedException(); }
-
- /** Called when a certain user has to be unbanned on a certain channel.
- * May be used to send protocol-specific messages.
- * @param u The user to be unbanned
- * @param c The channel that user has to be unbanned on
- */
- virtual void OnChannelUnban(User *u, ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual EventReturn OnNickValidate(User *u, NickAlias *na) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
};
enum Implementation
@@ -1123,23 +1081,23 @@ enum Implementation
I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick,
I_OnChanInfo, I_OnCheckPriv, I_OnGroupCheckPriv, I_OnNickDrop, I_OnNickGroup, I_OnNickIdentify,
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickConfirm, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
- I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearCert,
+ I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearCert,
I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnBotInfo, I_OnCheckAuthentication, I_OnNickUpdate,
- I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVhost, I_OnSetVhost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
+ I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVHost, I_OnSetVHost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd,
I_OnMLock, I_OnUnMLock, I_OnModuleLoad, I_OnModuleUnload, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnBotNotice,
I_OnPrivmsg, I_OnLog, I_OnLogMessage, I_OnDnsRequest, I_OnCheckModes, I_OnChannelSync, I_OnSetCorrectModes,
I_OnSerializeCheck, I_OnSerializableConstruct, I_OnSerializableDestruct, I_OnSerializableUpdate,
I_OnSerializeTypeCreate, I_OnSetChannelOption, I_OnSetNickOption, I_OnMessage, I_OnCanSet, I_OnCheckDelete,
- I_OnExpireTick, I_OnNickValidate, I_OnChannelUnban,
+ I_OnExpireTick, I_OnNickValidate,
I_SIZE
};
/** Used to manage modules.
*/
-class CoreExport ModuleManager
+class CoreExport ModuleManager final
{
- public:
+public:
/** Event handler hooks.
*/
static std::vector<Module *> EventHandlers[I_SIZE];
@@ -1222,7 +1180,7 @@ class CoreExport ModuleManager
*/
static void UnloadAll();
- private:
+private:
/** Call the module_delete function to safely delete the module
* @param m the module to delete
* @return MOD_ERR_OK on success, anything else on fail
@@ -1234,5 +1192,3 @@ class CoreExport ModuleManager
*/
static ModuleVersion GetVersion(void *handle);
};
-
-#endif // MODULES_H
diff --git a/include/modules/bs_badwords.h b/include/modules/bs_badwords.h
index db5e6c461..ae78df8b1 100644
--- a/include/modules/bs_badwords.h
+++ b/include/modules/bs_badwords.h
@@ -9,6 +9,8 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
/** Flags for badwords
*/
enum BadWordType
@@ -30,27 +32,27 @@ struct BadWord
Anope::string word;
BadWordType type;
- virtual ~BadWord() { }
- protected:
- BadWord() { }
+ virtual ~BadWord() = default;
+protected:
+ BadWord() = default;
};
struct BadWords
{
- virtual ~BadWords() { }
+ virtual ~BadWords() = default;
/** Add a badword to the badword list
* @param word The badword
* @param type The type (SINGLE START END)
* @return The badword
*/
- virtual BadWord* AddBadWord(const Anope::string &word, BadWordType type) = 0;
+ virtual BadWord *AddBadWord(const Anope::string &word, BadWordType type) = 0;
/** Get a badword structure by index
* @param index The index
* @return The badword
*/
- virtual BadWord* GetBadWord(unsigned index) const = 0;
+ virtual BadWord *GetBadWord(unsigned index) const = 0;
/** Get how many badwords are on this channel
* @return The number of badwords in the vector
diff --git a/include/modules/bs_kick.h b/include/modules/bs_kick.h
index e9bcc7fdf..8ad44aab5 100644
--- a/include/modules/bs_kick.h
+++ b/include/modules/bs_kick.h
@@ -9,6 +9,8 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
/* Indices for TTB (Times To Ban) */
enum
{
@@ -35,10 +37,10 @@ struct KickerData
bool dontkickops, dontkickvoices;
- protected:
- KickerData() { }
+protected:
+ KickerData() = default;
- public:
- virtual ~KickerData() { }
+public:
+ virtual ~KickerData() = default;
virtual void Check(ChannelInfo *ci) = 0;
};
diff --git a/include/modules/cs_entrymsg.h b/include/modules/cs_entrymsg.h
index a7ec337e0..2672f8ac0 100644
--- a/include/modules/cs_entrymsg.h
+++ b/include/modules/cs_entrymsg.h
@@ -6,6 +6,8 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
struct EntryMsg
{
Anope::string chan;
@@ -13,22 +15,23 @@ struct EntryMsg
Anope::string message;
time_t when;
- virtual ~EntryMsg() { }
- protected:
- EntryMsg() { }
+ virtual ~EntryMsg() = default;
+protected:
+ EntryMsg() = default;
};
-struct EntryMessageList : Serialize::Checker<std::vector<EntryMsg *> >
+struct EntryMessageList
+ : Serialize::Checker<std::vector<EntryMsg *> >
{
- protected:
+protected:
EntryMessageList() : Serialize::Checker<std::vector<EntryMsg *> >("EntryMsg") { }
- public:
+public:
virtual ~EntryMessageList()
{
for (unsigned i = (*this)->size(); i > 0; --i)
delete (*this)->at(i - 1);
}
- virtual EntryMsg* Create() = 0;
+ virtual EntryMsg *Create() = 0;
};
diff --git a/include/modules/cs_log.h b/include/modules/cs_log.h
index 1615c5b9f..f9549126b 100644
--- a/include/modules/cs_log.h
+++ b/include/modules/cs_log.h
@@ -9,6 +9,8 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
struct LogSetting
{
Anope::string chan;
@@ -22,21 +24,22 @@ struct LogSetting
Anope::string creator;
time_t created;
- virtual ~LogSetting() { }
- protected:
- LogSetting() { }
+ virtual ~LogSetting() = default;
+protected:
+ LogSetting() = default;
};
-struct LogSettings : Serialize::Checker<std::vector<LogSetting *> >
+struct LogSettings
+ : Serialize::Checker<std::vector<LogSetting *> >
{
typedef std::vector<LogSetting *>::iterator iterator;
- protected:
+protected:
LogSettings() : Serialize::Checker<std::vector<LogSetting *> >("LogSetting")
{
}
- public:
- virtual ~LogSettings() { }
+public:
+ virtual ~LogSettings() = default;
virtual LogSetting *Create() = 0;
};
diff --git a/include/modules/cs_mode.h b/include/modules/cs_mode.h
index 9ef04da68..f3668c004 100644
--- a/include/modules/cs_mode.h
+++ b/include/modules/cs_mode.h
@@ -9,6 +9,8 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
struct ModeLock
{
Anope::string ci;
@@ -18,16 +20,16 @@ struct ModeLock
Anope::string setter;
time_t created;
- virtual ~ModeLock() { }
- protected:
- ModeLock() { }
+ virtual ~ModeLock() = default;
+protected:
+ ModeLock() = default;
};
struct ModeLocks
{
typedef std::vector<ModeLock *> ModeList;
- virtual ~ModeLocks() { }
+ virtual ~ModeLocks() = default;
/** Check if a mode is mlocked
* @param mode The mode
diff --git a/include/modules/dns.h b/include/modules/dns.h
index 1aee0623e..1ab18a20f 100644
--- a/include/modules/dns.h
+++ b/include/modules/dns.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef DNS_H
-#define DNS_H
+#pragma once
namespace DNS
{
@@ -73,14 +72,14 @@ namespace DNS
struct Question
{
Anope::string name;
- QueryType type;
- unsigned short qclass;
+ QueryType type = QUERY_NONE;
+ unsigned short qclass = 0;
- Question() : type(QUERY_NONE), qclass(0) { }
+ Question() = default;
Question(const Anope::string &n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { }
inline bool operator==(const Question & other) const { return name == other.name && type == other.type && qclass == other.qclass; }
- struct hash
+ struct hash final
{
size_t operator()(const Question &q) const
{
@@ -89,14 +88,15 @@ namespace DNS
};
};
- struct ResourceRecord : Question
+ struct ResourceRecord final
+ : Question
{
- unsigned int ttl;
+ unsigned int ttl = 0;
Anope::string rdata;
time_t created;
- ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(Anope::CurTime) { }
- ResourceRecord(const Question &q) : Question(q), ttl(0), created(Anope::CurTime) { }
+ ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), created(Anope::CurTime) { }
+ ResourceRecord(const Question &q) : Question(q), created(Anope::CurTime) { }
};
struct Query
@@ -114,11 +114,12 @@ namespace DNS
/** DNS manager
*/
- class Manager : public Service
+ class Manager
+ : public Service
{
- public:
+ public:
Manager(Module *creator) : Service(creator, "DNS::Manager", "dns/manager") { }
- virtual ~Manager() { }
+ virtual ~Manager() = default;
virtual void Process(Request *req) = 0;
virtual void RemoveRequest(Request *req) = 0;
@@ -132,19 +133,27 @@ namespace DNS
/** A DNS query.
*/
- class Request : public Timer, public Question
+ class Request
+ : public Timer
+ , public Question
{
Manager *manager;
- public:
+ public:
/* Use result cache if available */
bool use_cache;
/* Request id */
- unsigned short id;
+ unsigned short id = 0;
/* Creator of this request */
Module *creator;
- Request(Manager *mgr, Module *c, const Anope::string &addr, QueryType qt, bool cache = false) : Timer(0), Question(addr, qt), manager(mgr),
- use_cache(cache), id(0), creator(c) { }
+ Request(Manager *mgr, Module *c, const Anope::string &addr, QueryType qt, bool cache = false)
+ : Timer(0)
+ , Question(addr, qt)
+ , manager(mgr)
+ , use_cache(cache)
+ , creator(c)
+ {
+ }
virtual ~Request()
{
@@ -164,7 +173,7 @@ namespace DNS
/** Used to time out the query, xalls OnError and lets the TimerManager
* delete this request.
*/
- void Tick(time_t) anope_override
+ void Tick() override
{
Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name;
Query rr(*this);
@@ -174,5 +183,3 @@ namespace DNS
};
} // namespace DNS
-
-#endif // DNS_H
diff --git a/include/modules/encryption.h b/include/modules/encryption.h
index 7f8988c09..9c5b58627 100644
--- a/include/modules/encryption.h
+++ b/include/modules/encryption.h
@@ -9,27 +9,139 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
namespace Encryption
{
- typedef std::pair<const unsigned char *, size_t> Hash;
- typedef std::pair<const uint32_t *, size_t> IV;
-
+ /** Base class for encryption contexts. */
class Context
{
- public:
- virtual ~Context() { }
+ public:
+ virtual ~Context() = default;
+
+ /** Updates the encryption context with the specified data.
+ * @param str The data to update the context with.
+ */
+ inline void Update(const Anope::string &str)
+ {
+ Update(reinterpret_cast<const unsigned char *>(str.c_str()), str.length());
+ }
+
+ /** Updates the encryption context with the specified data.
+ * @param data The data to update the context with.
+ * @param len The length of the data.
+ */
virtual void Update(const unsigned char *data, size_t len) = 0;
- virtual void Finalize() = 0;
- virtual Hash GetFinalizedHash() = 0;
+
+ /** Finalises the encryption context and returns the digest. */
+ virtual Anope::string Finalize() = 0;
+ };
+
+ /** Provider of encryption contexts. */
+ class Provider
+ : public Service
+ {
+ public:
+ /** The byte size of the block cipher. */
+ const size_t block_size;
+
+ /** The byte size of the resulting digest. */
+ const size_t digest_size;
+
+ /** Creates a provider of encryption contexts.
+ * @param creator The module that created this provider.
+ * @param algorithm The name of the encryption algorithm.
+ * @param bs The byte size of the block cipher.
+ * @param ds The byte size of the resulting digest.
+ */
+ Provider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
+ : Service(creator, "Encryption::Provider", algorithm)
+ , block_size(bs)
+ , digest_size(ds)
+ {
+ }
+
+ virtual ~Provider() = default;
+
+ /** Checks whether a plain text value matches a hash created by this provider. */
+ virtual bool Compare(const Anope::string &hash, const Anope::string &plain)
+ {
+ return !hash.empty() && hash.equals_cs(ToPrintable(Encrypt(plain)));
+ }
+
+ /** Called on initialising a encryption provider to check it works properly. */
+ void Check(const Anope::map<Anope::string> &checks)
+ {
+ for (const auto &[hash, plain] : checks)
+ {
+ if (!Compare(hash, plain))
+ throw ModuleException("BUG: unable to generate " + this->name + " hashes safely! Please report this!");
+ }
+ Log(LOG_DEBUG) << "The " << this->name << " encryption provider appears to be working correctly.";
+ }
+
+ /** Creates a new encryption context. */
+ virtual std::unique_ptr<Context> CreateContext() = 0;
+
+ /** Quickly encrypts the specified values and returns the digest. */
+ template<typename... Args>
+ Anope::string Encrypt(Args &&...args)
+ {
+ auto context = CreateContext();
+ context->Update(std::forward<Args>(args)...);
+ return context->Finalize();
+ }
+
+ /** Calculates the RFC 2104 hash-based message authentication code for the specified data. */
+ inline Anope::string HMAC(const Anope::string &key, const Anope::string &data)
+ {
+ if (!block_size)
+ return {};
+
+ auto keybuf = key.length() > block_size ? Encrypt(key) : key;
+ keybuf.resize(block_size);
+
+ Anope::string hmac1;
+ Anope::string hmac2;
+ for (size_t i = 0; i < block_size; ++i)
+ {
+ hmac1.push_back(static_cast<char>(keybuf[i] ^ 0x5C));
+ hmac2.push_back(static_cast<char>(keybuf[i] ^ 0x36));
+ }
+ hmac2.append(data);
+ hmac1.append(Encrypt(hmac2));
+
+ return Encrypt(hmac1);
+ }
+
+ /** Converts a hash to its printable form. */
+ virtual Anope::string ToPrintable(const Anope::string &hash)
+ {
+ return Anope::Hex(hash);
+ }
};
- class Provider : public Service
+ /** Helper template for creating simple providers of encryption contexts. */
+ template <typename T>
+ class SimpleProvider final
+ : public Provider
{
- public:
- Provider(Module *creator, const Anope::string &sname) : Service(creator, "Encryption::Provider", sname) { }
- virtual ~Provider() { }
+ public:
+ /** Creates a simple provider of encryption contexts.
+ * @param creator The module that created this provider.
+ * @param algorithm The name of the encryption algorithm.
+ * @param bs The byte size of the block cipher.
+ * @param ds The byte size of the resulting digest.
+ */
+ SimpleProvider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
+ : Provider(creator, algorithm, bs, ds)
+ {
+ }
- virtual Context *CreateContext(IV * = NULL) = 0;
- virtual IV GetDefaultIV() = 0;
+ /** @copydoc Encryption::Provider::CreateContext. */
+ std::unique_ptr<Context> CreateContext() override
+ {
+ return std::make_unique<T>();
+ }
};
}
diff --git a/include/modules/hs_request.h b/include/modules/hs_request.h
new file mode 100644
index 000000000..a1805a298
--- /dev/null
+++ b/include/modules/hs_request.h
@@ -0,0 +1,23 @@
+/*
+ *
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+class HostRequest
+{
+protected:
+ HostRequest() = default;
+
+public:
+ Anope::string nick;
+ Anope::string ident;
+ Anope::string host;
+ time_t time = 0;
+
+ virtual ~HostRequest() = default;
+};
diff --git a/include/modules/httpd.h b/include/modules/httpd.h
index bd2bde4a0..5b555fbab 100644
--- a/include/modules/httpd.h
+++ b/include/modules/httpd.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef ANOPE_HTTPD_H
-#define ANOPE_HTTPD_H
+#pragma once
enum HTTPError
{
@@ -19,34 +18,35 @@ enum HTTPError
};
/* A message to someone */
-struct HTTPReply
+struct HTTPReply final
{
- HTTPError error;
+ HTTPError error = HTTP_ERROR_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() : error(HTTP_ERROR_OK), length(0) { }
+ HTTPReply() = default;
+ HTTPReply &operator=(const HTTPReply &) = default;
- HTTPReply(const HTTPReply& other) : error(other.error), length(other.length)
+ HTTPReply(const HTTPReply &other) : error(other.error), length(other.length)
{
content_type = other.content_type;
headers = other.headers;
cookies = other.cookies;
- for (unsigned i = 0; i < other.out.size(); ++i)
- out.push_back(new Data(other.out[i]->buf, other.out[i]->len));
+ for (const auto &datum : other.out)
+ out.push_back(new Data(datum->buf, datum->len));
}
~HTTPReply()
{
- for (unsigned i = 0; i < out.size(); ++i)
- delete out[i];
+ for (const auto *datum : out)
+ delete datum;
out.clear();
}
- struct Data
+ struct Data final
{
char *buf;
size_t len;
@@ -65,7 +65,7 @@ struct HTTPReply
};
std::deque<Data *> out;
- size_t length;
+ size_t length = 0;
void Write(const Anope::string &message)
{
@@ -81,7 +81,7 @@ struct HTTPReply
};
/* A message from someone */
-struct HTTPMessage
+struct HTTPMessage final
{
std::map<Anope::string, Anope::string> headers;
std::map<Anope::string, Anope::string> cookies;
@@ -93,12 +93,13 @@ struct HTTPMessage
class HTTPClient;
class HTTPProvider;
-class HTTPPage : public Base
+class HTTPPage
+ : public virtual Base
{
Anope::string url;
Anope::string content_type;
- public:
+public:
HTTPPage(const Anope::string &u, const Anope::string &ct = "text/html") : url(u), content_type(ct) { }
const Anope::string &GetURL() const { return this->url; }
@@ -115,15 +116,18 @@ class HTTPPage : public Base
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
};
-class HTTPClient : public ClientSocket, public BinarySocket, public Base
+class HTTPClient
+ : public ClientSocket
+ , public BinarySocket
+ , public Base
{
- protected:
+protected:
void WriteClient(const Anope::string &message)
{
BinarySocket::Write(message + "\r\n");
}
- public:
+public:
HTTPClient(ListenSocket *l, int f, const sockaddrs &a) : ClientSocket(l, a), BinarySocket() { }
virtual const Anope::string GetIP()
@@ -135,12 +139,14 @@ class HTTPClient : public ClientSocket, public BinarySocket, public Base
virtual void SendReply(HTTPReply *) = 0;
};
-class HTTPProvider : public ListenSocket, public Service
+class HTTPProvider
+ : public ListenSocket
+ , public Service
{
Anope::string ip;
unsigned short port;
bool ssl;
- public:
+public:
std::vector<Anope::string> ext_ips;
std::vector<Anope::string> ext_headers;
@@ -163,7 +169,7 @@ class HTTPProvider : public ListenSocket, public Service
virtual bool RegisterPage(HTTPPage *page) = 0;
virtual void UnregisterPage(HTTPPage *page) = 0;
- virtual HTTPPage* FindPage(const Anope::string &name) = 0;
+ virtual HTTPPage *FindPage(const Anope::string &name) = 0;
};
namespace HTTPUtils
@@ -174,7 +180,7 @@ namespace HTTPUtils
for (unsigned i = 0; i < url.length(); ++i)
{
- const char& c = url[i];
+ const char &c = url[i];
if (c == '%' && i + 2 < url.length())
{
@@ -196,10 +202,8 @@ namespace HTTPUtils
{
Anope::string encoded;
- for (unsigned i = 0; i < url.length(); ++i)
+ for (const auto c : url)
{
- const char& c = url[i];
-
if (isalnum(c) || c == '.' || c == '-' || c == '*' || c == '_')
encoded += c;
else if (c == ' ')
@@ -215,9 +219,9 @@ namespace HTTPUtils
{
Anope::string dst;
- for (unsigned i = 0; i < src.length(); ++i)
+ for (const auto c : src)
{
- switch (src[i])
+ switch (c)
{
case '<':
dst += "&lt;";
@@ -232,12 +236,10 @@ namespace HTTPUtils
dst += "&amp;";
break;
default:
- dst += src[i];
+ dst += c;
}
}
return dst;
}
}
-
-#endif // ANOPE_HTTPD_H
diff --git a/include/modules/info.h b/include/modules/info.h
new file mode 100644
index 000000000..c38cf0b72
--- /dev/null
+++ b/include/modules/info.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+class OperInfo
+{
+protected:
+ OperInfo() = default;
+
+ OperInfo(const Anope::string &t, const Anope::string &i, const Anope::string &a, time_t c)
+ : target(t)
+ , info(i)
+ , adder(a)
+ , created(c)
+ {
+ }
+
+public:
+ Anope::string target;
+ Anope::string info;
+ Anope::string adder;
+ time_t created = 0;
+
+ virtual ~OperInfo() = default;
+};
+
+class OperInfoList
+ : public Serialize::Checker<std::vector<OperInfo *>>
+{
+public:
+ OperInfoList()
+ : Serialize::Checker<std::vector<OperInfo *>>("OperInfo")
+ {
+ }
+
+ virtual ~OperInfoList()
+ {
+ for (auto *info : *(*this))
+ delete info;
+ }
+
+ virtual OperInfo *Create() = 0;
+};
diff --git a/include/modules/ldap.h b/include/modules/ldap.h
index cc5a21b34..f982ea1ca 100644
--- a/include/modules/ldap.h
+++ b/include/modules/ldap.h
@@ -6,18 +6,17 @@
* Please read COPYING and README for further details.
*/
-#ifndef ANOPE_LDAP_H
-#define ANOPE_LDAP_H
+#pragma once
-class LDAPException : public ModuleException
+class DllExport LDAPException : public ModuleException
{
- public:
+public:
LDAPException(const Anope::string &reason) : ModuleException(reason) { }
- virtual ~LDAPException() throw() { }
+ virtual ~LDAPException() noexcept = default;
};
-struct LDAPModification
+struct LDAPModification final
{
enum LDAPOperation
{
@@ -32,7 +31,8 @@ struct LDAPModification
};
typedef std::vector<LDAPModification> LDAPMods;
-struct LDAPAttributes : public std::map<Anope::string, std::vector<Anope::string> >
+struct LDAPAttributes final
+ : public std::map<Anope::string, std::vector<Anope::string>>
{
size_t size(const Anope::string &attr) const
{
@@ -43,8 +43,8 @@ struct LDAPAttributes : public std::map<Anope::string, std::vector<Anope::string
const std::vector<Anope::string> keys() const
{
std::vector<Anope::string> k;
- for (const_iterator it = this->begin(), it_end = this->end(); it != it_end; ++it)
- k.push_back(it->first);
+ for (const auto &[key, _] : *this)
+ k.push_back(key);
return k;
}
@@ -75,7 +75,7 @@ enum QueryType
QUERY_MODIFY
};
-struct LDAPResult
+struct LDAPResult final
{
std::vector<LDAPAttributes> messages;
Anope::string error;
@@ -112,20 +112,21 @@ struct LDAPResult
class LDAPInterface
{
- public:
+public:
Module *owner;
LDAPInterface(Module *m) : owner(m) { }
- virtual ~LDAPInterface() { }
+ virtual ~LDAPInterface() = default;
virtual void OnResult(const LDAPResult &r) = 0;
virtual void OnError(const LDAPResult &err) = 0;
virtual void OnDelete() { }
};
-class LDAPProvider : public Service
+class LDAPProvider
+ : public Service
{
- public:
+public:
LDAPProvider(Module *c, const Anope::string &n) : Service(c, "LDAPProvider", n) { }
/** Attempt to bind to the LDAP server as an admin
@@ -167,5 +168,3 @@ class LDAPProvider : public Service
*/
virtual void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
};
-
-#endif // ANOPE_LDAP_H
diff --git a/include/modules/ns_cert.h b/include/modules/ns_cert.h
index 3fbe6b087..9462d66a0 100644
--- a/include/modules/ns_cert.h
+++ b/include/modules/ns_cert.h
@@ -9,12 +9,14 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
struct NSCertList
{
- protected:
- NSCertList() { }
- public:
- virtual ~NSCertList() { }
+protected:
+ NSCertList() = default;
+public:
+ virtual ~NSCertList() = default;
/** Add an entry to the nick's certificate list
*
@@ -52,6 +54,15 @@ struct NSCertList
*/
virtual void EraseCert(const Anope::string &entry) = 0;
+ /** Replaces a fingerprint in the nick's certificate list
+ *
+ * @param oldentry The old fingerprint to remove
+ * @param newentry The new fingerprint to add
+ *
+ * Replaces the specified fingerprint in the cert list.
+ */
+ virtual void ReplaceCert(const Anope::string &oldentry, const Anope::string &newentry) = 0;
+
/** Clears the entire nick's cert list
*
* Deletes all the memory allocated in the certificate list vector and then clears the vector.
@@ -61,10 +72,12 @@ struct NSCertList
virtual void Check() = 0;
};
-class CertService : public Service
+class CertService
+ : public Service
{
- public:
+public:
CertService(Module *c) : Service(c, "CertService", "certs") { }
- virtual NickCore* FindAccountFromCert(const Anope::string &cert) = 0;
+ virtual NickCore *FindAccountFromCert(const Anope::string &cert) = 0;
+ virtual void ReplaceCert(const Anope::string &oldcert, const Anope::string &newcert) = 0;
};
diff --git a/include/modules/os_forbid.h b/include/modules/os_forbid.h
index da3f8f62c..5c2f9d05c 100644
--- a/include/modules/os_forbid.h
+++ b/include/modules/os_forbid.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef OS_FORBID_H
-#define OS_FORBID_H
+#pragma once
enum ForbidType
{
@@ -23,25 +22,26 @@ struct ForbidData
Anope::string mask;
Anope::string creator;
Anope::string reason;
- time_t created;
- time_t expires;
+ time_t created = 0;
+ time_t expires = 0;
ForbidType type;
- virtual ~ForbidData() { }
- protected:
- ForbidData() : created(0), expires(0) { }
+ virtual ~ForbidData() = default;
+protected:
+ ForbidData() = default;
};
-class ForbidService : public Service
+class ForbidService
+ : public Service
{
- public:
+public:
ForbidService(Module *m) : Service(m, "ForbidService", "forbid") { }
virtual void AddForbid(ForbidData *d) = 0;
virtual void RemoveForbid(ForbidData *d) = 0;
- virtual ForbidData* CreateForbid() = 0;
+ virtual ForbidData *CreateForbid() = 0;
virtual ForbidData *FindForbid(const Anope::string &mask, ForbidType type) = 0;
@@ -51,5 +51,3 @@ class ForbidService : public Service
};
static ServiceReference<ForbidService> forbid_service("ForbidService", "forbid");
-
-#endif
diff --git a/include/modules/os_ignore.h b/include/modules/os_ignore.h
index a36d8264d..8a60a044f 100644
--- a/include/modules/os_ignore.h
+++ b/include/modules/os_ignore.h
@@ -9,24 +9,27 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
struct IgnoreData
{
Anope::string mask;
Anope::string creator;
Anope::string reason;
- time_t time; /* When do we stop ignoring them? */
+ time_t time = 0; /* When do we stop ignoring them? */
- virtual ~IgnoreData() { }
- protected:
- IgnoreData() : time(0) { }
+ virtual ~IgnoreData() = default;
+protected:
+ IgnoreData() = default;
};
-class IgnoreService : public Service
+class IgnoreService
+ : public Service
{
- protected:
+protected:
IgnoreService(Module *c) : Service(c, "IgnoreService", "ignore") { }
- public:
+public:
virtual void AddIgnore(IgnoreData *) = 0;
virtual void DelIgnore(IgnoreData *) = 0;
diff --git a/include/modules/os_news.h b/include/modules/os_news.h
index 2c488babf..815c71db6 100644
--- a/include/modules/os_news.h
+++ b/include/modules/os_news.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef OS_NEWS
-#define OS_NEWS
+#pragma once
enum NewsType
{
@@ -16,14 +15,15 @@ enum NewsType
NEWS_OPER
};
-struct NewsMessages
+struct NewsMessages final
{
NewsType type;
Anope::string name;
const char *msgs[10];
};
-struct NewsItem : Serializable
+struct NewsItem
+ : Serializable
{
NewsType type;
Anope::string text;
@@ -33,9 +33,10 @@ struct NewsItem : Serializable
NewsItem() : Serializable("NewsItem") { }
};
-class NewsService : public Service
+class NewsService
+ : public Service
{
- public:
+public:
NewsService(Module *m) : Service(m, "NewsService", "news") { }
virtual NewsItem *CreateNewsItem() = 0;
@@ -48,5 +49,3 @@ class NewsService : public Service
};
static ServiceReference<NewsService> news_service("NewsService", "news");
-
-#endif // OS_NEWS
diff --git a/include/modules/os_oper.h b/include/modules/os_oper.h
new file mode 100644
index 000000000..154b6af08
--- /dev/null
+++ b/include/modules/os_oper.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * (C) 2011-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+struct MyOper final
+ : Oper
+ , Serializable
+{
+ MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
+
+ void Serialize(Serialize::Data &data) const override
+ {
+ data.Store("name", this->name);
+ data.Store("type", this->ot->GetName());
+ }
+
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
+ {
+ Anope::string stype, sname;
+
+ data["type"] >> stype;
+ data["name"] >> sname;
+
+ OperType *ot = OperType::Find(stype);
+ if (ot == NULL)
+ return NULL;
+ NickCore *nc = NickCore::Find(sname);
+ if (nc == NULL)
+ return NULL;
+
+ MyOper *myo;
+ if (obj)
+ myo = anope_dynamic_static_cast<MyOper *>(obj);
+ else
+ myo = new MyOper(nc->display, ot);
+ nc->o = myo;
+ Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
+ return myo;
+ }
+};
diff --git a/include/modules/os_session.h b/include/modules/os_session.h
index 0bdec8a2b..0f25f669e 100644
--- a/include/modules/os_session.h
+++ b/include/modules/os_session.h
@@ -6,19 +6,19 @@
* Please read COPYING and README for further details.
*/
-#ifndef OS_SESSION_H
-#define OS_SESSION_H
+#pragma once
-struct Session
+struct Session final
{
cidr addr; /* A cidr (sockaddrs + len) representing this session */
- unsigned count; /* Number of clients with this host */
- unsigned hits; /* Number of subsequent kills for a host */
+ unsigned count = 1; /* Number of clients with this host */
+ unsigned hits = 0; /* Number of subsequent kills for a host */
- Session(const sockaddrs &ip, int len) : addr(ip, len), count(1), hits(0) { }
+ Session(const sockaddrs &ip, int len) : addr(ip, len) { }
};
-struct Exception : Serializable
+struct Exception final
+ : Serializable
{
Anope::string mask; /* Hosts to which this exception applies */
unsigned limit; /* Session limit for exception */
@@ -28,14 +28,15 @@ struct Exception : Serializable
time_t expires; /* Time when it expires. 0 == no expiry */
Exception() : Serializable("Exception") { }
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
-class SessionService : public Service
+class SessionService
+ : public Service
{
- public:
- typedef TR1NS::unordered_map<cidr, Session *, cidr::hash> SessionMap;
+public:
+ typedef std::unordered_map<cidr, Session *, cidr::hash> SessionMap;
typedef std::vector<Exception *> ExceptionVector;
SessionService(Module *m) : Service(m, "SessionService", "session") { }
@@ -61,15 +62,15 @@ static ServiceReference<SessionService> session_service("SessionService", "sessi
void Exception::Serialize(Serialize::Data &data) const
{
- data["mask"] << this->mask;
- data["limit"] << this->limit;
- data["who"] << this->who;
- data["reason"] << this->reason;
- data["time"] << this->time;
- data["expires"] << this->expires;
+ data.Store("mask", this->mask);
+ data.Store("limit", this->limit);
+ data.Store("who", this->who);
+ data.Store("reason", this->reason);
+ data.Store("time", this->time);
+ data.Store("expires", this->expires);
}
-Serializable* Exception::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *Exception::Unserialize(Serializable *obj, Serialize::Data &data)
{
if (!session_service)
return NULL;
@@ -90,5 +91,3 @@ Serializable* Exception::Unserialize(Serializable *obj, Serialize::Data &data)
session_service->AddException(ex);
return ex;
}
-
-#endif
diff --git a/include/modules/pseudoclients/chanserv.h b/include/modules/pseudoclients/chanserv.h
index 7e32da755..5bef94340 100644
--- a/include/modules/pseudoclients/chanserv.h
+++ b/include/modules/pseudoclients/chanserv.h
@@ -6,12 +6,12 @@
* Please read COPYING and README for further details.
*/
-#ifndef CHANSERV_H
-#define CHANSERV_H
+#pragma once
-class ChanServService : public Service
+class ChanServService
+ : public Service
{
- public:
+public:
ChanServService(Module *m) : Service(m, "ChanServService", "ChanServ")
{
}
@@ -21,5 +21,3 @@ class ChanServService : public Service
*/
virtual void Hold(Channel *c) = 0;
};
-
-#endif // CHANSERV_H
diff --git a/include/modules/pseudoclients/global.h b/include/modules/pseudoclients/global.h
index 77da218ba..01149d48e 100644
--- a/include/modules/pseudoclients/global.h
+++ b/include/modules/pseudoclients/global.h
@@ -6,25 +6,70 @@
* Please read COPYING and README for further details.
*/
-#ifndef GLOBAL_H
-#define GLOBAL_H
+#pragma once
-class GlobalService : public Service
+#define GLOBAL_NO_MESSAGE _("You do not have any messages queued and did not specify a message to send.")
+#define GLOBAL_QUEUE_CONFLICT _("You can not send a single message while you have messages queued.")
+
+class GlobalService
+ : public Service
{
- public:
- GlobalService(Module *m) : Service(m, "GlobalService", "Global")
+public:
+ GlobalService(Module *m)
+ : Service(m, "GlobalService", "Global")
{
}
/** Retrieves the bot which sends global messages unless otherwise specified. */
- virtual Reference<BotInfo> GetDefaultSender() = 0;
+ virtual Reference<BotInfo> GetDefaultSender() const = 0;
- /** Send out a global message to all users
- * @param sender Our client which should send the global
- * @param source The sender of the global
- * @param message The message
+ /** Clears any queued messages for the specified account.
+ * @param nc The account to clear queued messages for.
*/
- virtual void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) = 0;
-};
+ virtual void ClearQueue(NickCore *nc) = 0;
+
+ /** Retrieves the size of the messages queue for the specified user.
+ * @param nc The account to count queued messages for.
+ */
+ inline size_t CountQueue(NickCore* nc) const
+ {
+ auto *q = GetQueue(nc);
+ return q ? q->size() : 0;
+ }
+
+ /** Retrieves the messages queue for the specified user.
+ * @param nc The account to retrieve queued messages for.
+ */
+ virtual const std::vector<Anope::string> *GetQueue(NickCore* nc) const = 0;
-#endif // GLOBAL_H
+ /** Queues a message to be sent later.
+ * @param nc The account to queue the message for.
+ * @param message The message to queue.
+ * @return The new number of messages in the queue.
+ */
+ virtual size_t Queue(NickCore *nc, const Anope::string &message) = 0;
+
+ /** Sends a single message to all users on the network.
+ * @param message The message to send.
+ * @param source If non-nullptr then the source of the message.
+ * @param sender If non-nullptr then the bot to send the message from.
+ * @param server If non-nullptr then the server to send messages to.
+ * @return If the message was sent then true; otherwise, false.
+ */
+ virtual bool SendSingle(const Anope::string &message, CommandSource *source = nullptr, BotInfo *sender = nullptr, Server *server = nullptr) = 0;
+
+ /** Sends a message queue to all users on the network.
+ * @param source The source of the message.
+ * @param sender If non-nullptr then the bot to send the message from.
+ * @param server If non-nullptr then the server to send messages to.
+ * @return If the message queue was sent then true; otherwise, false.
+ */
+ virtual bool SendQueue(CommandSource &source, BotInfo *sender = nullptr, Server *server = nullptr) = 0;
+
+ /** Unqueues a message from the message queue.
+ * @param nc The account to unqueue the message from.
+ * @param idx The index of the item to remove.
+ * @return Whether the message was removed from the queue.
+ */
+ virtual bool Unqueue(NickCore *nc, size_t idx) = 0;
+};
diff --git a/include/modules/pseudoclients/memoserv.h b/include/modules/pseudoclients/memoserv.h
index bca26df43..c1ff4af7d 100644
--- a/include/modules/pseudoclients/memoserv.h
+++ b/include/modules/pseudoclients/memoserv.h
@@ -6,12 +6,12 @@
* Please read COPYING and README for further details.
*/
-#ifndef MEMOSERV_H
-#define MEMOSERV_H
+#pragma once
-class MemoServService : public Service
+class MemoServService
+ : public Service
{
- public:
+public:
enum MemoResult
{
MEMO_SUCCESS,
@@ -37,5 +37,3 @@ class MemoServService : public Service
*/
virtual void Check(User *u) = 0;
};
-
-#endif // MEMOSERV_H
diff --git a/include/modules/pseudoclients/nickserv.h b/include/modules/pseudoclients/nickserv.h
index 14502e7a8..2c659501e 100644
--- a/include/modules/pseudoclients/nickserv.h
+++ b/include/modules/pseudoclients/nickserv.h
@@ -6,12 +6,12 @@
* Please read COPYING and README for further details.
*/
-#ifndef NICKSERV_H
-#define NICKSERV_H
+#pragma once
-class NickServService : public Service
+class NickServService
+ : public Service
{
- public:
+public:
NickServService(Module *m) : Service(m, "NickServService", "NickServ")
{
}
@@ -19,6 +19,5 @@ class NickServService : public Service
virtual void Validate(User *u) = 0;
virtual void Collide(User *u, NickAlias *na) = 0;
virtual void Release(NickAlias *na) = 0;
+ virtual bool IsGuestNick(const Anope::string &nick) const = 0;
};
-
-#endif // NICKSERV_H
diff --git a/include/modules/redis.h b/include/modules/redis.h
index 346738492..6683997e0 100644
--- a/include/modules/redis.h
+++ b/include/modules/redis.h
@@ -6,9 +6,11 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
namespace Redis
{
- struct Reply
+ struct Reply final
{
enum Type
{
@@ -30,8 +32,8 @@ namespace Redis
i = 0;
bulk.clear();
multi_bulk_size = 0;
- for (unsigned j = 0; j < multi_bulk.size(); ++j)
- delete multi_bulk[j];
+ for (const auto *reply : multi_bulk)
+ delete reply;
multi_bulk.clear();
}
@@ -43,19 +45,20 @@ namespace Redis
class Interface
{
- public:
+ public:
Module *owner;
Interface(Module *m) : owner(m) { }
- virtual ~Interface() { }
+ virtual ~Interface() = default;
virtual void OnResult(const Reply &r) = 0;
virtual void OnError(const Anope::string &error) { Log(owner) << error; }
};
- class Provider : public Service
+ class Provider
+ : public Service
{
- public:
+ public:
Provider(Module *c, const Anope::string &n) : Service(c, "Redis::Provider", n) { }
virtual bool IsSocketDead() = 0;
diff --git a/include/modules/rpc.h b/include/modules/rpc.h
new file mode 100644
index 000000000..76ecf3542
--- /dev/null
+++ b/include/modules/rpc.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * (C) 2010-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+#include "httpd.h"
+
+class RPCRequest final
+{
+private:
+ std::optional<std::pair<int64_t, Anope::string>> error;
+ std::map<Anope::string, Anope::string> replies;
+
+public:
+ Anope::string name;
+ Anope::string id;
+ std::deque<Anope::string> data;
+ HTTPReply &reply;
+
+ RPCRequest(HTTPReply &r)
+ : reply(r)
+ {
+ }
+
+ inline void Error(uint64_t errcode, const Anope::string &errstr)
+ {
+ this->error.emplace(errcode, errstr);
+ }
+
+ inline void Reply(const Anope::string &dname, const Anope::string &ddata)
+ {
+ this->replies.emplace(dname, ddata);
+ }
+
+ inline const auto &GetError() { return this->error; }
+
+ inline const auto &GetReplies() { return this->replies; }
+};
+
+class RPCServiceInterface;
+
+class RPCEvent
+{
+public:
+ virtual ~RPCEvent() = default;
+ virtual bool Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) = 0;
+};
+
+class RPCServiceInterface
+ : public Service
+{
+public:
+ RPCServiceInterface(Module *creator, const Anope::string &sname) : Service(creator, "RPCServiceInterface", sname) { }
+
+ virtual void Register(RPCEvent *event) = 0;
+
+ virtual void Unregister(RPCEvent *event) = 0;
+
+ virtual void Reply(RPCRequest &request) = 0;
+};
diff --git a/include/modules/sasl.h b/include/modules/sasl.h
index bbd0f2f3d..e5786b524 100644
--- a/include/modules/sasl.h
+++ b/include/modules/sasl.h
@@ -6,30 +6,32 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
namespace SASL
{
- struct Message
+ struct Message final
{
Anope::string source;
Anope::string target;
Anope::string type;
- Anope::string data;
- Anope::string ext;
+ std::vector<Anope::string> data;
};
class Mechanism;
struct Session;
- class Service : public ::Service
+ class Service
+ : public ::Service
{
- public:
+ public:
Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { }
virtual void ProcessMessage(const Message &) = 0;
virtual Anope::string GetAgent() = 0;
- virtual Session* GetSession(const Anope::string &uid) = 0;
+ virtual Session *GetSession(const Anope::string &uid) = 0;
virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0;
@@ -58,14 +60,15 @@ namespace SASL
};
/* PLAIN, EXTERNAL, etc */
- class Mechanism : public ::Service
+ class Mechanism
+ : public ::Service
{
- public:
+ public:
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
- virtual Session* CreateSession(const Anope::string &uid) { return new Session(this, uid); }
+ virtual Session *CreateSession(const Anope::string &uid) { return new Session(this, uid); }
- virtual void ProcessMessage(Session *session, const Message &) = 0;
+ virtual bool ProcessMessage(Session *session, const Message &) = 0;
virtual ~Mechanism()
{
@@ -74,15 +77,16 @@ namespace SASL
}
};
- class IdentifyRequest : public ::IdentifyRequest
+ class IdentifyRequest
+ : public ::IdentifyRequest
{
Anope::string uid;
Anope::string hostname, ip;
- public:
+ public:
IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass, const Anope::string &h, const Anope::string &i) : ::IdentifyRequest(m, acc, pass), uid(id), hostname(h), ip(i) { }
- void OnSuccess() anope_override
+ void OnSuccess() override
{
if (!sasl)
return;
@@ -108,7 +112,7 @@ namespace SASL
}
}
- void OnFail() anope_override
+ void OnFail() override
{
if (!sasl)
return;
diff --git a/include/modules/set_misc.h b/include/modules/set_misc.h
index 38fa08818..2b93543c6 100644
--- a/include/modules/set_misc.h
+++ b/include/modules/set_misc.h
@@ -6,12 +6,15 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
struct MiscData
{
Anope::string object;
Anope::string name;
Anope::string data;
- MiscData() { }
- virtual ~MiscData() { }
+ virtual ~MiscData() = default;
+protected:
+ MiscData() = default;
};
diff --git a/include/modules/sql.h b/include/modules/sql.h
index 9c5e4fc4b..81af2e597 100644
--- a/include/modules/sql.h
+++ b/include/modules/sql.h
@@ -6,22 +6,27 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
+#include <stdexcept>
+
namespace SQL
{
- class Data : public Serialize::Data
+ class Data final
+ : public Serialize::Data
{
- public:
+ public:
typedef std::map<Anope::string, std::stringstream *> Map;
Map data;
- std::map<Anope::string, Type> types;
+ std::map<Anope::string, Serialize::DataType> types;
~Data()
{
Clear();
}
- std::iostream& operator[](const Anope::string &key) anope_override
+ std::iostream &operator[](const Anope::string &key) override
{
std::stringstream *&ss = data[key];
if (!ss)
@@ -29,72 +34,66 @@ namespace SQL
return *ss;
}
- std::set<Anope::string> KeySet() const anope_override
- {
- std::set<Anope::string> keys;
- for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- keys.insert(it->first);
- return keys;
- }
-
- size_t Hash() const anope_override
+ size_t Hash() const override
{
size_t hash = 0;
- for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- if (!it->second->str().empty())
- hash ^= Anope::hash_cs()(it->second->str());
+ for (const auto &[_, value] : this->data)
+ {
+ if (!value->str().empty())
+ hash ^= Anope::hash_cs()(value->str());
+ }
return hash;
}
std::map<Anope::string, std::iostream *> GetData() const
{
std::map<Anope::string, std::iostream *> d;
- for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- d[it->first] = it->second;
+ for (const auto &[key, value] : this->data)
+ d[key] = value;
return d;
}
void Clear()
{
- for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- delete it->second;
+ for (const auto &[_, value] : this->data)
+ delete value;
this->data.clear();
}
- void SetType(const Anope::string &key, Type t) anope_override
+ void SetType(const Anope::string &key, Serialize::DataType dt) override
{
- this->types[key] = t;
+ this->types[key] = dt;
}
- Type GetType(const Anope::string &key) const anope_override
+ Serialize::DataType GetType(const Anope::string &key) const override
{
- std::map<Anope::string, Type>::const_iterator it = this->types.find(key);
+ auto it = this->types.find(key);
if (it != this->types.end())
return it->second;
- return DT_TEXT;
+ return Serialize::DataType::TEXT;
}
};
/** A SQL exception, can be thrown at various points
*/
- class Exception : public ModuleException
+ class DllExport Exception : public ModuleException
{
- public:
+ public:
Exception(const Anope::string &reason) : ModuleException(reason) { }
- virtual ~Exception() throw() { }
+ virtual ~Exception() noexcept = default;
};
/** A SQL query
*/
- struct QueryData
+ struct QueryData final
{
Anope::string data;
bool escape;
};
- struct Query
+ struct Query final
{
Anope::string query;
std::map<Anope::string, QueryData> parameters;
@@ -102,7 +101,7 @@ namespace SQL
Query() { }
Query(const Anope::string &q) : query(q) { }
- Query& operator=(const Anope::string &q)
+ Query &operator=(const Anope::string &q)
{
this->query = q;
this->parameters.clear();
@@ -119,15 +118,14 @@ namespace SQL
return !(*this == other);
}
- template<typename T> void SetValue(const Anope::string &key, const T& value, bool escape = true)
+ template<typename T> void SetValue(const Anope::string &key, const T &value, bool escape = true)
{
- try
- {
- Anope::string string_value = stringify(value);
- this->parameters[key].data = string_value;
- this->parameters[key].escape = escape;
- }
- catch (const ConvertException &ex) { }
+ auto str = Anope::TryString(value);
+ if (!str.has_value())
+ return;
+
+ this->parameters[key].data = str.value();
+ this->parameters[key].escape = escape;
}
};
@@ -135,16 +133,16 @@ namespace SQL
*/
class Result
{
- protected:
+ protected:
/* Rows, column, item */
std::vector<std::map<Anope::string, Anope::string> > entries;
Query query;
Anope::string error;
- public:
- unsigned int id;
+ public:
+ unsigned int id = 0;
Anope::string finished_query;
- Result() : id(0) { }
+ Result() = default;
Result(unsigned int i, const Query &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
inline operator bool() const { return this->error.empty(); }
@@ -183,11 +181,11 @@ namespace SQL
*/
class Interface
{
- public:
+ public:
Module *owner;
Interface(Module *m) : owner(m) { }
- virtual ~Interface() { }
+ virtual ~Interface() = default;
virtual void OnResult(const Result &r) = 0;
virtual void OnError(const Result &r) = 0;
@@ -195,9 +193,10 @@ namespace SQL
/** Class providing the SQL service, modules call this to execute queries
*/
- class Provider : public Service
+ class Provider
+ : public Service
{
- public:
+ public:
Provider(Module *c, const Anope::string &n) : Service(c, "SQL::Provider", n) { }
virtual void Run(Interface *i, const Query &query) = 0;
diff --git a/include/modules/ssl.h b/include/modules/ssl.h
index 744cd46dd..a6dda0c52 100644
--- a/include/modules/ssl.h
+++ b/include/modules/ssl.h
@@ -6,9 +6,12 @@
* Please read COPYING and README for further details.
*/
-class SSLService : public Service
+#pragma once
+
+class SSLService
+ : public Service
{
- public:
+public:
SSLService(Module *o, const Anope::string &n) : Service(o, "SSLService", n) { }
virtual void Init(Socket *s) = 0;
diff --git a/include/modules/suspend.h b/include/modules/suspend.h
index 92523f7cf..f973baea4 100644
--- a/include/modules/suspend.h
+++ b/include/modules/suspend.h
@@ -9,11 +9,13 @@
* Based on the original code of Services by Andy Church.
*/
+#pragma once
+
struct SuspendInfo
{
Anope::string what, by, reason;
time_t when, expires;
- SuspendInfo() { }
- virtual ~SuspendInfo() { }
+ SuspendInfo() = default;
+ virtual ~SuspendInfo() = default;
};
diff --git a/include/modules/xmlrpc.h b/include/modules/xmlrpc.h
deleted file mode 100644
index 01847d3f0..000000000
--- a/include/modules/xmlrpc.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *
- * (C) 2010-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "httpd.h"
-
-class XMLRPCRequest
-{
- std::map<Anope::string, Anope::string> replies;
-
- public:
- Anope::string name;
- Anope::string id;
- std::deque<Anope::string> data;
- HTTPReply& r;
-
- XMLRPCRequest(HTTPReply &_r) : r(_r) { }
- inline void reply(const Anope::string &dname, const Anope::string &ddata) { this->replies.insert(std::make_pair(dname, ddata)); }
- inline const std::map<Anope::string, Anope::string> &get_replies() { return this->replies; }
-};
-
-class XMLRPCServiceInterface;
-
-class XMLRPCEvent
-{
- public:
- virtual ~XMLRPCEvent() { }
- virtual bool Run(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) = 0;
-};
-
-class XMLRPCServiceInterface : public Service
-{
- public:
- XMLRPCServiceInterface(Module *creator, const Anope::string &sname) : Service(creator, "XMLRPCServiceInterface", sname) { }
-
- virtual void Register(XMLRPCEvent *event) = 0;
-
- virtual void Unregister(XMLRPCEvent *event) = 0;
-
- virtual Anope::string Sanitize(const Anope::string &string) = 0;
-
- virtual void Reply(XMLRPCRequest &request) = 0;
-};
diff --git a/include/numeric.h b/include/numeric.h
new file mode 100644
index 000000000..2ee295278
--- /dev/null
+++ b/include/numeric.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * (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.
+ */
+
+#pragma once
+
+enum
+{
+ RPL_STATSLINKINFO = 211,
+ RPL_ENDOFSTATS = 219,
+ RPL_STATSUPTIME = 242,
+ RPL_STATSOLINE = 243,
+ RPL_STATSCONN = 250,
+ RPL_WHOISREGNICK = 307,
+ RPL_WHOISUSER = 311,
+ RPL_WHOISSERVER = 312,
+ RPL_WHOISOPERATOR = 313,
+ RPL_WHOISIDLE = 317,
+ RPL_ENDOFWHOIS = 318,
+ RPL_VERSION = 351,
+ RPL_MOTD = 372,
+ RPL_MOTDSTART = 375,
+ RPL_ENDOFMOTD = 376,
+ RPL_YOUREOPER = 381,
+ RPL_TIME = 391,
+ ERR_NOSUCHNICK = 401,
+ ERR_NOMOTD = 422,
+};
diff --git a/include/opertype.h b/include/opertype.h
index 9f04ebcce..16b52a34a 100644
--- a/include/opertype.h
+++ b/include/opertype.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef OPERTYPE_H
-#define OPERTYPE_H
+#pragma once
#include "services.h"
#include "account.h"
@@ -22,9 +21,9 @@ struct CoreExport Oper
/* The type of operator this operator is */
OperType *ot;
/* Whether the user must be an IRC operator (umode +o) to be considered a services operator */
- bool require_oper;
+ bool require_oper = true;
Anope::string password;
- Anope::string certfp;
+ std::vector<Anope::string> certfp;
/* Hosts allowed to use this operator block */
std::vector<Anope::string> hosts;
Anope::string vhost;
@@ -41,9 +40,9 @@ struct CoreExport Oper
static Oper *Find(const Anope::string &name);
};
-class CoreExport OperType
+class CoreExport OperType final
{
- private:
+private:
/** The name of this opertype, e.g. "sra".
*/
Anope::string name;
@@ -66,7 +65,7 @@ class CoreExport OperType
/** Set of opertypes we inherit from
*/
std::set<OperType *> inheritances;
- public:
+public:
/** Modes to set when someone identifies using this opertype
*/
Anope::string modes;
@@ -116,12 +115,10 @@ class CoreExport OperType
/** Gets the icommands for this opertype
* @return A list of commands
*/
- const std::list<Anope::string> GetCommands() const;
+ std::list<Anope::string> GetCommands() const;
/** Gets the privileges for this opertype
* @return A list of privileges
*/
- const std::list<Anope::string> GetPrivs() const;
+ std::list<Anope::string> GetPrivs() const;
};
-
-#endif // OPERTYPE_H
diff --git a/include/protocol.h b/include/protocol.h
index 029c67446..c92939be6 100644
--- a/include/protocol.h
+++ b/include/protocol.h
@@ -9,75 +9,141 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef PROTOCOL_H
-#define PROTOCOL_H
+#pragma once
#include "services.h"
#include "anope.h"
#include "service.h"
#include "modes.h"
+/** Thrown when a protocol error happens. */
+class CoreExport ProtocolException final
+ : public ModuleException
+{
+public:
+ ProtocolException(const Anope::string &message)
+ : ModuleException(message)
+ {
+ }
+};
+
/* Encapsulates the IRCd protocol we are speaking. */
-class CoreExport IRCDProto : public Service
+class CoreExport IRCDProto
+ : public Service
{
Anope::string proto_name;
- protected:
+protected:
IRCDProto(Module *creator, const Anope::string &proto_name);
- public:
+public:
+ /** Retrieves the protocol name. */
+ const Anope::string &GetProtocolName() const { return proto_name; }
+
virtual ~IRCDProto();
- virtual void SendSVSKillInternal(const MessageSource &, User *, const Anope::string &);
- virtual void SendModeInternal(const MessageSource &, const Channel *, const Anope::string &);
- virtual void SendModeInternal(const MessageSource &, User *, const Anope::string &);
- virtual void SendKickInternal(const MessageSource &, const Channel *, User *, const Anope::string &);
- virtual void SendNoticeInternal(const MessageSource &, const Anope::string &dest, const Anope::string &msg);
- virtual void SendPrivmsgInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf);
- virtual void SendQuitInternal(User *, const Anope::string &buf);
- virtual void SendPartInternal(User *, const Channel *chan, const Anope::string &buf);
- virtual void SendGlobopsInternal(const MessageSource &, const Anope::string &buf);
- virtual void SendCTCPInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf);
- virtual void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf);
-
- const Anope::string &GetProtocolName();
- virtual bool Parse(const Anope::string &, Anope::map<Anope::string> &, Anope::string &, Anope::string &, std::vector<Anope::string> &);
- virtual Anope::string Format(const Anope::string &source, const Anope::string &message);
+ virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
+ virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
+ virtual void SendTagmsg(const MessageSource &source, const Anope::string &dest, const Anope::map<Anope::string> &tags);
+
+ /** Parses an incoming message from the IRC server.
+ * @param message The message to parse.
+ * @param tags The location to store tags.
+ * @param source The location to store the source.
+ * @param command The location to store the command name.
+ * @param params The location to store the parameters.
+ * @return If the message was well formed then true; otherwise, false.
+ */
+ virtual bool Parse(const Anope::string &message, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> &params);
+
+ /* Formats an outgoing message so it can be sent to the IRC server.
+ * @param message The location to store the formatted message.
+ * @param tags IRCv3 message tags.
+ * @param source Source of the message.
+ * @param command Command name.
+ * @param params Any extra parameters.
+ * @return If the message was formatted then true; otherwise, false.
+ */
+ virtual bool Format(Anope::string &message, const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params);
/* Modes used by default by our clients */
- Anope::string DefaultPseudoclientModes;
+ Anope::string DefaultPseudoclientModes = "+io";
+
/* Can we force change a users's nick? */
- bool CanSVSNick;
+ bool CanSVSNick = false;
+
/* Can we force join or part users? */
- bool CanSVSJoin;
- /* Can we set vhosts/vidents on users? */
- bool CanSetVHost, CanSetVIdent;
+ bool CanSVSJoin = false;
+
+ /** Can we force servers to remove opers? */
+ bool CanSVSNOOP = false;
+
+ /* Can we set vhosts on users? */
+ bool CanSetVHost = false;
+
+ /* Can we set vidents on users? */
+ bool CanSetVIdent = false;
+
/* Can we ban specific gecos from being used? */
- bool CanSNLine;
+ bool CanSNLine = false;
+
/* Can we ban specific nicknames from being used? */
- bool CanSQLine;
+ bool CanSQLine = false;
+
/* Can we ban specific channel names from being used? */
- bool CanSQLineChannel;
+ bool CanSQLineChannel = false;
+
/* Can we ban by IP? */
- bool CanSZLine;
+ bool CanSZLine = false;
+
/* Can we place temporary holds on specific nicknames? */
- bool CanSVSHold;
- /* See os_oline */
- bool CanSVSO;
+ bool CanSVSHold = false;
+
/* See ns_cert */
- bool CanCertFP;
+ bool CanCertFP = false;
+
/* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */
- bool RequiresID;
+ bool RequiresID = false;
+
/* If this IRCd has unique ids, whether the IDs and nicknames are ambiguous */
- bool AmbiguousID;
- /* The maximum number of modes we are allowed to set with one MODE command */
- unsigned MaxModes;
+ bool AmbiguousID = false;
+
+ /** Can we ask the server to unban a user? */
+ bool CanClearBans = false;
+
+ /** Can we send tag messages? */
+ bool CanTagMessage = false;
+
+ /* The maximum length of a channel name. */
+ size_t MaxChannel = 0;
+
+ /* The maximum length of a hostname. */
+ size_t MaxHost = 0;
+
/* The maximum number of bytes a line may have */
- unsigned MaxLine;
+ size_t MaxLine = 512;
+
+ /* The maximum number of modes we are allowed to set with one MODE command */
+ size_t MaxModes = 3;
+
+ /* The maximum length of a nickname. */
+ size_t MaxNick = 0;
+
+ /* 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();
+ /** Extracts a timestamp from a string. */
+ virtual time_t ExtractTimestamp(const Anope::string &str);
+
+ /** Sends an error to the uplink before disconnecting.
+ * @param reason The error message.
+ */
+ virtual void SendError(const Anope::string &reason);
+
/** Sets the server in NOOP mode. If NOOP mode is enabled, no users
* will be able to oper on the server.
* @param s The server
@@ -96,8 +162,8 @@ class CoreExport IRCDProto : public Service
* @param vident The ident to set
* @param vhost The vhost to set
*/
- virtual void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) { }
- virtual void SendVhostDel(User *) { }
+ virtual void SendVHost(User *u, const Anope::string &vident, const Anope::string &vhost) { }
+ virtual void SendVHostDel(User *) { }
/** Sets an akill. This is a recursive function that can be called multiple times
* for the same xline, but for different users, if the xline is not one that can be
@@ -125,29 +191,38 @@ class CoreExport IRCDProto : public Service
/** Kills a user
* @param source Who is doing the kill
* @param user The user to be killed
- * @param fmt Kill reason
+ * @param msg Kill reason
*/
- virtual void SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...);
-
- virtual void SendMode(const MessageSource &source, const Channel *dest, const char *fmt, ...);
- virtual void SendMode(const MessageSource &source, User *u, const char *fmt, ...);
+ virtual void SendSVSKill(const MessageSource &source, User *user, const Anope::string &msg);
+
+ 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 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
*/
virtual void SendClientIntroduction(User *u) = 0;
- virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt, ...);
-
- virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
- virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
- virtual void SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
- virtual void SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
+ virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const Anope::string &msg);
virtual void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) = 0;
virtual void SendGlobalPrivmsg(BotInfo *bi, const Server *desc, const Anope::string &msg) = 0;
- virtual void SendQuit(User *u, const char *fmt, ...);
+ virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
+ virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
+
+ virtual void SendQuit(User *u, const Anope::string &msg);
virtual void SendPing(const Anope::string &servname, const Anope::string &who);
virtual void SendPong(const Anope::string &servname, const Anope::string &who);
@@ -159,15 +234,15 @@ class CoreExport IRCDProto : public Service
* stacker to be set "soon".
*/
virtual void SendJoin(User *u, Channel *c, const ChannelStatus *status) = 0;
- virtual void SendPart(User *u, const Channel *chan, const char *fmt, ...);
+ virtual void SendPart(User *u, const Channel *chan, const Anope::string &msg);
/** Force joins a user that isn't ours to a channel.
* @param bi The source of the message
* @param u The user to join
* @param chan The channel to join the user to
- * @param param Channel key?
+ * @param key Channel key
*/
- virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) { }
+ virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &key) { }
/** Force parts a user that isn't ours from a channel.
* @param source The source of the message
@@ -178,11 +253,7 @@ class CoreExport IRCDProto : public Service
virtual void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) { }
virtual void SendInvite(const MessageSource &source, const Channel *c, User *u);
- virtual void SendGlobops(const MessageSource &source, const char *fmt, ...);
-
- /** Sets oper flags on a user, currently only supported by Unreal
- */
- virtual void SendSVSO(BotInfo *, const Anope::string &, const Anope::string &) { }
+ virtual void SendGlobops(const MessageSource &source, const Anope::string &msg);
/** Sends a nick change of one of our clients.
*/
@@ -213,7 +284,12 @@ class CoreExport IRCDProto : public Service
virtual void SendServer(const Server *) = 0;
virtual void SendSquit(Server *, const Anope::string &message);
- virtual void SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...);
+ virtual void SendNumericInternal(int numeric, const Anope::string &dest, const std::vector<Anope::string> &params);
+ template <typename... Args>
+ void SendNumeric(int numeric, const Anope::string &dest, Args &&...args)
+ {
+ SendNumericInternal(numeric, dest, { Anope::ToString(args)... });
+ }
virtual void SendLogin(User *u, NickAlias *na) = 0;
virtual void SendLogout(User *u) = 0;
@@ -221,40 +297,43 @@ class CoreExport IRCDProto : public Service
/** Send a channel creation message to the uplink.
* On most TS6 IRCds this is a SJOIN with no nick
*/
- virtual void SendChannel(Channel *c) { }
+ virtual void SendChannel(Channel *c) = 0;
/** Make the user an IRC operator
* Normally this is a simple +o, though some IRCds require us to send the oper type
*/
virtual void SendOper(User *u);
+ virtual void SendClearBans(const MessageSource &user, Channel *c, User* u) { }
+
virtual void SendSASLMechanisms(std::vector<Anope::string> &) { }
virtual void SendSASLMessage(const SASL::Message &) { }
- virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) { }
+ virtual void SendSVSLogin(const Anope::string &uid, NickAlias *na) { }
virtual bool IsNickValid(const Anope::string &);
virtual bool IsChannelValid(const Anope::string &);
virtual bool IsIdentValid(const Anope::string &);
virtual bool IsHostValid(const Anope::string &);
virtual bool IsExtbanValid(const Anope::string &) { return false; }
+ virtual bool IsTagValid(const Anope::string &, const Anope::string &) { return false; }
/** Retrieve the maximum number of list modes settable on this channel
* Defaults to Config->ListSize
*/
- virtual unsigned GetMaxListFor(Channel *c);
- virtual unsigned GetMaxListFor(Channel *c, ChannelMode *cm);
+ virtual size_t GetMaxListFor(Channel *c, ChannelMode *cm);
virtual Anope::string NormalizeMask(const Anope::string &mask);
+
};
-class CoreExport MessageSource
+class CoreExport MessageSource final
{
Anope::string source;
- User *u;
- Server *s;
+ User *u = nullptr;
+ Server *s = nullptr;
- public:
- MessageSource(const Anope::string &);
+public:
+ explicit MessageSource(const Anope::string &);
MessageSource(User *u);
MessageSource(Server *s);
const Anope::string &GetName() const;
@@ -264,39 +343,70 @@ class CoreExport MessageSource
Server *GetServer() const;
};
-enum IRCDMessageFlag
-{
- IRCDMESSAGE_SOFT_LIMIT,
- IRCDMESSAGE_REQUIRE_SERVER,
- IRCDMESSAGE_REQUIRE_USER
-};
-class CoreExport IRCDMessage : public Service
+/** Base class for protocol module message handlers. */
+class CoreExport IRCDMessage
+ : public Service
{
- Anope::string name;
- unsigned param_count;
- std::set<IRCDMessageFlag> flags;
- public:
- IRCDMessage(Module *owner, const Anope::string &n, unsigned p = 0);
- unsigned GetParamCount() const;
- virtual void Run(MessageSource &, const std::vector<Anope::string> &params) = 0;
- virtual void Run(MessageSource &, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags);
-
- void SetFlag(IRCDMessageFlag f) { flags.insert(f); }
- bool HasFlag(IRCDMessageFlag f) const { return flags.count(f); }
+public:
+ /** An enumeration of potential flags a command can have. */
+ enum Flag
+ : uint8_t
+ {
+ /** The parameter count is a minimum instead of an exact limit. */
+ FLAG_SOFT_LIMIT,
+
+ /** The message must come from a server. */
+ FLAG_REQUIRE_SERVER,
+
+ /** The message must come from a user. */
+ FLAG_REQUIRE_USER,
+
+ /** The highest flag possible. */
+ FLAG_MAX,
+ };
+
+private:
+ /** The name of the message (e.g. PRIVMSG). */
+ const Anope::string name;
+
+ /** The number of parameters this command takes. */
+ const size_t param_count;
+
+ /** The flags that are set on the command. */
+ std::bitset<FLAG_MAX> flags;
+
+public:
+ IRCDMessage(Module *o, const Anope::string &n, size_t pc = 0);
+
+ /** Retrieves the parameter count. */
+ inline size_t GetParamCount() const { return param_count; }
+
+ /** Runs the handler for this message.
+ * @param source Entity that sent the message.
+ * @param params Message parameters
+ * @param tags Message tags
+ */
+ virtual void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) = 0;
+
+ /** Sets the flags for this message. */
+ inline void SetFlag(Flag flag, bool value = true) { flags.set(flag, value); }
+
+ /** Determines if a flag is set. */
+ inline bool HasFlag(Flag flag) const { return flags[flag]; }
};
/** MessageTokenizer allows tokens in the IRC wire format to be read from a string */
-class CoreExport MessageTokenizer
+class CoreExport MessageTokenizer final
{
private:
/** The message we are parsing tokens from. */
Anope::string message;
/** The current position within the message. */
- Anope::string::size_type position;
+ Anope::string::size_type position = 0;
- public:
+public:
/** Create a tokenstream and fill it with the provided data. */
MessageTokenizer(const Anope::string &msg);
@@ -314,5 +424,3 @@ private:
};
extern CoreExport IRCDProto *IRCD;
-
-#endif // PROTOCOL_H
diff --git a/include/pstdint.h b/include/pstdint.h
deleted file mode 100644
index b034ae086..000000000
--- a/include/pstdint.h
+++ /dev/null
@@ -1,800 +0,0 @@
-/* A portable stdint.h
- ****************************************************************************
- * BSD License:
- ****************************************************************************
- *
- * Copyright (c) 2005-2011 Paul Hsieh
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************
- *
- * Version 0.1.12
- *
- * The ANSI C standard committee, for the C99 standard, specified the
- * inclusion of a new standard include file called stdint.h. This is
- * a very useful and long desired include file which contains several
- * very precise definitions for integer scalar types that is
- * critically important for making portable several classes of
- * applications including cryptography, hashing, variable length
- * integer libraries and so on. But for most developers its likely
- * useful just for programming sanity.
- *
- * The problem is that most compiler vendors have decided not to
- * implement the C99 standard, and the next C++ language standard
- * (which has a lot more mindshare these days) will be a long time in
- * coming and its unknown whether or not it will include stdint.h or
- * how much adoption it will have. Either way, it will be a long time
- * before all compilers come with a stdint.h and it also does nothing
- * for the extremely large number of compilers available today which
- * do not include this file, or anything comparable to it.
- *
- * So that's what this file is all about. Its an attempt to build a
- * single universal include file that works on as many platforms as
- * possible to deliver what stdint.h is supposed to. A few things
- * that should be noted about this file:
- *
- * 1) It is not guaranteed to be portable and/or present an identical
- * interface on all platforms. The extreme variability of the
- * ANSI C standard makes this an impossibility right from the
- * very get go. Its really only meant to be useful for the vast
- * majority of platforms that possess the capability of
- * implementing usefully and precisely defined, standard sized
- * integer scalars. Systems which are not intrinsically 2s
- * complement may produce invalid constants.
- *
- * 2) There is an unavoidable use of non-reserved symbols.
- *
- * 3) Other standard include files are invoked.
- *
- * 4) This file may come in conflict with future platforms that do
- * include stdint.h. The hope is that one or the other can be
- * used with no real difference.
- *
- * 5) In the current version, if your platform can't represent
- * int32_t, int16_t and int8_t, it just dumps out with a compiler
- * error.
- *
- * 6) 64 bit integers may or may not be defined. Test for their
- * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
- * Note that this is different from the C99 specification which
- * requires the existence of 64 bit support in the compiler. If
- * this is not defined for your platform, yet it is capable of
- * dealing with 64 bits then it is because this file has not yet
- * been extended to cover all of your system's capabilities.
- *
- * 7) (u)intptr_t may or may not be defined. Test for its presence
- * with the test: #ifdef PTRDIFF_MAX. If this is not defined
- * for your platform, then it is because this file has not yet
- * been extended to cover all of your system's capabilities, not
- * because its optional.
- *
- * 8) The following might not been defined even if your platform is
- * capable of defining it:
- *
- * WCHAR_MIN
- * WCHAR_MAX
- * (u)int64_t
- * PTRDIFF_MIN
- * PTRDIFF_MAX
- * (u)intptr_t
- *
- * 9) The following have not been defined:
- *
- * WINT_MIN
- * WINT_MAX
- *
- * 10) The criteria for defining (u)int_least(*)_t isn't clear,
- * except for systems which don't have a type that precisely
- * defined 8, 16, or 32 bit types (which this include file does
- * not support anyways). Default definitions have been given.
- *
- * 11) The criteria for defining (u)int_fast(*)_t isn't something I
- * would trust to any particular compiler vendor or the ANSI C
- * committee. It is well known that "compatible systems" are
- * commonly created that have very different performance
- * characteristics from the systems they are compatible with,
- * especially those whose vendors make both the compiler and the
- * system. Default definitions have been given, but its strongly
- * recommended that users never use these definitions for any
- * reason (they do *NOT* deliver any serious guarantee of
- * improved performance -- not in this file, nor any vendor's
- * stdint.h).
- *
- * 12) The following macros:
- *
- * PRINTF_INTMAX_MODIFIER
- * PRINTF_INT64_MODIFIER
- * PRINTF_INT32_MODIFIER
- * PRINTF_INT16_MODIFIER
- * PRINTF_LEAST64_MODIFIER
- * PRINTF_LEAST32_MODIFIER
- * PRINTF_LEAST16_MODIFIER
- * PRINTF_INTPTR_MODIFIER
- *
- * are strings which have been defined as the modifiers required
- * for the "d", "u" and "x" printf formats to correctly output
- * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
- * (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
- * PRINTF_INTPTR_MODIFIER is not defined for some systems which
- * provide their own stdint.h. PRINTF_INT64_MODIFIER is not
- * defined if INT64_MAX is not defined. These are an extension
- * beyond what C99 specifies must be in stdint.h.
- *
- * In addition, the following macros are defined:
- *
- * PRINTF_INTMAX_HEX_WIDTH
- * PRINTF_INT64_HEX_WIDTH
- * PRINTF_INT32_HEX_WIDTH
- * PRINTF_INT16_HEX_WIDTH
- * PRINTF_INT8_HEX_WIDTH
- * PRINTF_INTMAX_DEC_WIDTH
- * PRINTF_INT64_DEC_WIDTH
- * PRINTF_INT32_DEC_WIDTH
- * PRINTF_INT16_DEC_WIDTH
- * PRINTF_INT8_DEC_WIDTH
- *
- * Which specifies the maximum number of characters required to
- * print the number of that type in either hexadecimal or decimal.
- * These are an extension beyond what C99 specifies must be in
- * stdint.h.
- *
- * Compilers tested (all with 0 warnings at their highest respective
- * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
- * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
- * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
- *
- * This file should be considered a work in progress. Suggestions for
- * improvements, especially those which increase coverage are strongly
- * encouraged.
- *
- * Acknowledgements
- *
- * The following people have made significant contributions to the
- * development and testing of this file:
- *
- * Chris Howie
- * John Steele Scott
- * Dave Thorup
- * John Dill
- *
- */
-
-#include <stddef.h>
-#include <limits.h>
-#include <signal.h>
-
-/*
- * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
- * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
- */
-
-#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
-#include <stdint.h>
-#define _PSTDINT_H_INCLUDED
-# ifndef PRINTF_INT64_MODIFIER
-# define PRINTF_INT64_MODIFIER "ll"
-# endif
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER "l"
-# endif
-# ifndef PRINTF_INT16_MODIFIER
-# define PRINTF_INT16_MODIFIER "h"
-# endif
-# ifndef PRINTF_INTMAX_MODIFIER
-# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
-# endif
-# ifndef PRINTF_INT64_HEX_WIDTH
-# define PRINTF_INT64_HEX_WIDTH "16"
-# endif
-# ifndef PRINTF_INT32_HEX_WIDTH
-# define PRINTF_INT32_HEX_WIDTH "8"
-# endif
-# ifndef PRINTF_INT16_HEX_WIDTH
-# define PRINTF_INT16_HEX_WIDTH "4"
-# endif
-# ifndef PRINTF_INT8_HEX_WIDTH
-# define PRINTF_INT8_HEX_WIDTH "2"
-# endif
-# ifndef PRINTF_INT64_DEC_WIDTH
-# define PRINTF_INT64_DEC_WIDTH "20"
-# endif
-# ifndef PRINTF_INT32_DEC_WIDTH
-# define PRINTF_INT32_DEC_WIDTH "10"
-# endif
-# ifndef PRINTF_INT16_DEC_WIDTH
-# define PRINTF_INT16_DEC_WIDTH "5"
-# endif
-# ifndef PRINTF_INT8_DEC_WIDTH
-# define PRINTF_INT8_DEC_WIDTH "3"
-# endif
-# ifndef PRINTF_INTMAX_HEX_WIDTH
-# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
-# endif
-# ifndef PRINTF_INTMAX_DEC_WIDTH
-# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
-# endif
-
-/*
- * Something really weird is going on with Open Watcom. Just pull some of
- * these duplicated definitions from Open Watcom's stdint.h file for now.
- */
-
-# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
-# if !defined (INT64_C)
-# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
-# endif
-# if !defined (UINT64_C)
-# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
-# endif
-# if !defined (INT32_C)
-# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
-# endif
-# if !defined (UINT32_C)
-# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
-# endif
-# if !defined (INT16_C)
-# define INT16_C(x) (x)
-# endif
-# if !defined (UINT16_C)
-# define UINT16_C(x) (x)
-# endif
-# if !defined (INT8_C)
-# define INT8_C(x) (x)
-# endif
-# if !defined (UINT8_C)
-# define UINT8_C(x) (x)
-# endif
-# if !defined (UINT64_MAX)
-# define UINT64_MAX 18446744073709551615ULL
-# endif
-# if !defined (INT64_MAX)
-# define INT64_MAX 9223372036854775807LL
-# endif
-# if !defined (UINT32_MAX)
-# define UINT32_MAX 4294967295UL
-# endif
-# if !defined (INT32_MAX)
-# define INT32_MAX 2147483647L
-# endif
-# if !defined (INTMAX_MAX)
-# define INTMAX_MAX INT64_MAX
-# endif
-# if !defined (INTMAX_MIN)
-# define INTMAX_MIN INT64_MIN
-# endif
-# endif
-#endif
-
-#ifndef _PSTDINT_H_INCLUDED
-#define _PSTDINT_H_INCLUDED
-
-#ifndef SIZE_MAX
-# define SIZE_MAX (~(size_t)0)
-#endif
-
-/*
- * Deduce the type assignments from limits.h under the assumption that
- * integer sizes in bits are powers of 2, and follow the ANSI
- * definitions.
- */
-
-#ifndef UINT8_MAX
-# define UINT8_MAX 0xff
-#endif
-#ifndef uint8_t
-# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
- typedef unsigned char uint8_t;
-# define UINT8_C(v) ((uint8_t) v)
-# else
-# error "Platform not supported"
-# endif
-#endif
-
-#ifndef INT8_MAX
-# define INT8_MAX 0x7f
-#endif
-#ifndef INT8_MIN
-# define INT8_MIN INT8_C(0x80)
-#endif
-#ifndef int8_t
-# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
- typedef signed char int8_t;
-# define INT8_C(v) ((int8_t) v)
-# else
-# error "Platform not supported"
-# endif
-#endif
-
-#ifndef UINT16_MAX
-# define UINT16_MAX 0xffff
-#endif
-#ifndef uint16_t
-#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
- typedef unsigned int uint16_t;
-# ifndef PRINTF_INT16_MODIFIER
-# define PRINTF_INT16_MODIFIER ""
-# endif
-# define UINT16_C(v) ((uint16_t) (v))
-#elif (USHRT_MAX == UINT16_MAX)
- typedef unsigned short uint16_t;
-# define UINT16_C(v) ((uint16_t) (v))
-# ifndef PRINTF_INT16_MODIFIER
-# define PRINTF_INT16_MODIFIER "h"
-# endif
-#else
-#error "Platform not supported"
-#endif
-#endif
-
-#ifndef INT16_MAX
-# define INT16_MAX 0x7fff
-#endif
-#ifndef INT16_MIN
-# define INT16_MIN INT16_C(0x8000)
-#endif
-#ifndef int16_t
-#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
- typedef signed int int16_t;
-# define INT16_C(v) ((int16_t) (v))
-# ifndef PRINTF_INT16_MODIFIER
-# define PRINTF_INT16_MODIFIER ""
-# endif
-#elif (SHRT_MAX == INT16_MAX)
- typedef signed short int16_t;
-# define INT16_C(v) ((int16_t) (v))
-# ifndef PRINTF_INT16_MODIFIER
-# define PRINTF_INT16_MODIFIER "h"
-# endif
-#else
-#error "Platform not supported"
-#endif
-#endif
-
-#ifndef UINT32_MAX
-# define UINT32_MAX (0xffffffffUL)
-#endif
-#ifndef uint32_t
-#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
- typedef unsigned long uint32_t;
-# define UINT32_C(v) v ## UL
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER "l"
-# endif
-#elif (UINT_MAX == UINT32_MAX)
- typedef unsigned int uint32_t;
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER ""
-# endif
-# define UINT32_C(v) v ## U
-#elif (USHRT_MAX == UINT32_MAX)
- typedef unsigned short uint32_t;
-# define UINT32_C(v) ((unsigned short) (v))
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER ""
-# endif
-#else
-#error "Platform not supported"
-#endif
-#endif
-
-#ifndef INT32_MAX
-# define INT32_MAX (0x7fffffffL)
-#endif
-#ifndef INT32_MIN
-# define INT32_MIN INT32_C(0x80000000)
-#endif
-#ifndef int32_t
-#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
- typedef signed long int32_t;
-# define INT32_C(v) v ## L
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER "l"
-# endif
-#elif (INT_MAX == INT32_MAX)
- typedef signed int int32_t;
-# define INT32_C(v) v
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER ""
-# endif
-#elif (SHRT_MAX == INT32_MAX)
- typedef signed short int32_t;
-# define INT32_C(v) ((short) (v))
-# ifndef PRINTF_INT32_MODIFIER
-# define PRINTF_INT32_MODIFIER ""
-# endif
-#else
-#error "Platform not supported"
-#endif
-#endif
-
-/*
- * The macro stdint_int64_defined is temporarily used to record
- * whether or not 64 integer support is available. It must be
- * defined for any 64 integer extensions for new platforms that are
- * added.
- */
-
-#undef stdint_int64_defined
-#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
-# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
-# define stdint_int64_defined
- typedef long long int64_t;
- typedef unsigned long long uint64_t;
-# define UINT64_C(v) v ## ULL
-# define INT64_C(v) v ## LL
-# ifndef PRINTF_INT64_MODIFIER
-# define PRINTF_INT64_MODIFIER "ll"
-# endif
-# endif
-#endif
-
-#if !defined (stdint_int64_defined)
-# if defined(__GNUC__)
-# define stdint_int64_defined
- __extension__ typedef long long int64_t;
- __extension__ typedef unsigned long long uint64_t;
-# define UINT64_C(v) v ## ULL
-# define INT64_C(v) v ## LL
-# ifndef PRINTF_INT64_MODIFIER
-# define PRINTF_INT64_MODIFIER "ll"
-# endif
-# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
-# define stdint_int64_defined
- typedef long long int64_t;
- typedef unsigned long long uint64_t;
-# define UINT64_C(v) v ## ULL
-# define INT64_C(v) v ## LL
-# ifndef PRINTF_INT64_MODIFIER
-# define PRINTF_INT64_MODIFIER "ll"
-# endif
-# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
-# define stdint_int64_defined
- typedef __int64 int64_t;
- typedef unsigned __int64 uint64_t;
-# define UINT64_C(v) v ## UI64
-# define INT64_C(v) v ## I64
-# ifndef PRINTF_INT64_MODIFIER
-# define PRINTF_INT64_MODIFIER "I64"
-# endif
-# endif
-#endif
-
-#if !defined (LONG_LONG_MAX) && defined (INT64_C)
-# define LONG_LONG_MAX INT64_C (9223372036854775807)
-#endif
-#ifndef ULONG_LONG_MAX
-# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
-#endif
-
-#if !defined (INT64_MAX) && defined (INT64_C)
-# define INT64_MAX INT64_C (9223372036854775807)
-#endif
-#if !defined (INT64_MIN) && defined (INT64_C)
-# define INT64_MIN INT64_C (-9223372036854775808)
-#endif
-#if !defined (UINT64_MAX) && defined (INT64_C)
-# define UINT64_MAX UINT64_C (18446744073709551615)
-#endif
-
-/*
- * Width of hexadecimal for number field.
- */
-
-#ifndef PRINTF_INT64_HEX_WIDTH
-# define PRINTF_INT64_HEX_WIDTH "16"
-#endif
-#ifndef PRINTF_INT32_HEX_WIDTH
-# define PRINTF_INT32_HEX_WIDTH "8"
-#endif
-#ifndef PRINTF_INT16_HEX_WIDTH
-# define PRINTF_INT16_HEX_WIDTH "4"
-#endif
-#ifndef PRINTF_INT8_HEX_WIDTH
-# define PRINTF_INT8_HEX_WIDTH "2"
-#endif
-
-#ifndef PRINTF_INT64_DEC_WIDTH
-# define PRINTF_INT64_DEC_WIDTH "20"
-#endif
-#ifndef PRINTF_INT32_DEC_WIDTH
-# define PRINTF_INT32_DEC_WIDTH "10"
-#endif
-#ifndef PRINTF_INT16_DEC_WIDTH
-# define PRINTF_INT16_DEC_WIDTH "5"
-#endif
-#ifndef PRINTF_INT8_DEC_WIDTH
-# define PRINTF_INT8_DEC_WIDTH "3"
-#endif
-
-/*
- * Ok, lets not worry about 128 bit integers for now. Moore's law says
- * we don't need to worry about that until about 2040 at which point
- * we'll have bigger things to worry about.
- */
-
-#ifdef stdint_int64_defined
- typedef int64_t intmax_t;
- typedef uint64_t uintmax_t;
-# define INTMAX_MAX INT64_MAX
-# define INTMAX_MIN INT64_MIN
-# define UINTMAX_MAX UINT64_MAX
-# define UINTMAX_C(v) UINT64_C(v)
-# define INTMAX_C(v) INT64_C(v)
-# ifndef PRINTF_INTMAX_MODIFIER
-# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
-# endif
-# ifndef PRINTF_INTMAX_HEX_WIDTH
-# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
-# endif
-# ifndef PRINTF_INTMAX_DEC_WIDTH
-# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
-# endif
-#else
- typedef int32_t intmax_t;
- typedef uint32_t uintmax_t;
-# define INTMAX_MAX INT32_MAX
-# define UINTMAX_MAX UINT32_MAX
-# define UINTMAX_C(v) UINT32_C(v)
-# define INTMAX_C(v) INT32_C(v)
-# ifndef PRINTF_INTMAX_MODIFIER
-# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
-# endif
-# ifndef PRINTF_INTMAX_HEX_WIDTH
-# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
-# endif
-# ifndef PRINTF_INTMAX_DEC_WIDTH
-# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
-# endif
-#endif
-
-/*
- * Because this file currently only supports platforms which have
- * precise powers of 2 as bit sizes for the default integers, the
- * least definitions are all trivial. Its possible that a future
- * version of this file could have different definitions.
- */
-
-#ifndef stdint_least_defined
- typedef int8_t int_least8_t;
- typedef uint8_t uint_least8_t;
- typedef int16_t int_least16_t;
- typedef uint16_t uint_least16_t;
- typedef int32_t int_least32_t;
- typedef uint32_t uint_least32_t;
-# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
-# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
-# define UINT_LEAST8_MAX UINT8_MAX
-# define INT_LEAST8_MAX INT8_MAX
-# define UINT_LEAST16_MAX UINT16_MAX
-# define INT_LEAST16_MAX INT16_MAX
-# define UINT_LEAST32_MAX UINT32_MAX
-# define INT_LEAST32_MAX INT32_MAX
-# define INT_LEAST8_MIN INT8_MIN
-# define INT_LEAST16_MIN INT16_MIN
-# define INT_LEAST32_MIN INT32_MIN
-# ifdef stdint_int64_defined
- typedef int64_t int_least64_t;
- typedef uint64_t uint_least64_t;
-# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
-# define UINT_LEAST64_MAX UINT64_MAX
-# define INT_LEAST64_MAX INT64_MAX
-# define INT_LEAST64_MIN INT64_MIN
-# endif
-#endif
-#undef stdint_least_defined
-
-/*
- * The ANSI C committee pretending to know or specify anything about
- * performance is the epitome of misguided arrogance. The mandate of
- * this file is to *ONLY* ever support that absolute minimum
- * definition of the fast integer types, for compatibility purposes.
- * No extensions, and no attempt to suggest what may or may not be a
- * faster integer type will ever be made in this file. Developers are
- * warned to stay away from these types when using this or any other
- * stdint.h.
- */
-
-typedef int_least8_t int_fast8_t;
-typedef uint_least8_t uint_fast8_t;
-typedef int_least16_t int_fast16_t;
-typedef uint_least16_t uint_fast16_t;
-typedef int_least32_t int_fast32_t;
-typedef uint_least32_t uint_fast32_t;
-#define UINT_FAST8_MAX UINT_LEAST8_MAX
-#define INT_FAST8_MAX INT_LEAST8_MAX
-#define UINT_FAST16_MAX UINT_LEAST16_MAX
-#define INT_FAST16_MAX INT_LEAST16_MAX
-#define UINT_FAST32_MAX UINT_LEAST32_MAX
-#define INT_FAST32_MAX INT_LEAST32_MAX
-#define INT_FAST8_MIN INT_LEAST8_MIN
-#define INT_FAST16_MIN INT_LEAST16_MIN
-#define INT_FAST32_MIN INT_LEAST32_MIN
-#ifdef stdint_int64_defined
- typedef int_least64_t int_fast64_t;
- typedef uint_least64_t uint_fast64_t;
-# define UINT_FAST64_MAX UINT_LEAST64_MAX
-# define INT_FAST64_MAX INT_LEAST64_MAX
-# define INT_FAST64_MIN INT_LEAST64_MIN
-#endif
-
-#undef stdint_int64_defined
-
-/*
- * Whatever piecemeal, per compiler thing we can do about the wchar_t
- * type limits.
- */
-
-#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
-# include <wchar.h>
-# ifndef WCHAR_MIN
-# define WCHAR_MIN 0
-# endif
-# ifndef WCHAR_MAX
-# define WCHAR_MAX ((wchar_t)-1)
-# endif
-#endif
-
-/*
- * Whatever piecemeal, per compiler/platform thing we can do about the
- * (u)intptr_t types and limits.
- */
-
-#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
-# define STDINT_H_UINTPTR_T_DEFINED
-#endif
-
-#ifndef STDINT_H_UINTPTR_T_DEFINED
-# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
-# define stdint_intptr_bits 64
-# elif defined (__WATCOMC__) || defined (__TURBOC__)
-# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
-# define stdint_intptr_bits 16
-# else
-# define stdint_intptr_bits 32
-# endif
-# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
-# define stdint_intptr_bits 32
-# elif defined (__INTEL_COMPILER)
-/* TODO -- what did Intel do about x86-64? */
-# endif
-
-# ifdef stdint_intptr_bits
-# define stdint_intptr_glue3_i(a,b,c) a##b##c
-# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
-# ifndef PRINTF_INTPTR_MODIFIER
-# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
-# endif
-# ifndef PTRDIFF_MAX
-# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
-# endif
-# ifndef PTRDIFF_MIN
-# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
-# endif
-# ifndef UINTPTR_MAX
-# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
-# endif
-# ifndef INTPTR_MAX
-# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
-# endif
-# ifndef INTPTR_MIN
-# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
-# endif
-# ifndef INTPTR_C
-# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
-# endif
-# ifndef UINTPTR_C
-# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
-# endif
- typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
- typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
-# else
-/* TODO -- This following is likely wrong for some platforms, and does
- nothing for the definition of uintptr_t. */
- typedef ptrdiff_t intptr_t;
-# endif
-# define STDINT_H_UINTPTR_T_DEFINED
-#endif
-
-/*
- * Assumes sig_atomic_t is signed and we have a 2s complement machine.
- */
-
-#ifndef SIG_ATOMIC_MAX
-# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
-#endif
-
-#endif
-
-#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
-
-/*
- * Please compile with the maximum warning settings to make sure macros are not
- * defined more than once.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define glue3_aux(x,y,z) x ## y ## z
-#define glue3(x,y,z) glue3_aux(x,y,z)
-
-#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
-#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
-
-#define DECL(us,bits) glue3(DECL,us,) (bits)
-
-#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
-
-int main () {
- DECL(I,8)
- DECL(U,8)
- DECL(I,16)
- DECL(U,16)
- DECL(I,32)
- DECL(U,32)
-#ifdef INT64_MAX
- DECL(I,64)
- DECL(U,64)
-#endif
- intmax_t imax = INTMAX_C(0);
- uintmax_t umax = UINTMAX_C(0);
- char str0[256], str1[256];
-
- sprintf (str0, "%d %x\n", 0, ~0);
-
- sprintf (str1, "%d %x\n", i8, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
- sprintf (str1, "%u %x\n", u8, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
- sprintf (str1, "%d %x\n", i16, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
- sprintf (str1, "%u %x\n", u16, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
- sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
- sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
-#ifdef INT64_MAX
- sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
-#endif
- sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
- sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
- if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
-
- TESTUMAX(8);
- TESTUMAX(16);
- TESTUMAX(32);
-#ifdef INT64_MAX
- TESTUMAX(64);
-#endif
-
- return EXIT_SUCCESS;
-}
-
-#endif
diff --git a/include/regchannel.h b/include/regchannel.h
index 0e1ca0bce..9a7bf9880 100644
--- a/include/regchannel.h
+++ b/include/regchannel.h
@@ -6,8 +6,7 @@
* Please read COPYING and README for further details.
*/
-#ifndef REGCHANNEL_H
-#define REGCHANNEL_H
+#pragma once
#include "memo.h"
#include "modes.h"
@@ -17,14 +16,15 @@
#include "serialize.h"
#include "bots.h"
-typedef Anope::hash_map<ChannelInfo *> registered_channel_map;
+typedef Anope::unordered_map<ChannelInfo *> registered_channel_map;
extern CoreExport Serialize::Checker<registered_channel_map> RegisteredChannelList;
/* AutoKick data. */
-class CoreExport AutoKick : public Serializable
+class CoreExport AutoKick final
+ : public Serializable
{
- public:
+public:
/* Channel this autokick is on */
Serialize::Reference<ChannelInfo> ci;
@@ -38,24 +38,26 @@ class CoreExport AutoKick : public Serializable
AutoKick();
~AutoKick();
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
};
/* It matters that Base is here before Extensible (it is inherited by Serializable)
*/
-class CoreExport ChannelInfo : public Serializable, public Extensible
+class CoreExport ChannelInfo final
+ : public Serializable
+ , public Extensible
{
/* channels who reference this one */
Anope::map<int> references;
- private:
+private:
Serialize::Reference<NickCore> founder; /* Channel founder */
Serialize::Reference<NickCore> successor; /* Who gets the channel if the founder nick is dropped or expires */
Serialize::Checker<std::vector<ChanAccess *> > access; /* List of authorized users */
Serialize::Checker<std::vector<AutoKick *> > akick; /* List of users to kickban */
Anope::map<int16_t> levels;
- public:
+public:
friend class ChanAccess;
friend class AutoKick;
@@ -93,9 +95,10 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
ChannelInfo(const ChannelInfo &ci);
~ChannelInfo();
+ ChannelInfo &operator=(const ChannelInfo &) = default;
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
/** Change the founder of the channel
* @params nc The new founder
@@ -166,7 +169,7 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
* @param t The time the akick was added, defaults to now
* @param lu The time the akick was last used, defaults to never
*/
- AutoKick* AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0);
+ AutoKick *AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0);
/** Add an akick entry to the channel by reason
* @param user The user who added the akick
@@ -175,13 +178,13 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
* @param t The time the akick was added, defaults to now
* @param lu The time the akick was last used, defaults to never
*/
- AutoKick* AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0);
+ AutoKick *AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0);
/** Get an entry from the channel akick list
* @param index The index in the akick vector
* @return The akick structure, or NULL if not found
*/
- AutoKick* GetAkick(unsigned index) const;
+ AutoKick *GetAkick(unsigned index) const;
/** Get the size of the akick vector for this channel
* @return The akick vector size
@@ -235,7 +238,7 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
* @param name channel name to lookup
* @return the ChannelInfo associated with the channel
*/
- static ChannelInfo* Find(const Anope::string &name);
+ static ChannelInfo *Find(const Anope::string &name);
void AddChannelReference(const Anope::string &what);
void RemoveChannelReference(const Anope::string &what);
@@ -248,5 +251,3 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
* @return true or false
*/
extern CoreExport bool IsFounder(const User *user, const ChannelInfo *ci);
-
-#endif // REGCHANNEL_H
diff --git a/include/regexpr.h b/include/regexpr.h
index fde1501c1..aecf38f5f 100644
--- a/include/regexpr.h
+++ b/include/regexpr.h
@@ -9,37 +9,36 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef REGEXPR_H
-#define REGEXPR_H
+#pragma once
#include "services.h"
#include "anope.h"
#include "service.h"
-class RegexException : public CoreException
+class CoreExport RegexException final
+ : public CoreException
{
- public:
+public:
RegexException(const Anope::string &reason = "") : CoreException(reason) { }
- virtual ~RegexException() throw() { }
+ virtual ~RegexException() noexcept = default;
};
class CoreExport Regex
{
Anope::string expression;
- protected:
+protected:
Regex(const Anope::string &expr) : expression(expr) { }
- public:
- virtual ~Regex() { }
+public:
+ virtual ~Regex() = default;
const Anope::string &GetExpression() { return expression; }
virtual bool Matches(const Anope::string &str) = 0;
};
-class CoreExport RegexProvider : public Service
+class CoreExport RegexProvider
+ : public Service
{
- public:
+public:
RegexProvider(Module *o, const Anope::string &n) : Service(o, "Regex", n) { }
virtual Regex *Compile(const Anope::string &) = 0;
};
-
-#endif // REGEXPR_H
diff --git a/include/serialize.h b/include/serialize.h
index a0842a3f0..1459a1ebd 100644
--- a/include/serialize.h
+++ b/include/serialize.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef SERIALIZE_H
-#define SERIALIZE_H
+#pragma once
#include <sstream>
@@ -19,23 +18,44 @@
namespace Serialize
{
+ enum class DataType
+ : uint8_t
+ {
+ BOOL,
+ FLOAT,
+ INT,
+ TEXT,
+ UINT,
+ };
+
class Data
{
- public:
- enum Type
- {
- DT_TEXT,
- DT_INT
- };
+ public:
+ virtual ~Data() = default;
+
+ virtual std::iostream &operator[](const Anope::string &key) = 0;
- virtual ~Data() { }
+ template <typename T>
+ void Store(const Anope::string &key, const T &value)
+ {
+ using Type = std::remove_cv_t<std::remove_reference_t<T>>;
+
+ if constexpr (std::is_same_v<Type, bool>)
+ SetType(key, DataType::BOOL);
+ else if constexpr (std::is_floating_point_v<Type>)
+ SetType(key, DataType::FLOAT);
+ else if constexpr (std::is_integral_v<Type> && std::is_signed_v<Type>)
+ SetType(key, DataType::INT);
+ else if constexpr (std::is_integral_v<Type> && std::is_unsigned_v<Type>)
+ SetType(key, DataType::UINT);
+
+ this->operator[](key) << value;
+ }
- virtual std::iostream& operator[](const Anope::string &key) = 0;
- virtual std::set<Anope::string> KeySet() const { throw CoreException("Not supported"); }
virtual size_t Hash() const { throw CoreException("Not supported"); }
- virtual void SetType(const Anope::string &key, Type t) { }
- virtual Type GetType(const Anope::string &key) const { return DT_TEXT; }
+ virtual void SetType(const Anope::string &key, DataType dt) { }
+ virtual DataType GetType(const Anope::string &key) const { return DataType::TEXT; }
};
extern void RegisterTypes();
@@ -50,9 +70,10 @@ namespace Serialize
* abstract data types (Serialize::Data), and then reconstructed or
* updated later at any time.
*/
-class CoreExport Serializable : public virtual Base
+class CoreExport Serializable
+ : public virtual Base
{
- private:
+private:
/* A list of every serializable item in Anope.
* Some of these are static and constructed at runtime,
* so this list must be on the heap, as it is not always
@@ -65,24 +86,24 @@ class CoreExport Serializable : public virtual Base
/* Iterator into serializable_items */
std::list<Serializable *>::iterator s_iter;
/* The hash of the last serialized form of this object committed to the database */
- size_t last_commit;
+ size_t last_commit = 0;
/* The last time this object was committed to the database */
- time_t last_commit_time;
+ time_t last_commit_time = 0;
- protected:
+protected:
Serializable(const Anope::string &serialize_type);
Serializable(const Serializable &);
Serializable &operator=(const Serializable &);
- public:
+public:
virtual ~Serializable();
/* Unique ID (per type, not globally) for this object */
- uint64_t id;
+ uint64_t id = 0;
/* Only used by redis, to ignore updates */
- unsigned short redis_ignore;
+ unsigned short redis_ignore = 0;
/** Marks the object as potentially being updated "soon".
*/
@@ -97,7 +118,7 @@ class CoreExport Serializable : public virtual Base
/** Get the type of serializable object this is
* @return The serializable object type
*/
- Serialize::Type* GetSerializableType() const { return this->s_type; }
+ Serialize::Type *GetSerializableType() const { return this->s_type; }
virtual void Serialize(Serialize::Data &data) const = 0;
@@ -108,9 +129,10 @@ class CoreExport Serializable : public virtual Base
* of class that inherits from Serializable. Used for unserializing objects
* of this type, as it requires a function pointer to a static member function.
*/
-class CoreExport Serialize::Type : public Base
+class CoreExport Serialize::Type final
+ : public Base
{
- typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
+ typedef Serializable *(*unserialize_func)(Serializable *obj, Serialize::Data &);
static std::vector<Anope::string> TypeOrder;
static std::map<Anope::string, Serialize::Type *> Types;
@@ -127,9 +149,9 @@ class CoreExport Serialize::Type : public Base
* this timestamp. if curtime == timestamp then we have the most up to date
* version of every object of this type.
*/
- time_t timestamp;
+ time_t timestamp = 0;
- public:
+public:
/* Map of Serializable::id to Serializable objects */
std::map<uint64_t, Serializable *> objects;
@@ -167,7 +189,7 @@ class CoreExport Serialize::Type : public Base
*/
void UpdateTimestamp();
- Module* GetOwner() const { return this->owner; }
+ Module *GetOwner() const { return this->owner; }
static Serialize::Type *Find(const Anope::string &name);
@@ -187,7 +209,7 @@ class Serialize::Checker
{
Anope::string name;
T obj;
- mutable ::Reference<Serialize::Type> type;
+ mutable ::Reference<Serialize::Type> type = nullptr;
inline void Check() const
{
@@ -197,26 +219,26 @@ class Serialize::Checker
type->Check();
}
- public:
- Checker(const Anope::string &n) : name(n), type(NULL) { }
+public:
+ Checker(const Anope::string &n) : name(n) { }
- inline const T* operator->() const
+ inline const T *operator->() const
{
this->Check();
return &this->obj;
}
- inline T* operator->()
+ inline T *operator->()
{
this->Check();
return &this->obj;
}
- inline const T& operator*() const
+ inline const T &operator*() const
{
this->Check();
return this->obj;
}
- inline T& operator*()
+ inline T &operator*()
{
this->Check();
return this->obj;
@@ -241,15 +263,14 @@ class Serialize::Checker
* destructed.
*/
template<typename T>
-class Serialize::Reference : public ReferenceBase
+class Serialize::Reference final
+ : public ReferenceBase
{
- protected:
- T *ref;
+protected:
+ T *ref = nullptr;
- public:
- Reference() : ref(NULL)
- {
- }
+public:
+ Reference() = default;
Reference(T *obj) : ref(obj)
{
@@ -305,7 +326,7 @@ class Serialize::Reference : public ReferenceBase
return NULL;
}
- inline T* operator*() const
+ inline T *operator*() const
{
if (!this->invalid)
{
@@ -318,7 +339,7 @@ class Serialize::Reference : public ReferenceBase
return NULL;
}
- inline T* operator->() const
+ inline T *operator->() const
{
if (!this->invalid)
{
@@ -331,5 +352,3 @@ class Serialize::Reference : public ReferenceBase
return NULL;
}
};
-
-#endif // SERIALIZE_H
diff --git a/include/servers.h b/include/servers.h
index cc97c25ec..5c78cc979 100644
--- a/include/servers.h
+++ b/include/servers.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef SERVERS_H
-#define SERVERS_H
+#pragma once
#include "services.h"
#include "anope.h"
@@ -26,7 +25,7 @@ namespace Servers
* the only server whose uplink *is* Me that is not a juped server.
* @return Our uplink, or NULL if not uplinked to anything
*/
- extern CoreExport Server* GetUplink();
+ extern CoreExport Server *GetUplink();
/* Server maps by name and id */
extern CoreExport Anope::map<Server *> ByName;
@@ -38,9 +37,10 @@ namespace Servers
/** Class representing a server
*/
-class CoreExport Server : public Extensible
+class CoreExport Server final
+ : public Extensible
{
- private:
+private:
/* Server name */
Anope::string name;
/* Hops between services and server */
@@ -62,7 +62,7 @@ class CoreExport Server : public Extensible
/* Reason this server was quit */
Anope::string quit_reason;
- public:
+public:
/** Constructor
* @param uplink The uplink this server is from, is only NULL when creating Me
* @param name The server name
@@ -73,14 +73,14 @@ class CoreExport Server : public Extensible
*/
Server(Server *uplink, const Anope::string &name, unsigned hops, const Anope::string &description, const Anope::string &sid = "", bool jupe = false);
- private:
+private:
/** Destructor
*/
~Server();
- public:
+public:
/* Number of users on the server */
- unsigned users;
+ unsigned users = 0;
/** Delete this server with a reason
* @param reason The reason
@@ -183,5 +183,3 @@ class CoreExport Server : public Extensible
*/
static Server *Find(const Anope::string &name, bool name_only = false);
};
-
-#endif // SERVERS_H
diff --git a/include/service.h b/include/service.h
index ee5168b85..ad1d12f92 100644
--- a/include/service.h
+++ b/include/service.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef SERVICE_H
-#define SERVICE_H
+#pragma once
#include "services.h"
#include "anope.h"
@@ -21,7 +20,8 @@
* such as commands, use this. This is also used for modules
* that publish a service (m_ssl_openssl, etc).
*/
-class CoreExport Service : public virtual Base
+class CoreExport Service
+ : public virtual Base
{
static std::map<Anope::string, std::map<Anope::string, Service *> > Services;
static std::map<Anope::string, std::map<Anope::string, Anope::string> > Aliases;
@@ -42,7 +42,7 @@ class CoreExport Service : public virtual Base
return NULL;
}
- public:
+public:
static Service *FindService(const Anope::string &t, const Anope::string &n)
{
std::map<Anope::string, std::map<Anope::string, Service *> >::const_iterator it = Services.find(t);
@@ -59,13 +59,27 @@ class CoreExport Service : public virtual Base
static std::vector<Anope::string> GetServiceKeys(const Anope::string &t)
{
std::vector<Anope::string> keys;
- std::map<Anope::string, std::map<Anope::string, Service *> >::iterator it = Services.find(t);
+ const auto it = Services.find(t);
if (it != Services.end())
- for (std::map<Anope::string, Service *>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
- keys.push_back(it2->first);
+ {
+ for (const auto &[key, _] : it->second)
+ keys.push_back(key);
+ }
return keys;
}
+ static std::vector<Service *> GetServices(const Anope::string &t)
+ {
+ std::vector<Service *> values;
+ const auto it = Services.find(t);
+ if (it != Services.end())
+ {
+ for (const auto &[_, value] : it->second)
+ values.push_back(value);
+ }
+ return values;
+ }
+
static void AddAlias(const Anope::string &t, const Anope::string &n, const Anope::string &v)
{
std::map<Anope::string, Anope::string> &smap = Aliases[t];
@@ -98,10 +112,8 @@ class CoreExport Service : public virtual Base
void Register()
{
- std::map<Anope::string, Service *> &smap = Services[this->type];
- if (smap.find(this->name) != smap.end())
+ if (!Services[this->type].emplace(this->name, this).second)
throw ModuleException("Service " + this->type + " with name " + this->name + " already exists");
- smap[this->name] = this;
}
void Unregister()
@@ -113,16 +125,17 @@ class CoreExport Service : public virtual Base
}
};
-/** Like Reference, but used to refer to Services.
+/** Like Reference, but used to refer to a Service.
*/
template<typename T>
-class ServiceReference : public Reference<T>
+class ServiceReference
+ : public Reference<T>
{
Anope::string type;
Anope::string name;
- public:
- ServiceReference() { }
+public:
+ ServiceReference() = default;
ServiceReference(const Anope::string &t, const Anope::string &n) : type(t), name(n)
{
@@ -138,7 +151,7 @@ class ServiceReference : public Reference<T>
this->invalid = true;
}
- operator bool() anope_override
+ operator bool() override
{
if (this->invalid)
{
@@ -159,10 +172,10 @@ class ServiceReference : public Reference<T>
}
};
-class ServiceAlias
+class ServiceAlias final
{
Anope::string t, f;
- public:
+public:
ServiceAlias(const Anope::string &type, const Anope::string &from, const Anope::string &to) : t(type), f(from)
{
Service::AddAlias(type, from, to);
@@ -173,5 +186,3 @@ class ServiceAlias
Service::DelAlias(t, f);
}
};
-
-#endif // SERVICE_H
diff --git a/include/services.h b/include/services.h
index 722636379..7f0752d11 100644
--- a/include/services.h
+++ b/include/services.h
@@ -9,60 +9,43 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef SERVICES_H
-#define SERVICES_H
-
-#include "sysconf.h"
-
-#define BUFSIZE 1024
+#pragma once
+#include <cstdarg>
+#include <cstddef>
+#include <cstdint>
#include <cstdio>
#include <cstdlib>
-#include <cstdarg>
-#include <stdexcept>
-
-#include <string.h>
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
+#include <cstring>
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-/* Pull in the various bits of STL */
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <map>
+#include <algorithm>
+#include <bitset>
+#include <deque>
#include <exception>
+#include <fstream>
+#include <iostream>
#include <list>
-#include <vector>
-#include <deque>
-#include <bitset>
+#include <map>
#include <set>
-#include <algorithm>
-#include <iterator>
+#include <sstream>
+#include <vector>
+
+#ifndef _WIN32
+# include <unistd.h>
+#endif
#include "defs.h"
+#include "sysconf.h"
-#define _(x) x
+#define BUFSIZE 1024
-#if defined __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
-# define anope_override override
-# define anope_final final
-#else
-# define anope_override
-# define anope_final
-#endif
+#define _(x) x
+#define N_(x, y) x, y
#ifndef _WIN32
-# define DllExport
-# define CoreExport
-# define MARK_DEPRECATED __attribute((deprecated))
+# define DllExport __attribute__ ((visibility ("default")))
+# define CoreExport __attribute__ ((visibility ("default")))
# define anope_close close
#else
# include "anope_windows.h"
#endif
-
-#endif // SERVICES_H
diff --git a/include/socketengine.h b/include/socketengine.h
index e5b30ec92..83eaa3705 100644
--- a/include/socketengine.h
+++ b/include/socketengine.h
@@ -9,16 +9,15 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef SOCKETENGINE_H
-#define SOCKETENGINE_H
+#pragma once
#include "services.h"
#include "sockets.h"
-class CoreExport SocketEngine
+class CoreExport SocketEngine final
{
static const int DefaultSize = 2; // Uplink, mode stacker
- public:
+public:
/* Map of sockets */
static std::map<int, Socket *> Sockets;
@@ -46,5 +45,3 @@ class CoreExport SocketEngine
static bool IgnoreErrno();
};
-
-#endif // SOCKETENGINE_H
diff --git a/include/sockets.h b/include/sockets.h
index dcdb49a5e..e9b40685c 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -9,17 +9,22 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef SOCKETS_H
-#define SOCKETS_H
+#pragma once
#ifndef _WIN32
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#endif
#include "anope.h"
+// This has to be after anope.h
+#ifdef _WIN32
+# include <afunix.h>
+#endif
+
#define NET_BUFSIZE 65535
/** A sockaddr union used to combine IPv4 and IPv6 sockaddrs
@@ -29,6 +34,7 @@ union CoreExport sockaddrs
sockaddr sa;
sockaddr_in sa4;
sockaddr_in6 sa6;
+ sockaddr_un saun;
/** Construct the object, sets everything to 0
*/
@@ -57,6 +63,11 @@ union CoreExport sockaddrs
*/
Anope::string addr() const;
+ /** Gets the endpoint represented by this addr.
+ * @return The endpoint.
+ */
+ Anope::string str() const;
+
/** Get the reverse address represented by this addr
* @return The reverse address
*/
@@ -92,12 +103,12 @@ union CoreExport sockaddrs
void ntop(int type, const void *src);
};
-class CoreExport cidr
+class CoreExport cidr final
{
sockaddrs addr;
Anope::string cidr_ip;
unsigned short cidr_len;
- public:
+public:
cidr(const Anope::string &ip);
cidr(const Anope::string &ip, unsigned char len);
cidr(const sockaddrs &ip, unsigned char len);
@@ -109,15 +120,16 @@ class CoreExport cidr
bool operator==(const cidr &other) const;
bool operator!=(const cidr &other) const;
- struct CoreExport hash
+ struct CoreExport hash final
{
size_t operator()(const cidr &s) const;
};
};
-class SocketException : public CoreException
+class CoreExport SocketException final
+ : public CoreException
{
- public:
+public:
/** Constructor for socket exceptions
* @param message Error message
*/
@@ -126,7 +138,7 @@ class SocketException : public CoreException
/** Destructor
* @throws Nothing
*/
- virtual ~SocketException() throw() { }
+ virtual ~SocketException() noexcept = default;
};
enum SocketFlag
@@ -143,8 +155,8 @@ enum SocketFlag
class CoreExport SocketIO
{
- public:
- virtual ~SocketIO() { }
+public:
+ virtual ~SocketIO() = default;
/** Receive something from the buffer
* @param s The socket
@@ -152,15 +164,15 @@ class CoreExport SocketIO
* @param sz How much to read
* @return Number of bytes received
*/
- virtual int Recv(Socket *s, char *buf, size_t sz);
+ virtual ssize_t Recv(Socket *s, char *buf, size_t sz);
/** Write something to the socket
* @param s The socket
* @param buf The data to write
* @param size The length of the data
*/
- virtual int Send(Socket *s, const char *buf, size_t sz);
- int Send(Socket *s, const Anope::string &buf);
+ virtual ssize_t Send(Socket *s, const char *buf, size_t sz);
+ ssize_t Send(Socket *s, const Anope::string &buf);
/** Accept a connection from a socket
* @param s The socket
@@ -201,13 +213,14 @@ class CoreExport SocketIO
class CoreExport Socket
{
- protected:
+protected:
/* Socket FD */
int sock;
- /* Is this an IPv6 socket? */
- bool ipv6;
- public:
+ /* The family of this socket FD */
+ int family;
+
+public:
std::bitset<SF_SIZE> flags;
/* Sockaddrs for bind() (if it's bound) */
@@ -222,25 +235,25 @@ class CoreExport Socket
/** Constructor, possibly creates the socket and adds it to the engine
* @param sock The socket to use, -1 if we need to create our own
- * @param ipv6 true if using ipv6
+ * @param family The family of the socket
* @param type The socket type, defaults to SOCK_STREAM
*/
- Socket(int sock, bool ipv6 = false, int type = SOCK_STREAM);
+ Socket(int sock, int family = AF_INET, int type = SOCK_STREAM);
/** Destructor, closes the socket and removes it from the engine
*/
virtual ~Socket();
+ /** Get the socket family for this socket
+ * @return the family
+ */
+ int GetFamily() const;
+
/** Get the socket FD for this socket
* @return the fd
*/
int GetFD() const;
- /** Check if this socket is IPv6
- * @return true or false
- */
- bool IsIPv6() const;
-
/** Mark a socket as (non)blocking
* @param state true to enable blocking, false to disable blocking
* @return true if the socket is now blocking
@@ -274,9 +287,10 @@ class CoreExport Socket
virtual void ProcessError();
};
-class CoreExport BufferedSocket : public virtual Socket
+class CoreExport BufferedSocket
+ : public virtual Socket
{
- protected:
+protected:
/* Things read from the socket */
Anope::string read_buffer;
/* Things to be written to the socket */
@@ -284,31 +298,30 @@ class CoreExport BufferedSocket : public virtual Socket
/* How much data was received from this socket on this recv() */
int recv_len;
- public:
- BufferedSocket();
- virtual ~BufferedSocket();
+public:
+ virtual ~BufferedSocket() = default;
/** Called when there is something to be received for this socket
* @return true on success, false to drop this socket
*/
- bool ProcessRead() anope_override;
+ bool ProcessRead() override;
/** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
- bool ProcessWrite() anope_override;
+ bool ProcessWrite() override;
/** Gets the new line from the input buffer, if any
*/
- const Anope::string GetLine();
+ Anope::string GetLine();
/** Write to the socket
* @param message The message
*/
- protected:
+protected:
virtual void Write(const char *buffer, size_t l);
- public:
- void Write(const char *message, ...);
+public:
+ void Write(const char *message, ...) ATTR_FORMAT(2, 3);
void Write(const Anope::string &message);
/** Get the length of the read buffer
@@ -322,10 +335,11 @@ class CoreExport BufferedSocket : public virtual Socket
int WriteBufferLen() const;
};
-class CoreExport BinarySocket : public virtual Socket
+class CoreExport BinarySocket
+ : public virtual Socket
{
- protected:
- struct DataBlock
+protected:
+ struct DataBlock final
{
char *orig;
char *buf;
@@ -338,26 +352,25 @@ class CoreExport BinarySocket : public virtual Socket
/* Data to be written out */
std::deque<DataBlock *> write_buffer;
- public:
- BinarySocket();
- virtual ~BinarySocket();
+public:
+ virtual ~BinarySocket() = default;
/** Called when there is something to be received for this socket
* @return true on success, false to drop this socket
*/
- bool ProcessRead() anope_override;
+ bool ProcessRead() override;
/** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
- bool ProcessWrite() anope_override;
+ bool ProcessWrite() override;
/** Write data to the socket
* @param buffer The data to write
* @param l The length of the data; if 0 then this function returns without doing anything
*/
virtual void Write(const char *buffer, size_t l);
- void Write(const char *message, ...);
+ void Write(const char *message, ...) ATTR_FORMAT(2, 3);
void Write(const Anope::string &message);
/** Called with data from the socket
@@ -368,16 +381,17 @@ class CoreExport BinarySocket : public virtual Socket
virtual bool Read(const char *buffer, size_t l);
};
-class CoreExport ListenSocket : public virtual Socket
+class CoreExport ListenSocket
+ : public virtual Socket
{
- public:
+public:
/** Constructor
* @param bindip The IP to bind to
* @param port The port to listen on
* @param ipv6 true for ipv6
*/
ListenSocket(const Anope::string &bindip, int port, bool ipv6);
- virtual ~ListenSocket();
+ virtual ~ListenSocket() = default;
/** Process what has come in from the connection
* @return false to destroy this socket
@@ -392,9 +406,10 @@ class CoreExport ListenSocket : public virtual Socket
virtual ClientSocket *OnAccept(int fd, const sockaddrs &addr) = 0;
};
-class CoreExport ConnectionSocket : public virtual Socket
+class CoreExport ConnectionSocket
+ : public virtual Socket
{
- public:
+public:
/* Sockaddrs for connection ip/port */
sockaddrs conaddr;
@@ -408,12 +423,12 @@ class CoreExport ConnectionSocket : public virtual Socket
* Used to determine whether or not this socket is connected yet.
* @return true to continue to call ProcessRead/ProcessWrite, false to not continue
*/
- bool Process() anope_override;
+ bool Process() override;
/** Called when there is an error for this socket
* @return true on success, false to drop this socket
*/
- void ProcessError() anope_override;
+ void ProcessError() override;
/** Called on a successful connect
*/
@@ -425,9 +440,10 @@ class CoreExport ConnectionSocket : public virtual Socket
virtual void OnError(const Anope::string &error);
};
-class CoreExport ClientSocket : public virtual Socket
+class CoreExport ClientSocket
+ : public virtual Socket
{
- public:
+public:
/* Listen socket this connection came from */
ListenSocket *ls;
/* Clients address */
@@ -443,12 +459,12 @@ class CoreExport ClientSocket : public virtual Socket
* Used to determine whether or not this socket is connected yet.
* @return true to continue to call ProcessRead/ProcessWrite, false to not continue
*/
- bool Process() anope_override;
+ bool Process() override;
/** Called when there is an error for this socket
* @return true on success, false to drop this socket
*/
- void ProcessError() anope_override;
+ void ProcessError() override;
/** Called when a client has been accepted() successfully.
*/
@@ -459,9 +475,10 @@ class CoreExport ClientSocket : public virtual Socket
virtual void OnError(const Anope::string &error);
};
-class CoreExport Pipe : public Socket
+class CoreExport Pipe
+ : public Socket
{
- public:
+public:
/** The FD of the write pipe
* this->sock is the readfd
*/
@@ -472,7 +489,7 @@ class CoreExport Pipe : public Socket
/** Called when data is to be read, reads the data then calls OnNotify
*/
- bool ProcessRead() anope_override;
+ bool ProcessRead() override;
/** Write data to this pipe
* @param data The data to write
@@ -486,7 +503,7 @@ class CoreExport Pipe : public Socket
* @param sz The size of the buffer
* @return The amount of data read
*/
- int Read(char *data, size_t sz);
+ ssize_t Read(char *data, size_t sz);
/** Mark the write end of this pipe (non)blocking
* @param state true to enable blocking, false to disable blocking
@@ -507,5 +524,3 @@ class CoreExport Pipe : public Socket
extern CoreExport uint32_t TotalRead;
extern CoreExport uint32_t TotalWritten;
extern CoreExport SocketIO NormalSocketIO;
-
-#endif // SOCKET_H
diff --git a/include/sysconf.h.cmake b/include/sysconf.h.cmake
index 5f0e275c3..71290dfca 100644
--- a/include/sysconf.h.cmake
+++ b/include/sysconf.h.cmake
@@ -1,47 +1,58 @@
-#ifndef _SYSCONF_H_
-#define _SYSCONF_H_
+/*
+ *
+ * (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.
+ */
-#cmakedefine DEBUG_BUILD
+#pragma once
+// The default umask to use for files.
#cmakedefine DEFUMASK @DEFUMASK@
-#cmakedefine HAVE_CSTDINT 1
-#cmakedefine HAVE_STDINT_H 1
-#cmakedefine HAVE_STDDEF_H 1
-#cmakedefine HAVE_STRCASECMP 1
-#cmakedefine HAVE_STRICMP 1
-#cmakedefine HAVE_STRINGS_H 1
-#cmakedefine HAVE_UMASK 1
-#cmakedefine HAVE_EVENTFD 1
-#cmakedefine HAVE_EPOLL 1
-#cmakedefine HAVE_POLL 1
-#cmakedefine GETTEXT_FOUND 1
-
-#ifdef HAVE_CSTDINT
-# include <cstdint>
-#else
-# ifdef HAVE_STDINT_H
-# include <stdint.h>
-# else
-# include "pstdint.h"
-# endif
-#endif
-#ifdef HAVE_STDDEF_H
-# include <stddef.h>
-#endif
+
+// The extension used for module file extensions.
+#define DLL_EXT "@CMAKE_SHARED_LIBRARY_SUFFIX@"
+
+// Whether Anope was built in debug mode.
+#cmakedefine01 DEBUG_BUILD
+
+// The default config directory.
+#define DEFAULT_CONF_DIR "@CONF_DIR@"
+
+// The default data directory.
+#define DEFAULT_DATA_DIR "@DATA_DIR@"
+
+// The default locale directory.
+#define DEFAULT_LOCALE_DIR "@LOCALE_DIR@"
+
+// The default log directory.
+#define DEFAULT_LOG_DIR "@LOG_DIR@"
+
+// The default module directory.
+#define DEFAULT_MODULE_DIR "@MODULE_DIR@"
+
+// Whether the clock_gettime() function is available.
+#cmakedefine01 HAVE_CLOCK_GETTIME
+
+// Whether Anope was built with localization support.
+#cmakedefine01 HAVE_LOCALIZATION
+
+// Whether the umask() function is available.
+#cmakedefine01 HAVE_UMASK
#ifdef _WIN32
# define popen _popen
# define pclose _pclose
-# define ftruncate _chsize
-# ifdef MSVCPP
-# define PATH_MAX MAX_PATH
-# endif
-# define MAXPATHLEN MAX_PATH
-# define bzero(buf, size) memset(buf, 0, size)
-# ifdef MSVCPP
-# define strcasecmp stricmp
-# endif
-# define sleep(x) Sleep(x * 1000)
#endif
+#if defined __GNUC__
+# define ATTR_FORMAT(STRINGPOS, FIRSTPOS) __attribute__((format(printf, STRINGPOS, FIRSTPOS)))
+# define ATTR_NOT_NULL(...) __attribute__((nonnull(__VA_ARGS__)))
+#else
+# define ATTR_FORMAT(STRINGPOS, FIRSTPOS)
+# define ATTR_NOT_NULL(...)
#endif
diff --git a/include/threadengine.h b/include/threadengine.h
index c7c88d157..b8184d8a8 100644
--- a/include/threadengine.h
+++ b/include/threadengine.h
@@ -9,29 +9,28 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef THREADENGINE_H
-#define THREADENGINE_H
+#pragma once
#include "sockets.h"
#include "extensible.h"
-class CoreExport Thread : public Pipe, public Extensible
+#include <thread>
+
+class CoreExport Thread
+ : public Pipe
+ , public Extensible
{
- private:
+private:
/* Set to true to tell the thread to finish and we are waiting for it */
- bool exit;
+ bool exit = false;
- public:
+public:
/* Handle for this thread */
- pthread_t handle;
-
- /** Threads constructor
- */
- Thread();
+ std::unique_ptr<std::thread> handle;
/** Threads destructor
*/
- virtual ~Thread();
+ virtual ~Thread() = default;
/** Join to the thread, sets the exit state to true
*/
@@ -62,59 +61,3 @@ class CoreExport Thread : public Pipe, public Extensible
*/
virtual void Run() = 0;
};
-
-class CoreExport Mutex
-{
- protected:
- /* A mutex, used to keep threads in sync */
- pthread_mutex_t mutex;
-
- public:
- /** Constructor
- */
- Mutex();
-
- /** Destructor
- */
- ~Mutex();
-
- /** Attempt to lock the mutex, will hang until a lock can be achieved
- */
- void Lock();
-
- /** Unlock the mutex, it must be locked first
- */
- void Unlock();
-
- /** Attempt to lock the mutex, will return true on success and false on fail
- * Does not block
- * @return true or false
- */
- bool TryLock();
-};
-
-class CoreExport Condition : public Mutex
-{
- private:
- /* A condition */
- pthread_cond_t cond;
-
- public:
- /** Constructor
- */
- Condition();
-
- /** Destructor
- */
- ~Condition();
-
- /** Called to wakeup the waiter
- */
- void Wakeup();
-
- /** Called to wait for a Wakeup() call
- */
- void Wait();
-};
-
-#endif // THREADENGINE_H
diff --git a/include/timers.h b/include/timers.h
index 2764ccc56..f4ee47b75 100644
--- a/include/timers.h
+++ b/include/timers.h
@@ -9,49 +9,42 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef TIMERS_H
-#define TIMERS_H
+#pragma once
#include "anope.h"
class CoreExport Timer
{
- private:
+private:
/** The owner of the timer, if any
*/
- Module *owner;
-
- /** The time this was created
- */
- time_t settime;
+ Module *owner = nullptr;
/** The triggering time
*/
time_t trigger;
- /** Numer of seconds between triggers
+ /** Number of seconds between triggers
*/
- long secs;
+ time_t secs;
/** True if this is a repeating timer
*/
bool repeat;
- public:
+public:
/** Constructor, initializes the triggering time
* @param time_from_now The number of seconds from now to trigger the timer
- * @param now The time now
* @param repeating Repeat this timer every time_from_now if this is true
*/
- Timer(long time_from_now, time_t now = Anope::CurTime, bool repeating = false);
+ Timer(time_t time_from_now, bool repeating = false);
/** Constructor, initializes the triggering time
* @param creator The creator of the timer
* @param time_from_now The number of seconds from now to trigger the timer
- * @param now The time now
* @param repeating Repeat this timer every time_from_now if this is true
*/
- Timer(Module *creator, long time_from_now, time_t now = Anope::CurTime, bool repeating = false);
+ Timer(Module *creator, time_t time_from_now, bool repeating = false);
/** Destructor, removes the timer from the list
*/
@@ -82,11 +75,6 @@ class CoreExport Timer
*/
long GetSecs() const;
- /** Returns the time this timer was created
- * @return The time this timer was created
- */
- time_t GetSetTime() const;
-
/** Returns the owner of this timer, if any
* @return The owner of the timer
*/
@@ -95,19 +83,19 @@ class CoreExport Timer
/** Called when the timer ticks
* This should be overridden with something useful
*/
- virtual void Tick(time_t ctime) = 0;
+ virtual void Tick() = 0;
};
/** This class manages sets of Timers, and triggers them at their defined times.
* This will ensure timers are not missed, as well as removing timers that have
* expired and allowing the addition of new ones.
*/
-class CoreExport TimerManager
+class CoreExport TimerManager final
{
/** A list of timers
*/
static std::multimap<time_t, Timer *> Timers;
- public:
+public:
/** Add a timer to the list
* @param t A Timer derived class to add
*/
@@ -121,11 +109,9 @@ class CoreExport TimerManager
/** Tick all pending timers
* @param ctime The current time
*/
- static void TickTimers(time_t ctime = Anope::CurTime);
+ static void TickTimers();
/** Deletes all timers owned by the given module
*/
static void DeleteTimersFor(Module *m);
};
-
-#endif // TIMERS_H
diff --git a/include/uplink.h b/include/uplink.h
index 035ab5b27..ffa389345 100644
--- a/include/uplink.h
+++ b/include/uplink.h
@@ -9,45 +9,53 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef UPLINK_H
-#define UPLINK_H
+#pragma once
#include "sockets.h"
#include "protocol.h"
+#include "servers.h"
namespace Uplink
{
extern void Connect();
+ extern CoreExport void SendInternal(const Anope::map<Anope::string> &, const MessageSource &, const Anope::string &, const std::vector<Anope::string> &);
+
+ template<typename... Args>
+ void Send(const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, Args &&...args)
+ {
+ SendInternal(tags, source, command, { Anope::ToString(args)... });
+ }
+
+ template<typename... Args>
+ void Send(const Anope::map<Anope::string> &tags, const Anope::string &command, Args &&...args)
+ {
+ SendInternal(tags, Me, command, { Anope::ToString(args)... });
+ }
+
+ template<typename... Args>
+ void Send(const MessageSource &source, const Anope::string &command, Args &&...args)
+ {
+ SendInternal({}, source, command, { Anope::ToString(args)... });
+ }
+
+ template<typename... Args>
+ void Send(const Anope::string &command, Args &&...args)
+ {
+ SendInternal({}, Me, command, { Anope::ToString(args)... });
+ }
}
/* This is the socket to our uplink */
-class UplinkSocket : public ConnectionSocket, public BufferedSocket
+class UplinkSocket final
+ : public ConnectionSocket
+ , public BufferedSocket
{
- public:
+public:
bool error;
UplinkSocket();
~UplinkSocket();
- bool ProcessRead() anope_override;
- void OnConnect() anope_override;
- void OnError(const Anope::string &) anope_override;
-
- /* A message sent over the uplink socket */
- class CoreExport Message
- {
- MessageSource source;
- std::stringstream buffer;
-
- public:
- Message();
- Message(const MessageSource &);
- ~Message();
- template<typename T> Message &operator<<(const T &val)
- {
- this->buffer << val;
- return *this;
- }
- };
+ bool ProcessRead() override;
+ void OnConnect() override;
+ void OnError(const Anope::string &) override;
};
extern CoreExport UplinkSocket *UplinkSock;
-
-#endif // UPLINK_H
diff --git a/include/users.h b/include/users.h
index c8f05ca2c..7fd096c8c 100644
--- a/include/users.h
+++ b/include/users.h
@@ -9,8 +9,7 @@
* Based on the original code of Services by Andy Church.
*/
-#ifndef USERS_H
-#define USERS_H
+#pragma once
#include "anope.h"
#include "modes.h"
@@ -20,7 +19,7 @@
#include "account.h"
#include "sockets.h"
-typedef Anope::hash_map<User *> user_map;
+typedef Anope::unordered_map<User *> user_map;
extern CoreExport user_map UserListByNick, UserListByUID;
@@ -29,21 +28,22 @@ extern CoreExport unsigned MaxUserCount;
extern CoreExport time_t MaxUserTime;
/* Online user and channel data. */
-class CoreExport User : public virtual Base, public Extensible, public CommandReply
+class CoreExport User
+ : public virtual Base
+ , public Extensible
+ , public CommandReply
{
/* true if the user was quit or killed */
bool quit;
/* Users that are in the process of quitting */
static std::list<User *> quitting_users;
- public:
+public:
typedef std::map<Anope::string, Anope::string> ModeList;
- protected:
+protected:
Anope::string vident;
Anope::string ident;
Anope::string uid;
- /* If the user is on the access list of the nick they're on */
- bool on_access;
/* Map of user modes and the params this user has (if any) */
ModeList modes;
/* NickCore account the user is currently logged in as, if they are logged in */
@@ -55,7 +55,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
time_t invalid_pw_time;
- public: // XXX: exposing a tiny bit too much
+public: // XXX: exposing a tiny bit too much
/* User's current nick */
Anope::string nick;
@@ -91,7 +91,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
/* Last time this user sent an email */
time_t lastmail;
- protected:
+protected:
/** Create a new user object, initialising necessary fields and
* adds it to the hash
*
@@ -107,14 +107,14 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
* @param suid The unique identifier of the user.
* @param nc The account the user is identified as, if any
*/
- User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc);
+ User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const std::vector<Anope::string> &smodeparams, const Anope::string &suid, NickCore *nc);
/** Destroy a user.
*/
virtual ~User();
- public:
- static User* OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc);
+public:
+ static User *OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc, const std::vector<Anope::string> &smodeparams = {});
/** Update the nickname of a user record accordingly, should be
* called from ircd protocol.
@@ -189,8 +189,10 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
* @param fmt Format of the Message
* @param ... any number of parameters
*/
- void SendMessage(BotInfo *source, const char *fmt, ...);
- void SendMessage(BotInfo *source, const Anope::string &msg) anope_override;
+ void SendMessage(BotInfo *source, const char *fmt, ...) ATTR_FORMAT(3, 4);
+ void SendMessage(BotInfo *source, int count, const char *singular, const char *plural, ...) ATTR_FORMAT(5, 6);
+ void SendMessage(BotInfo *source, const Anope::string &msg) override;
+ void SendMessage(CommandSource &source, const Anope::string &msg) override;
/** Identify the user to a nick.
* updates last_seen, logs the user in,
@@ -214,17 +216,21 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
*/
NickCore *Account() const;
+ /** Get the account nick the user is logged in using
+ * @return The account nick or NULL
+ */
+ NickAlias *AccountNick() const;
+
/** Check if the user is identified for their nick
* @param check_nick True to check if the user is identified to the nickname they are on too
* @return true or false
*/
bool IsIdentified(bool check_nick = false) const;
- /** Check if the user is recognized for their nick (on the nicks access list)
- * @param check_secure Only returns true if the user has secure off
- * @return true or false
+ /** Check if the user is connected securely.
+ * @return True if the user is connected securely; otherwise, false.
*/
- bool IsRecognized(bool check_secure = true) const;
+ bool IsSecurelyConnected() const;
/** Check if the user is a services oper
* @return true if they are an oper
@@ -243,8 +249,7 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
*/
bool HasPriv(const Anope::string &privstr);
- /** Update the last usermask stored for a user, and check to see if they are recognized
- */
+ /** Update the last usermask stored for a user. */
void UpdateHost();
/** Check if the user has a mode
@@ -298,13 +303,15 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
* @param bi The client setting the modes
* @param umodes The modes
*/
- void SetModes(BotInfo *bi, const char *umodes, ...);
+ void SetModes(BotInfo *bi, const char *umodes, ...) ATTR_FORMAT(3, 4);
+ void SetModes(BotInfo *bi, const Anope::string &umodes);
/** Set a string of modes on a user internally
* @param setter who/what is setting the mode
- * @param umodes The modes
+ * @param umodes The mode letters
+ * @param umodeparams The mode values
*/
- void SetModesInternal(const MessageSource &source, const char *umodes, ...);
+ void SetModesInternal(const MessageSource &source, const Anope::string &umodes, const std::vector<Anope::string> &umodeparams = {});
/** Get modes set for this user.
* @return A string of modes set on the user
@@ -359,16 +366,17 @@ class CoreExport User : public virtual Base, public Extensible, public CommandRe
*/
bool BadPassword();
+ /** Determines whether this user should receive a PRIVMSG instead of a NOTICE. */
+ bool ShouldPrivmsg() const;
+
/** Finds a user by nick, or possibly UID
* @param name The nick, or possibly UID, to lookup
* @param nick_only set to true to only look up by nick, not UID
* @return the user, if they exist
*/
- static User* Find(const Anope::string &name, bool nick_only = false);
+ static User *Find(const Anope::string &name, bool nick_only = false);
/** Quits all users who are pending to be quit
*/
static void QuitUsers();
};
-
-#endif // USERS_H
diff --git a/include/version.cpp b/include/version.cpp
index 4a11a6e11..d87bebb18 100644
--- a/include/version.cpp
+++ b/include/version.cpp
@@ -42,7 +42,7 @@ static std::string get_git_hash(const std::string &git_dir)
}
fd.close();
- return "g" + filebuf.substr(0, 7);
+ return filebuf.substr(0, 7);
}
static bool read_version_sh(const std::string &version_sh, std::map<std::string, std::string> &versions)
@@ -105,8 +105,9 @@ static bool write_build_h(const std::string &buildh, const std::string &git_vers
return false;
}
- fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl;
- fd << build << std::endl;
+ fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl
+ << "#pragma once" << std::endl
+ << build << std::endl;
if (!git_version.empty())
fd << "#define VERSION_GIT \"" << git_version << "\"" << std::endl;
fd.close();
@@ -144,9 +145,10 @@ static bool write_version_h(const std::string &versionh, const std::map<std::str
if (!fd.is_open())
return false;
- for (std::map<std::string, std::string>::const_iterator it = versions.begin(); it != versions.end(); ++it)
+ fd << "#pragma once" << std::endl;
+ for (const auto &[key, value] : versions)
{
- fd << "#define " << it->first << " " << it->second << std::endl;
+ fd << "#define " << key << " " << value << std::endl;
}
fd.close();
@@ -170,19 +172,19 @@ int main(int argc, char *argv[])
std::map<std::string, std::string> versions, old_versions;
if (!read_version_sh(version_sh, versions))
- return -1;
+ return EXIT_FAILURE;
std::string git_version = get_git_hash(git_dir);
if (!write_build_h(buildh, git_version))
- return -1;
+ return EXIT_FAILURE;
read_version_h(versionh, old_versions);
if (versions == old_versions)
- return 0;
+ return EXIT_SUCCESS;
if (!write_version_h(versionh, versions))
- return -1;
+ return EXIT_FAILURE;
- return 0;
+ return EXIT_SUCCESS;
}
diff --git a/include/xline.h b/include/xline.h
index b02aeedd1..ebd88e928 100644
--- a/include/xline.h
+++ b/include/xline.h
@@ -6,25 +6,25 @@
* Please read COPYING and README for further details.
*/
-#ifndef XLINE_H
-#define XLINE_H
+#pragma once
#include "serialize.h"
#include "service.h"
#include "sockets.h"
/* An Xline, eg, anything added with operserv/akill, or any of the operserv/sxline commands */
-class CoreExport XLine : public Serializable
+class CoreExport XLine final
+ : public Serializable
{
void Init();
Anope::string nick, user, host, real;
- public:
+public:
cidr *c;
Anope::string mask;
Regex *regex;
Anope::string by;
- time_t created;
- time_t expires;
+ time_t created = 0;
+ time_t expires = 0;
Anope::string reason;
XLineManager *manager;
Anope::string id;
@@ -44,19 +44,20 @@ class CoreExport XLine : public Serializable
bool HasNickOrReal() const;
bool IsRegex() const;
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
/* Managers XLines. There is one XLineManager per type of XLine. */
-class CoreExport XLineManager : public Service
+class CoreExport XLineManager
+ : public Service
{
char type;
/* List of XLines in this XLineManager */
Serialize::Checker<std::vector<XLine *> > xlines;
/* Akills can have the same IDs, sometimes */
static Serialize::Checker<std::multimap<Anope::string, XLine *, ci::less> > XLinesByUID;
- public:
+public:
/* List of XLine managers we check users against in XLineManager::CheckAll */
static std::list<XLineManager *> XLineManagers;
@@ -124,7 +125,7 @@ class CoreExport XLineManager : public Service
* @param index The index
* @return The XLine, or NULL if the index is out of bounds
*/
- XLine* GetEntry(unsigned index);
+ XLine *GetEntry(unsigned index);
/** Clear the XLine vector
* Note: This does not remove the XLines from the IRCd
@@ -144,7 +145,7 @@ class CoreExport XLineManager : public Service
* @param mask The mask
* @return The XLine the user matches, or NULL
*/
- XLine* HasEntry(const Anope::string &mask);
+ XLine *HasEntry(const Anope::string &mask);
/** Check a user against all of the xlines in this XLineManager
* @param u The user
@@ -180,5 +181,3 @@ class CoreExport XLineManager : public Service
*/
virtual void SendDel(XLine *x) = 0;
};
-
-#endif // XLINE_H
diff --git a/language/CMakeLists.txt b/language/CMakeLists.txt
index 577e132a3..3c98d266a 100644
--- a/language/CMakeLists.txt
+++ b/language/CMakeLists.txt
@@ -1,8 +1,8 @@
# Only do this if gettext is installed
-if(GETTEXT_FOUND)
+if(HAVE_LOCALIZATION)
# Get all of the .po files
file(GLOB LANG_SRCS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.*.po")
- sort_list(LANG_SRCS_PO)
+ list(SORT LANG_SRCS_PO)
foreach(LANG_PO ${LANG_SRCS_PO})
# Get the domain for this language file
@@ -26,12 +26,12 @@ if(GETTEXT_FOUND)
# Add to cpack ignored files if not on Windows.
if(NOT WIN32)
add_to_cpack_ignored_files("${LANG_MO}")
- endif(NOT WIN32)
+ endif()
# Install the new language file
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG_MO} DESTINATION ${LOCALE_DIR}/${LANG_LANG}/LC_MESSAGES RENAME ${LANG_DOMAIN}.mo PERMISSIONS ${PERMS})
- endforeach(LANG_PO)
+ endforeach()
# Generate languages, depends on the mo files
add_custom_target(language DEPENDS ${LANG_SRCS_MO})
-endif(GETTEXT_FOUND)
+endif()
diff --git a/language/anope.ca_ES.po b/language/anope.ca_ES.po
deleted file mode 100644
index 54a662f47..000000000
--- a/language/anope.ca_ES.po
+++ /dev/null
@@ -1,10057 +0,0 @@
-# Anope IRC Services language file
-# Copyright (C) 2011
-# This file is distributed under the same license as the Anope IRC Services package.
-# Adam <adam@anope.org>, 2011.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Anope\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-01-06 18:19+0100\n"
-"PO-Revision-Date: 2010-09-19 20:12-0400\n"
-"Last-Translator: Adam <adam@anope.org>\n"
-"Language-Team: Catalan\n"
-"Language: ca_ES\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#, c-format
-msgid "%d channel(s) cleared, and %d channel(s) dropped."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%d nickname(s) dropped."
-msgstr "El teu nickname ha estat expulsat."
-
-#, fuzzy, c-format
-msgid "%s added to %s %s list."
-msgstr "%s afegit a la llista de AKILLs."
-
-#, c-format
-msgid "%s added to %s access list at level %d."
-msgstr "%s afegit a la llista d'accés de %s amb nivel %d."
-
-#, fuzzy, c-format
-msgid "%s added to %s access list at privilege %s (level %d)"
-msgstr "%s afegit a la llista d'accés de %s amb nivel %d."
-
-#, c-format
-msgid "%s added to %s autokick list."
-msgstr "%s afegit a la llista de kicks automàtics en el canal %s."
-
-#, c-format
-msgid "%s added to %s bad words list."
-msgstr "%s afegida a la llista de paraules malsonants de %s."
-
-#, fuzzy, c-format
-msgid "%s added to %s's access list."
-msgstr "%s afegit a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s added to %s's certificate list."
-msgstr "%s afegit a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s added to ignore list."
-msgstr "%s afegit a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s added to the %s list."
-msgstr "%s afegit a la llista de AKILLs."
-
-#, c-format
-msgid "%s added to the AKILL list."
-msgstr "%s afegit a la llista de AKILLs."
-
-#, c-format
-msgid ""
-"%s allows you to execute \"fantasy\" commands in the channel.\n"
-"Fantasy commands are commands that can be executed from messaging a\n"
-"channel, and provide a more convenient way to execute commands. Commands "
-"that\n"
-"require a channel as a parameter will automatically have that parameter\n"
-"given.\n"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to have a bot on your own channel.\n"
-"It has been created for users that can't host or\n"
-"configure a bot, or for use on networks that don't\n"
-"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
-"more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s et permet crear un bot en el teu propi canal.\n"
-"Això ha estat creat per a usuaris que no poden\n"
-"tenir un bot en un host o configurar un bot, o per a us en xarxes\n"
-"que no permeten bots d'usuaris. Comandes\n"
-"disponibles estan llistades més endavant; per a\n"
-"utilitzar-los, escriu /msg %s comanda. per a més\n"
-"informació sobre un comanda especifica, escriu \n"
-"/msg %s HELP comanda."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register a nickname and\n"
-"prevent others from using it. The following\n"
-"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s Et permet \"registrar\" un nickname i\n"
-"prevenir a d'altres utilitzar-lo. Les següents comandes\n"
-"permeten el registre i manteniment de nicknames;\n"
-"per a utilitzar-los, escriu /msg %s comanda.\n"
-"per més informació sobre una comanda especifica\n"
-"escriu /msg %s HELP comanda."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register an account.\n"
-"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s Et permet \"registrar\" un nickname i\n"
-"prevenir a d'altres utilitzar-lo. Les següents comandes\n"
-"permeten el registre i manteniment de nicknames;\n"
-"per a utilitzar-los, escriu /msg %s comanda.\n"
-"per més informació sobre una comanda especifica\n"
-"escriu /msg %s HELP comanda."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register and control various\n"
-"aspects of channels. %s can often prevent\n"
-"malicious users from \"taking over\" channels by limiting\n"
-"who is allowed channel operator privileges. Available\n"
-"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
-msgstr ""
-"%s et permet registrar i controlar varis\n"
-"aspectes dels canals. Sovint, %s pot prevenir\n"
-"a usuaris maliciosos \"pendre\" canals limitant\n"
-"qui esta permés a tenir privilegis d'operador.\n"
-"Les comandes disponibles estan llistades a continuació;\n"
-"Per a utilitzar-los, escriu /msg %s comanda.\n"
-"Per més informació sobre una comanda especifica,\n"
-"escriu /msg %s HELP comanda.\n"
-" "
-
-#, c-format
-msgid "%s already exists in %s bad words list."
-msgstr "%s ja existeix a la llista de paraules malsonants de %s."
-
-#, c-format
-msgid "%s already exists on %s autokick list."
-msgstr "%s ja esta present a la llista de kick automàtic en el canal %s."
-
-#, c-format
-msgid "%s already exists on the EXCEPTION list."
-msgstr "%s already exists on the EXCEPTION list."
-
-#, c-format
-msgid "%s cannot be taken as times to ban."
-msgstr "%s no pot ser pres com vegades a banegar"
-
-#, fuzzy, c-format
-msgid "%s changed your usermodes to %s."
-msgstr "%s changed your usermodes."
-
-#, fuzzy, c-format
-msgid "%s channel list:"
-msgstr "Fi de la llista de canals."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s %s list."
-msgstr "%s esborrat de la llista AOP de %s."
-
-#, c-format
-msgid "%s deleted from %s access list."
-msgstr "%s esborrat de la llista d'accés de %s."
-
-#, c-format
-msgid "%s deleted from %s autokick list."
-msgstr "%s esborrat de la llista de kicks automàtics del canal %s."
-
-#, c-format
-msgid "%s deleted from %s bad words list."
-msgstr "%s esborrada de la llista de paraules malsonants de %s."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s's access list."
-msgstr "%s esborrat de la llista d'accés de %s."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s's certificate list."
-msgstr "%s esborrat de la teva lllista d'accés."
-
-#, c-format
-msgid "%s deleted from session-limit exception list."
-msgstr ""
-"%s instàncies esborrades de la llista d'excepcions al límit de sessions."
-
-#, fuzzy, c-format
-msgid "%s deleted from the %s list."
-msgstr "%s esborrat de la llista AOP de %s."
-
-#, c-format
-msgid "%s deleted from the AKILL list."
-msgstr "%s esborrat de la llista de AKILLs."
-
-#, c-format
-msgid "%s disabled on channel %s."
-msgstr "%s inhabilitat(s) en el canal %s."
-
-#, c-format
-msgid "%s has been invited to %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "%s has been joined to %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "%s has been parted from %s."
-msgstr "%s has been unbanned from %s."
-
-#, c-format
-msgid "%s has been unbanned from %s."
-msgstr "%s has been unbanned from %s."
-
-#, fuzzy, c-format
-msgid "%s has no access in any channels."
-msgstr "%s inhabilitat(s) en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s has no access on %s."
-msgstr "%s has been invited to %s."
-
-#, c-format
-msgid "%s has too many channels registered."
-msgstr "%s te masses canals registrats."
-
-#, fuzzy, c-format
-msgid "%s is a super administrator."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy, c-format
-msgid ""
-"%s is a utility allowing IRC users to send short\n"
-"messages to other IRC users, whether they are online at\n"
-"the time or not, or to channels(*). Both the sender's\n"
-"nickname and the target nickname or channel must be\n"
-"registered in order to send a memo.\n"
-"%s's commands include:"
-msgstr ""
-"%s és una utilitat que permet a usuaris de IRC\n"
-"enviar missatges curts a altres usuaris de IRC, estiguin\n"
-"en linea o no, o a canals(*). Ambdós el nickname que\n"
-"envia i el nickname o canal destinataris han d'estar\n"
-"registrats per a enviar un memo.\n"
-"\n"
-"Les comandes de %s incloen:"
-
-#, fuzzy, c-format
-msgid "%s is already in %s!"
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is already in %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is already on the ignore list."
-msgstr "%s afegit a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s is already suspended."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is not a registered unforbidden nick or channel."
-msgstr "%s no és un bot valid o un canal registrat."
-
-#, c-format
-msgid "%s is not a valid ban type."
-msgstr "%s no es un tipus de ban valid."
-
-#, c-format
-msgid "%s is not a valid bot or registered channel."
-msgstr "%s no és un bot valid o un canal registrat."
-
-#, fuzzy, c-format
-msgid "%s is not a valid e-mail address."
-msgstr "%s no es un tipus de ban valid."
-
-#, fuzzy, c-format
-msgid "%s is not currently on channel %s."
-msgstr "%s inhabilitat(s) en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s is not in %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is not on the ignore list."
-msgstr "%s not found on ignore list."
-
-#, fuzzy, c-format
-msgid "%s is on the auto kick list of %s (%s)."
-msgstr "%s afegit a la llista de kicks automàtics en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s is the founder of %s."
-msgstr "%s inhabilitat(s) en el canal %s."
-
-#, c-format
-msgid "%s matches access entry %s (from entry %s), which has privilege %s."
-msgstr ""
-
-#, c-format
-msgid "%s matches access entry %s, which has privilege %s."
-msgstr ""
-
-#, c-format
-msgid ""
-"%s matches an except on %s and cannot be banned until the except has been "
-"removed."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s matches auto kick entry %s on %s (%s)."
-msgstr "%s afegit a la llista de kicks automàtics en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s not found on %s %s list."
-msgstr "%s no trobat a la llista AOP de %s."
-
-#, c-format
-msgid "%s not found on %s access list."
-msgstr "%s no trobat a la llista d'accés de %s."
-
-#, c-format
-msgid "%s not found on %s autokick list."
-msgstr "%s no trobat a la llista de kicks automàtics en el canal %s."
-
-#, c-format
-msgid "%s not found on %s bad words list."
-msgstr "%s no trobada a la llista de paraules malsonants de %s."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's access list."
-msgstr "%s no trobat a la llista d'accés de %s."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's certificate list."
-msgstr "%s no trobat a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s not found on ignore list."
-msgstr "%s not found on ignore list."
-
-#, c-format
-msgid ""
-"%s not found on session list, but has a limit of %d because it matches entry:"
-" %s."
-msgstr ""
-
-#, c-format
-msgid "%s not found on session-limit exception list."
-msgstr "%s no trobat a a la llista d'excepcions al límit de sessions."
-
-#, fuzzy, c-format
-msgid "%s not found on the %s list."
-msgstr "%s no trobat a la llista AOP de %s."
-
-#, c-format
-msgid "%s not found on the AKILL list."
-msgstr "%s no trobat a la llista de AKILLs."
-
-#, fuzzy, c-format
-msgid "%s removed from the %s access list."
-msgstr "%s esborrat de la llista d'accés de %s."
-
-#, fuzzy, c-format
-msgid "%s removed from the ignore list."
-msgstr "%s esborrat de la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s users list:"
-msgstr "Fi de la llista d'usuaris."
-
-#, c-format
-msgid "%s will no longer be ignored."
-msgstr "%s will no longer be ignored."
-
-#, c-format
-msgid "%s will now be ignored for %s."
-msgstr "%s will now be ignored for %s."
-
-#, c-format
-msgid "%s will now permanently be ignored."
-msgstr "%s will now permanently be ignored."
-
-#, fuzzy, c-format
-msgid "%s%s HELP %s for more information."
-msgstr ""
-"Escriu /msg %s HELP opció per més informació\n"
-"sobre una opció en particular."
-
-msgid "ADD nick user host real"
-msgstr ""
-
-#, fuzzy
-msgid "CHANGE oldnick newnick [user [host [real]]]"
-msgstr ""
-"BOT ADD nick usuari host nom-real\n"
-"BOT CHANGE nick-antic nick-nou [usuari [host [nom-real]]]\n"
-"BOT DEL nick"
-
-#, fuzzy
-msgid "DEL nick"
-msgstr "DEL <nick>."
-
-#, fuzzy
-msgid ""
-"EXCEPTION ADD adds the given host mask to the exception list.\n"
-"Note that nick!user@host and user@host masks are invalid!\n"
-"Only real host masks, such as box.host.dom and *.host.dom,\n"
-"are allowed because sessions limiting does not take nick or\n"
-"user names into account. limit must be a number greater than\n"
-"or equal to zero. This determines how many sessions this host\n"
-"may carry at a time. A value of zero means the host has an\n"
-"unlimited session limit. See the AKILL help for details about\n"
-"the format of the optional expiry parameter.\n"
-" \n"
-"EXCEPTION DEL removes the given mask from the exception list.\n"
-" \n"
-"EXCEPTION LIST and EXCEPTION VIEW show all current\n"
-"sessions if the optional mask is given, the list is limited\n"
-"to those sessions matching the mask. The difference is that\n"
-"EXCEPTION VIEW is more verbose, displaying the name of the\n"
-"person who added the exception, its session limit, reason,\n"
-"host mask and the expiry date and time.\n"
-" \n"
-"Note that a connecting client will \"use\" the first exception\n"
-"their host matches."
-msgstr ""
-"Sintaxis: EXCEPTION ADD [+expiració] mascara límit raó\n"
-" EXCEPTION DEL {mascara | llista}\n"
-" EXCEPTION MOVE numero posició\n"
-" EXCEPTION LIST [mascara | llista]\n"
-" EXCEPTION VIEW [mascara | llista]\n"
-"\n"
-"Permet als administradors de serveis manipular la llista\n"
-"de hosts que tenen un límit de sessió específic - permetent \n"
-"a certes màquines, com servidors de shells, mantenir un nombre més alt \n"
-"de clients al mateix temps. En quant un host arribi al seu límit\n"
-"de sessions, tots els clients intentant conectarse desde aquest \n"
-"host seran expulsats. Abans de expulsar usuaris, aquests son\n"
-"notificats a traves de un /NOTICE del %s amb ajuda sobre\n"
-"el límit de sessió. El contingut d'aquest notice es un establiment\n"
-"de configuració.\n"
-"\n"
-"EXCEPTION ADD afegeix la mascara de host donada a la llista de\n"
-"excepcion. Teniu en compte que les mascares nick!usuari@host\n"
-"i usuari@host son invalides. Nomès mascares reals com\n"
-"irc.aujac.org i *.aujac.org, son permessas ja que el\n"
-"límit de sessions no compta nicks o noms d'usuari.\n"
-"Límit ha de ser un numero mes gran o igual a zero. Això determina\n"
-"quantes sessions el host pot tenir en un cert temps. El valor\n"
-"zero significa que el host no te límits de sessió. Veure la ajuda\n"
-"sobre AKILL per a més detalls sobre el parametre opcional\n"
-"expiració.\n"
-"EXCEPTION DEL remou la mascara donada de la llista d'excepcions.\n"
-"EXCEPTION MOVE mou l'excepció numero a posició. Les\n"
-"excepcions entremig seran mogudes amunt o avall per a omplir l'espai.\n"
-"\n"
-"EXCEPTION LIST i EXCEPTION VIEW mostra totes les\n"
-"excepcions actuals; si la mascara opcional es donada, la llista es\n"
-"limitada a les excepcions similars a la mascara. La diferencia\n"
-"es que EXCEPTION VIEW es mes verbal, mostrant el nom de la\n"
-"persona que va afegir l'excepció, el límit d'excepció, raó,\n"
-"mascara de hosts i la data i hora d'expiració. \n"
-"\n"
-"Pren nota de que un client conectant-se \"utilitzara\" la primera\n"
-"excepció a la que el host s'assembli. Llargues llistes d'excepcions\n"
-"i mascares que s'assemblin a moltes mascares possiblement contribueixin\n"
-"al mal rendiment dels serveis.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-msgid ""
-"SET kills all operators from the given\n"
-"server and prevents operators from opering\n"
-"up on the given server. REVOKE removes this\n"
-"restriction."
-msgstr ""
-
-#, c-format
-msgid ""
-"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
-"information."
-msgstr ""
-
-#, c-format
-msgid "[auto-memo] The memo you sent to %s has been viewed."
-msgstr "[auto-memo] The memo you sent to %s has been viewed."
-
-#, fuzzy
-msgid "[target] [password]"
-msgstr "GROUP grup clau"
-
-msgid "address"
-msgstr ""
-
-#, fuzzy
-msgid "botname {ON|OFF}"
-msgstr "SASET nickname AUTOOP {ON | OFF}"
-
-#, fuzzy
-msgid "channel"
-msgstr "DROP canal"
-
-#, fuzzy
-msgid "channel bantype"
-msgstr "ACT canal text"
-
-#, fuzzy
-msgid "channel channel"
-msgstr "TOPIC canal [tòpic]"
-
-#, fuzzy
-msgid "channel command method [status]"
-msgstr "KICK canal opció {ON|OFF} [establiments]"
-
-#, fuzzy
-msgid "channel mask [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel modes"
-msgstr "MODE canal Modes"
-
-#, fuzzy
-msgid "channel nick"
-msgstr "UNBAN canal [nick]"
-
-#, fuzzy
-msgid "channel nick [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel target [what]"
-msgstr "CLEAR canal Modes-a-netegar"
-
-#, fuzzy
-msgid "channel text"
-msgstr "ACT canal text"
-
-#, fuzzy
-msgid "channel time"
-msgstr "ACT canal text"
-
-#, fuzzy
-msgid "channel user reason"
-msgstr "KICK canal usuari raó"
-
-#, fuzzy
-msgid "channel what"
-msgstr "TOPIC canal [tòpic]"
-
-#, fuzzy
-msgid "channel ADD mask"
-msgstr "MODE canal Modes"
-
-msgid "channel ADD mask level"
-msgstr ""
-
-#, fuzzy
-msgid "channel ADD message"
-msgstr "MODE canal Modes"
-
-msgid "channel ADD word [SINGLE | START | END]"
-msgstr ""
-
-#, fuzzy
-msgid "channel ADD {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel APPEND topic"
-msgstr "TOPIC canal [tòpic]"
-
-#, fuzzy
-msgid "channel CLEAR"
-msgstr "DROP canal"
-
-#, fuzzy
-msgid "channel CLEAR [what]"
-msgstr "TOPIC canal [tòpic]"
-
-#, fuzzy
-msgid "channel CLEAR [ALL]"
-msgstr "DROP canal"
-
-#, fuzzy
-msgid "channel DEL num"
-msgstr "MODE canal Modes"
-
-#, fuzzy
-msgid "channel DEL {mask | entry-num | list}"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-#, fuzzy
-msgid "channel DEL {nick | mask | entry-num | list}"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | instància]"
-
-#, fuzzy
-msgid "channel DEL {word | entry-num | list}"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-msgid "channel ENFORCE"
-msgstr ""
-
-#, fuzzy
-msgid "channel LIST"
-msgstr "DROP canal"
-
-#, fuzzy
-msgid "channel LIST [mask | entry-num | list]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | instància]"
-
-#, fuzzy
-msgid "channel LIST [mask | list]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | instància]"
-
-msgid "channel LIST [mask | +flags]"
-msgstr ""
-
-#, fuzzy
-msgid "channel LOCK {ADD|DEL|SET|LIST} [what]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | instància]"
-
-#, fuzzy
-msgid "channel RESET"
-msgstr "SET canal GREET {ON|OFF}"
-
-#, fuzzy
-msgid "channel SET modes"
-msgstr "MODE canal Modes"
-
-msgid "channel SET type level"
-msgstr ""
-
-#, fuzzy
-msgid "channel VIEW [mask | entry-num | list]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | instància]"
-
-#, fuzzy
-msgid "channel VIEW [mask | list]"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-#, fuzzy
-msgid "channel [description]"
-msgstr "REGISTER canal descripció"
-
-#, fuzzy
-msgid "channel [nick]"
-msgstr "UNBAN canal [nick]"
-
-#, fuzzy
-msgid "channel [parameters]"
-msgstr "CLEAR canal Modes-a-netegar"
-
-#, fuzzy
-msgid "channel [user]"
-msgstr "UNBAN canal [nick]"
-
-#, fuzzy
-msgid "channel [+expiry] [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [+expiry] {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [MODIFY] mask changes"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [SET] [topic]"
-msgstr "TOPIC canal [tòpic]"
-
-#, fuzzy
-msgid "channel [UNLOCK|LOCK]"
-msgstr "DROP canal"
-
-#, fuzzy
-msgid "channel {ON|OFF}"
-msgstr "SET canal XOP {ON | OFF}"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [ln [secs]]]"
-msgstr "KICK canal opció {ON|OFF} [establiments]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [min [percent]]]"
-msgstr "KICK canal opció {ON|OFF} [establiments]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [num]]"
-msgstr "KICK canal opció {ON|OFF} [establiments]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb]"
-msgstr "SET canal XOP {ON | OFF}"
-
-msgid "channel {DIS | DISABLE} type"
-msgstr ""
-
-#, fuzzy
-msgid "channel {ON | LEVEL | OFF}"
-msgstr "SET canal SIGNKICK {ON | LEVEL | OFF}"
-
-#, fuzzy
-msgid "channel {ON | OFF}"
-msgstr "SET canal XOP {ON | OFF}"
-
-msgid "email"
-msgstr ""
-
-#, fuzzy
-msgid "language"
-msgstr "SET LANGUAGE numero"
-
-#, fuzzy
-msgid "memo-text"
-msgstr "STAFF memo-text"
-
-#, fuzzy
-msgid "message"
-msgstr "GLOBAL missatge"
-
-msgid "modname"
-msgstr ""
-
-msgid "new-display"
-msgstr ""
-
-#, fuzzy
-msgid "new-password"
-msgstr "GROUP grup clau"
-
-#, fuzzy
-msgid "nick"
-msgstr "INFO nick"
-
-#, fuzzy
-msgid "nick channel"
-msgstr "CANCEL {nick | canal}"
-
-#, fuzzy
-msgid "nick channel [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "nick flags"
-msgstr "OLINE nick flags"
-
-#, fuzzy
-msgid "nick hostmask"
-msgstr "SET <nick> <hostmask>."
-
-#, fuzzy
-msgid "nick newnick"
-msgstr "SVSNICK nick newnick "
-
-#, fuzzy
-msgid "nick [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "nickname"
-msgstr "CHECK nickname"
-
-#, fuzzy
-msgid "nickname address"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "nickname email"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "nickname language"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "nickname message"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "nickname new-display"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "nickname new-password"
-msgstr "GHOST nickname [clau]"
-
-#, fuzzy
-msgid "nickname [parameter]"
-msgstr "GHOST nickname [clau]"
-
-#, fuzzy
-msgid "nickname [password]"
-msgstr "GHOST nickname [clau]"
-
-#, fuzzy
-msgid "nickname [+expiry] [reason]"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-msgstr "SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-
-#, fuzzy
-msgid "nickname {ON | OFF}"
-msgstr "SASET nickname AUTOOP {ON | OFF}"
-
-#, fuzzy
-msgid "nickname {ON | QUICK | IMMED | OFF}"
-msgstr "SASET nickname KILL {ON | QUICK | IMMED | OFF}"
-
-#, fuzzy
-msgid "option (channel | bot) settings"
-msgstr "SET canal Opció establiments"
-
-#, fuzzy
-msgid "option channel parameters"
-msgstr "SEND {nick | canal} text"
-
-#, fuzzy
-msgid "option channel {ON|OFF} [settings]"
-msgstr "KICK canal opció {ON|OFF} [establiments]"
-
-msgid "option nickname parameters"
-msgstr ""
-
-#, fuzzy
-msgid "option parameters"
-msgstr "SET Opció estabilment"
-
-#, fuzzy
-msgid "option setting"
-msgstr "SET Opció estabilment"
-
-#, fuzzy
-msgid "passcode"
-msgstr "REGISTER clau email"
-
-#, fuzzy
-msgid "password"
-msgstr "GROUP grup clau"
-
-#, fuzzy
-msgid "password [email]"
-msgstr "REGISTER clau email"
-
-#, fuzzy
-msgid "password email"
-msgstr "REGISTER clau email"
-
-#, fuzzy
-msgid "pattern [SUSPENDED] [NOEXPIRE]"
-msgstr "LIST patro [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-
-#, fuzzy
-msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-msgstr "LIST patro [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-
-#, fuzzy
-msgid "server [reason]"
-msgstr "JUPE nom-del-servidor [raó]"
-
-#, fuzzy
-msgid "user modes"
-msgstr "MODE canal Modes"
-
-#, fuzzy
-msgid "user [reason]"
-msgstr "JUPE nom-del-servidor [raó]"
-
-#, fuzzy
-msgid ""
-" \n"
-"SNLINE ADD adds the given realname mask to the SNLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SNLINE which does not expire, use +0. If the\n"
-"realname mask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current SNLINE default expiry time can be found with the\n"
-"STATS AKILL command.\n"
-" \n"
-"Note: because the realname mask may contain spaces, the\n"
-"separator between it and the reason is a colon."
-msgstr ""
-"Sintàxi: AKILL ADD [+expiració] mascara raó\n"
-" AKILL DEL {mascara | nom | llista}\n"
-" AKILL LIST [mascara | llista]\n"
-" AKILL VIEW [mascara | llista]\n"
-" AKILL CLEAR\n"
-"\n"
-"Permet als operadors de serveis manipular la llista de\n"
-"AKILLS. Si un usuari coincideix amb una mascara en la\n"
-"llista de AKILLS i s'esta intentant connectar, els serveis enviaran\n"
-"un KILL a aquest usuari i, en tipus de servidors soportats,\n"
-"notificara a tots els servidors que afegeixin un ban (linea K)\n"
-"per la mascara de l'usuari.\n"
-"\n"
-"AKILL ADD afegeix la mascara usuari@host especificada a la llista\n"
-"de AKILLS per la raó especificada (que HA DE SER especificada).\n"
-"expiració es especificada com un sencer seguit de\n"
-" d (dies), h (hores), o m (minuts). Combinacions (com\n"
-"1h30m) no estan permesses. Si un especificador d'unitats no\n"
-"es inclòs, per defecte seran dies (o sigui +30 nomès\n"
-"significa 30 dies). Per afegir un AKILL que no caduqui, utilitza +0.\n"
-"Si la mascara a afegir comença amb un +, s'ha d'especificar\n"
-"un temps d'expiració. El temps d'expiració per defecte actual de AKILLS\n"
-"pot ser consultat amb la comanda STATS AKILL.\n"
-"\n"
-"La comanda AKILL DEL esborra la mascara especificada de la llista\n"
-"d'AKILLS si esta present. Si s'especifica una llista de noms,\n"
-"aquestes instàncies son esborrades. (Veure l'exemple per LIST \n"
-"especificat més endavant.)\n"
-"\n"
-"La comanda AKILL LIST mostra la llista d'AKILLS. \n"
-"Si s'especifica una mascara, nomès les instàncies coincidents\n"
-"amb la mascara són mostrades. Si s'especifica una llista de noms,\n"
-"nomès aquestes instàncies son mostrades; per exemple:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" Llista les instàncies de AKILL enumerades de 2 a 5 i de 7 \n"
-" a 9.\n"
-" \n"
-"AKILL VIEW es una versió més verbal d'AKILL LIST, i \n"
-"mostrara qui va afegir un AKILL, la data en que va ser afegit,\n"
-"i quan caducara, així com tambe la mascara usuari@host\n"
-"i la raó.\n"
-"\n"
-"AKILL CLEAR neteja totes les instàncies de la llista d'AKILLS.\n"
-"\n"
-"Limitat a operadors de serveis."
-
-#, fuzzy
-msgid ""
-" \n"
-"SQLINE ADD adds the given (nick's) mask to the SQLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SQLINE which does not expire, use +0.\n"
-"If the mask to be added starts with a +, an expiry time\n"
-"must be given, even if it is the same as the default. The\n"
-"current SQLINE default expiry time can be found with the\n"
-"STATS AKILL command."
-msgstr ""
-"Sintàxi: AKILL ADD [+expiració] mascara raó\n"
-" AKILL DEL {mascara | nom | llista}\n"
-" AKILL LIST [mascara | llista]\n"
-" AKILL VIEW [mascara | llista]\n"
-" AKILL CLEAR\n"
-"\n"
-"Permet als operadors de serveis manipular la llista de\n"
-"AKILLS. Si un usuari coincideix amb una mascara en la\n"
-"llista de AKILLS i s'esta intentant connectar, els serveis enviaran\n"
-"un KILL a aquest usuari i, en tipus de servidors soportats,\n"
-"notificara a tots els servidors que afegeixin un ban (linea K)\n"
-"per la mascara de l'usuari.\n"
-"\n"
-"AKILL ADD afegeix la mascara usuari@host especificada a la llista\n"
-"de AKILLS per la raó especificada (que HA DE SER especificada).\n"
-"expiració es especificada com un sencer seguit de\n"
-" d (dies), h (hores), o m (minuts). Combinacions (com\n"
-"1h30m) no estan permesses. Si un especificador d'unitats no\n"
-"es inclòs, per defecte seran dies (o sigui +30 nomès\n"
-"significa 30 dies). Per afegir un AKILL que no caduqui, utilitza +0.\n"
-"Si la mascara a afegir comença amb un +, s'ha d'especificar\n"
-"un temps d'expiració. El temps d'expiració per defecte actual de AKILLS\n"
-"pot ser consultat amb la comanda STATS AKILL.\n"
-"\n"
-"La comanda AKILL DEL esborra la mascara especificada de la llista\n"
-"d'AKILLS si esta present. Si s'especifica una llista de noms,\n"
-"aquestes instàncies son esborrades. (Veure l'exemple per LIST \n"
-"especificat més endavant.)\n"
-"\n"
-"La comanda AKILL LIST mostra la llista d'AKILLS. \n"
-"Si s'especifica una mascara, nomès les instàncies coincidents\n"
-"amb la mascara són mostrades. Si s'especifica una llista de noms,\n"
-"nomès aquestes instàncies son mostrades; per exemple:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" Llista les instàncies de AKILL enumerades de 2 a 5 i de 7 \n"
-" a 9.\n"
-" \n"
-"AKILL VIEW es una versió més verbal d'AKILL LIST, i \n"
-"mostrara qui va afegir un AKILL, la data en que va ser afegit,\n"
-"i quan caducara, així com tambe la mascara usuari@host\n"
-"i la raó.\n"
-"\n"
-"AKILL CLEAR neteja totes les instàncies de la llista d'AKILLS.\n"
-"\n"
-"Limitat a operadors de serveis."
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Accounts that are not used anymore are subject to\n"
-"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
-msgstr ""
-"Nicknames en desus estan subjectes a l'expiració\n"
-"automatica, en altres paraules, seran esborrats després\n"
-"de %d dies."
-
-#, fuzzy
-msgid ""
-" \n"
-"Available commands are:"
-msgstr "No existeix ajuda per %s."
-
-#, c-format
-msgid ""
-" \n"
-"Bot will join a channel whenever there is at least\n"
-"%d user(s) on it."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Enables or disables fantasy mode on a channel.\n"
-"When it is enabled, users will be able to use\n"
-"fantasy commands on a channel when prefixed\n"
-"with one of the following fantasy characters: %s\n"
-" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
-msgstr ""
-"Sintàxi: SET canal FANTASY {ON|OFF}\n"
-"\n"
-"Habilita o deshabilita el mode de fantasia\n"
-"en un canal. En habilitar-lo, els usuaris podran\n"
-"utilitzar les comandes !op, !deop, !voice, !devoice,\n"
-"!kick, !kb, !unban, !seen en un canal (investiga\n"
-"com utilitzar-los; intenta amb o sense nick per cadascú\n"
-"i amb raó per a alguns?).\n"
-"\n"
-"Cal dir que els usuaris que desitgin utilitzar comandes\n"
-"de fantasia HAN DE DISPOSSAR del nivell necessari\n"
-"pel nivell FANTASIA i altres depenent\n"
-"de la comanda si es requereix (per exemple, per a\n"
-"utilitzar !op, l'usuari ha de tenir suficient\n"
-"accés pel nivell OPDEOP)."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables greet mode on a channel.\n"
-"When it is enabled, the bot will display greet\n"
-"messages of users joining the channel, provided\n"
-"they have enough access to the channel."
-msgstr ""
-"Sintàxi: SET canal GREET {ON|OFF}\n"
-"\n"
-"Habilita o deshabilita el mode de asludo en\n"
-"un canal. En habilitar-lo, el bot mostrara els\n"
-"missatges dels usuaris que entrin al canal,\n"
-"sempre i quan tinguin el suficient accés\n"
-"al canal."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables ops protection mode on a channel.\n"
-"When it is enabled, ops won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
-msgstr ""
-"Sintàxi: SET canal DONTKICKOPS {ON|OFF}\n"
-"\n"
-"Habilita o deshabilita el mode de protecció d'ops\n"
-"en un canal. En habilitar-lo, ops no seran\n"
-"kickejats pel bot, encara que no concideixen amb\n"
-"el nivell NOKICK."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables voices protection mode on a channel.\n"
-"When it is enabled, voices won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
-msgstr ""
-"Sintàxi: SET canal DONTKICKVOICES {ON|OFF}\n"
-"\n"
-"Habilita o deshabilita el mode de protecció de voices\n"
-"en un canal. En hbilitarlo, voices no seran\n"
-"kickejatos pel bot, encara que no coincideixin amb\n"
-"el nivell NOKICK."
-
-#, c-format
-msgid ""
-" \n"
-"Fantasy commands may be prefixed with one of the following characters: %s\n"
-msgstr ""
-
-msgid ""
-" \n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Note that any channel which is not used for %d days\n"
-"(i.e. which no user on the channel's access list enters\n"
-"for that period of time) will be automatically dropped."
-msgstr ""
-"Tingues en compte que qualsevol canal que no sigui utilitzat durant\n"
-"%d dies (al qual cap usuari a la llista d'accés\n"
-"del canal entri en aquest periode de temps) sera\n"
-"automaticament eliminat."
-
-#, c-format
-msgid ""
-" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-msgstr ""
-
-#, fuzzy
-msgid ""
-" \n"
-"Services Operators can also drop any nickname without needing\n"
-"to identify for the nick, and may view the access list for\n"
-"any nickname."
-msgstr ""
-"Administradors de serveis poden també eliminar qualsevol\n"
-"nickname sense tenir que identificar-se pel nick i poden\n"
-"veure la llista d'accés per qualsevol nickname\n"
-"(/msg %s ACCESS LIST nick)."
-
-#, fuzzy
-msgid ""
-" \n"
-"Services Operators can also, depending on their access drop\n"
-"any channel, view (and modify) the access, levels and akick\n"
-"lists and settings for any channel."
-msgstr ""
-" \n"
-"Les següents comandes estan disponibles per a administradors\n"
-"de serveis:\n"
-"\n"
-" STATUS Retorna el nivell d'accés actual d'un\n"
-" usuari en un canal\n"
-" CLIST llista tots els canals en els que l'usuari\n"
-" sigui fundador\n"
-"\n"
-"Administradors de serveis també poden eliminar un canal\n"
-"sense haver d'identificar-se per mitjà d'una clau, i poden\n"
-"Veure l'accés, AKICK, i paràmetres de les llistes de nivells per a\n"
-"qualsevol canal."
-
-msgid ""
-" \n"
-"Sets the time bot bans expire in. If enabled, any bans placed by\n"
-"bots, such as flood kicker, badwords kicker, etc. will automatically\n"
-"be removed after the given time. Set to 0 to disable bans from\n"
-"automatically expiring."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"The %s ADD command adds the given nickname to the\n"
-"%s list.\n"
-" \n"
-"The %s DEL command removes the given nick from the\n"
-"%s list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The %s LIST command displays the %s list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" %s #channel LIST 2-5,7-9\n"
-" Lists %s entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The %s CLEAR command clears all entries of the\n"
-"%s list."
-msgstr ""
-"Sintàxi: HOP canal ADD nick\n"
-" HOP canal DEL {nick | instancia | llista}\n"
-" HOP canal LIST [mascara | llista]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Manté la llista HOP (HalfOP) per a un canal. La llista\n"
-"HOP li dóna a l'usuari el dret de ser automàticament\n"
-"halfopejat en el teu canal.\n"
-"\n"
-"La comanda HOP ADD agrega al nickname donat a la llista\n"
-"HOP.\n"
-"\n"
-"La comanda HOP DEL esborra el nickname donat de la\n"
-"llista HOP. Si una llista d'instàncies és donada, aquestes\n"
-"instàncies són esborrades. (Veure l'exemple per a LIST més\n"
-"endevant.)\n"
-"\n"
-"La comanda HOP LIST mostra la llista HOP. Si una\n"
-"mascara amb comodí és donada, només les instàncies\n"
-"que concordin amb la mascara són mostrades. Si una llista de\n"
-"instàncies és donada, només aquestes instàncies són mostrades;\n"
-"per exemple:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Mostra instàncies de HOP enumerades 2 a 5 y\n"
-" 7 a 9.\n"
-"\n"
-"La comanda HOP CLEAR neteja totes les instàncies de la\n"
-"llista HOP.\n"
-"\n"
-"Les comandes HOP ADD i HOP DEL estan limitades a\n"
-"AOPs o superior, mentre que la comanda HOP CLEAR\n"
-"sols pot ser utilitzada per el fundador del canal.\n"
-"\n"
-"Aquesta comanda pot haber estat deshabilitada per al teu canal.\n"
-"Si aquest és el cas, has de fer servir la llista d'accés. Veure\n"
-"/msg %s HELP ACCESS per a informació sobre la llista\n"
-"d'accés i /msg %s HELP SET XOP per a saber com canviar\n"
-"entre la llista d'accés i el sistema de llistes xOP."
-
-#, c-format
-msgid ""
-" \n"
-"The AKICK DEL command removes the given nick or mask\n"
-"from the AutoKick list. It does not, however, remove any\n"
-"bans placed by an AutoKick; those must be removed\n"
-"manually.\n"
-" \n"
-"The AKICK LIST command displays the AutoKick list, or\n"
-"optionally only those AutoKick entries which match the\n"
-"given mask.\n"
-" \n"
-"The AKICK VIEW command is a more verbose version of the\n"
-"AKICK LIST command.\n"
-" \n"
-"The AKICK ENFORCE command causes %s to enforce the\n"
-"current AKICK list by removing those users who match an\n"
-"AKICK mask.\n"
-" \n"
-"The AKICK CLEAR command clears all entries of the\n"
-"akick list."
-msgstr ""
-
-#, fuzzy
-msgid ""
-" \n"
-"The AKILL DEL command removes the given mask from the\n"
-"AKILL list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The AKILL LIST command displays the AKILL list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" AKILL LIST 2-5,7-9\n"
-" Lists AKILL entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"AKILL VIEW is a more verbose version of AKILL LIST, and\n"
-"will show who added an AKILL, the date it was added, and when\n"
-"it expires, as well as the user@host/ip mask and reason.\n"
-" \n"
-"AKILL CLEAR clears all entries of the AKILL list."
-msgstr ""
-"Sintàxi: HOP canal ADD nick\n"
-" HOP canal DEL {nick | instancia | llista}\n"
-" HOP canal LIST [mascara | llista]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Manté la llista HOP (HalfOP) per a un canal. La llista\n"
-"HOP li dóna a l'usuari el dret de ser automàticament\n"
-"halfopejat en el teu canal.\n"
-"\n"
-"La comanda HOP ADD agrega al nickname donat a la llista\n"
-"HOP.\n"
-"\n"
-"La comanda HOP DEL esborra el nickname donat de la\n"
-"llista HOP. Si una llista d'instàncies és donada, aquestes\n"
-"instàncies són esborrades. (Veure l'exemple per a LIST més\n"
-"endevant.)\n"
-"\n"
-"La comanda HOP LIST mostra la llista HOP. Si una\n"
-"mascara amb comodí és donada, només les instàncies\n"
-"que concordin amb la mascara són mostrades. Si una llista de\n"
-"instàncies és donada, només aquestes instàncies són mostrades;\n"
-"per exemple:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Mostra instàncies de HOP enumerades 2 a 5 y\n"
-" 7 a 9.\n"
-"\n"
-"La comanda HOP CLEAR neteja totes les instàncies de la\n"
-"llista HOP.\n"
-"\n"
-"Les comandes HOP ADD i HOP DEL estan limitades a\n"
-"AOPs o superior, mentre que la comanda HOP CLEAR\n"
-"sols pot ser utilitzada per el fundador del canal.\n"
-"\n"
-"Aquesta comanda pot haber estat deshabilitada per al teu canal.\n"
-"Si aquest és el cas, has de fer servir la llista d'accés. Veure\n"
-"/msg %s HELP ACCESS per a informació sobre la llista\n"
-"d'accés i /msg %s HELP SET XOP per a saber com canviar\n"
-"entre la llista d'accés i el sistema de llistes xOP."
-
-#, fuzzy
-msgid ""
-" \n"
-"The SNLINE DEL command removes the given mask from the\n"
-"SNLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SNLINE LIST command displays the SNLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SNLINE LIST 2-5,7-9\n"
-" Lists SNLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SNLINE VIEW is a more verbose version of SNLINE LIST, and\n"
-"will show who added an SNLINE, the date it was added, and when\n"
-"it expires, as well as the realname mask and reason.\n"
-" \n"
-"SNLINE CLEAR clears all entries of the SNLINE list."
-msgstr ""
-"Sintàxi: HOP canal ADD nick\n"
-" HOP canal DEL {nick | instancia | llista}\n"
-" HOP canal LIST [mascara | llista]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Manté la llista HOP (HalfOP) per a un canal. La llista\n"
-"HOP li dóna a l'usuari el dret de ser automàticament\n"
-"halfopejat en el teu canal.\n"
-"\n"
-"La comanda HOP ADD agrega al nickname donat a la llista\n"
-"HOP.\n"
-"\n"
-"La comanda HOP DEL esborra el nickname donat de la\n"
-"llista HOP. Si una llista d'instàncies és donada, aquestes\n"
-"instàncies són esborrades. (Veure l'exemple per a LIST més\n"
-"endevant.)\n"
-"\n"
-"La comanda HOP LIST mostra la llista HOP. Si una\n"
-"mascara amb comodí és donada, només les instàncies\n"
-"que concordin amb la mascara són mostrades. Si una llista de\n"
-"instàncies és donada, només aquestes instàncies són mostrades;\n"
-"per exemple:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Mostra instàncies de HOP enumerades 2 a 5 y\n"
-" 7 a 9.\n"
-"\n"
-"La comanda HOP CLEAR neteja totes les instàncies de la\n"
-"llista HOP.\n"
-"\n"
-"Les comandes HOP ADD i HOP DEL estan limitades a\n"
-"AOPs o superior, mentre que la comanda HOP CLEAR\n"
-"sols pot ser utilitzada per el fundador del canal.\n"
-"\n"
-"Aquesta comanda pot haber estat deshabilitada per al teu canal.\n"
-"Si aquest és el cas, has de fer servir la llista d'accés. Veure\n"
-"/msg %s HELP ACCESS per a informació sobre la llista\n"
-"d'accés i /msg %s HELP SET XOP per a saber com canviar\n"
-"entre la llista d'accés i el sistema de llistes xOP."
-
-#, fuzzy
-msgid ""
-" \n"
-"The SQLINE DEL command removes the given mask from the\n"
-"SQLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SQLINE LIST command displays the SQLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SQLINE LIST 2-5,7-9\n"
-" Lists SQLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SQLINE VIEW is a more verbose version of SQLINE LIST, and\n"
-"will show who added an SQLINE, the date it was added, and when\n"
-"it expires, as well as the mask and reason.\n"
-" \n"
-"SQLINE CLEAR clears all entries of the SQLINE list."
-msgstr ""
-"Sintàxi: HOP canal ADD nick\n"
-" HOP canal DEL {nick | instancia | llista}\n"
-" HOP canal LIST [mascara | llista]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Manté la llista HOP (HalfOP) per a un canal. La llista\n"
-"HOP li dóna a l'usuari el dret de ser automàticament\n"
-"halfopejat en el teu canal.\n"
-"\n"
-"La comanda HOP ADD agrega al nickname donat a la llista\n"
-"HOP.\n"
-"\n"
-"La comanda HOP DEL esborra el nickname donat de la\n"
-"llista HOP. Si una llista d'instàncies és donada, aquestes\n"
-"instàncies són esborrades. (Veure l'exemple per a LIST més\n"
-"endevant.)\n"
-"\n"
-"La comanda HOP LIST mostra la llista HOP. Si una\n"
-"mascara amb comodí és donada, només les instàncies\n"
-"que concordin amb la mascara són mostrades. Si una llista de\n"
-"instàncies és donada, només aquestes instàncies són mostrades;\n"
-"per exemple:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Mostra instàncies de HOP enumerades 2 a 5 y\n"
-" 7 a 9.\n"
-"\n"
-"La comanda HOP CLEAR neteja totes les instàncies de la\n"
-"llista HOP.\n"
-"\n"
-"Les comandes HOP ADD i HOP DEL estan limitades a\n"
-"AOPs o superior, mentre que la comanda HOP CLEAR\n"
-"sols pot ser utilitzada per el fundador del canal.\n"
-"\n"
-"Aquesta comanda pot haber estat deshabilitada per al teu canal.\n"
-"Si aquest és el cas, has de fer servir la llista d'accés. Veure\n"
-"/msg %s HELP ACCESS per a informació sobre la llista\n"
-"d'accés i /msg %s HELP SET XOP per a saber com canviar\n"
-"entre la llista d'accés i el sistema de llistes xOP."
-
-#, fuzzy
-msgid ""
-" \n"
-"This option makes a channel unassignable. If a bot\n"
-"is already assigned to the channel, it is unassigned\n"
-"automatically when you enable it."
-msgstr ""
-"Sintaxi: SET canal NOBOT {ON|OFF}\n"
-"\n"
-"Aquesta opció fa al canal no sigui assignable. Si un\n"
-"bot ja està assignat al canal, es desassignara\n"
-"automàticament quan habiliteu aquesta opció.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-" \n"
-"This option prevents a bot from being assigned to a\n"
-"channel by users that aren't IRC Operators."
-msgstr ""
-"Sintaxi: SET nick-del-bot PRIVATE {ON|OFF}\n"
-"\n"
-"Aquesta opció evita un bot de ser assignat\n"
-"a un canal per usuaris que no son operadors\n"
-"d'IRC.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, c-format
-msgid ""
-" \n"
-"Type %s%s HELP command for help on any of the\n"
-"above commands."
-msgstr ""
-
-#, c-format
-msgid " %s is online using this oper block."
-msgstr ""
-
-#, c-format
-msgid " Command %s on %s is linked to %s"
-msgstr ""
-
-#, fuzzy, c-format
-msgid " Providing service: %s"
-msgstr "Providing command: /msg %s %s"
-
-msgid " This oper is configured in the configuration file."
-msgstr ""
-
-#, c-format
-msgid " Loaded at: %p"
-msgstr ""
-
-#, c-format
-msgid " but %s mysteriously dematerialized."
-msgstr ""
-
-#, c-format
-msgid ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-
-#, fuzzy
-msgid "\"Jupiter\" a server"
-msgstr " JUPE \"Jupiter\" (Mart,Saturn....) un servidor"
-
-#, fuzzy, c-format
-msgid "%-8s %s"
-msgstr "%-20s %s@%s"
-
-#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
-
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr ""
-
-#, c-format
-msgid "%c is an unknown status mode."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%c%c is not locked on %s."
-msgstr "%s no es notificat per memos nous."
-
-#, fuzzy, c-format
-msgid "%c%c%s has been unlocked from %s."
-msgstr "Nick %s has been ungrouped from %s."
-
-#, fuzzy, c-format
-msgid "%d access entries from %s have been cloned to %s."
-msgstr "All vhost's in the group %s have been set to %s"
-
-#, c-format
-msgid "%d bots available."
-msgstr "%d bots disponibles."
-
-#, fuzzy, c-format
-msgid "%d modules loaded."
-msgstr "%d Modules loaded."
-
-#, fuzzy, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nicknames en el grup."
-
-#, c-format
-msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s %s list is empty."
-msgstr "La llista AOP de %s esta buida."
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban)"
-msgstr " Kicker per negretes : %s (%d kick(s) per a ban)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; %d lines in %ds)"
-msgstr " Kicker per flood : %s (%d kick(s) per a ban; %d linees en %ds)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; %d times)"
-msgstr " Kicker per repetició : %s (%d kick(s) per a ban; %d vegades)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; minimum %d/%d%%)"
-msgstr " Kicker per majuscules : %s (%d kick(s) per a ban; mínim %d/%d%%)"
-
-#, fuzzy, c-format
-msgid "%s (%d lines in %ds)"
-msgstr " %s (expires in %s)"
-
-#, c-format
-msgid "%s (%d times)"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was kicked from %s (\"%s\") %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was kicked from a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen changing nick from %s to %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen changing nick to %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen connecting %s ago (%s)%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen joining %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen joining a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen parting %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen parting a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s (minimum %d/%d%%)"
-msgstr " Caps kicker : %s (mínim %d/%d%%)"
-
-#, c-format
-msgid "%s access list is empty."
-msgstr "La llista d'accés de %s esta buida."
-
-#, fuzzy, c-format
-msgid "%s added to %s's auto join list."
-msgstr "%s afegit a la llista de kicks automàtics en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s already exists."
-msgstr "El bot %s ja existeix."
-
-#, c-format
-msgid "%s autokick list is empty."
-msgstr "La llista de kicks automàtics del canal %s esta buida."
-
-#, c-format
-msgid "%s bad words list is empty."
-msgstr "La llista de paraules malsonants de %s esta buida."
-
-#, fuzzy, c-format
-msgid "%s cannot be the successor on channel %s as they are the founder."
-msgstr "%s no pot ser el sucessor en el canal %s ja que n'es el fundador."
-
-#, c-format
-msgid "%s commands:"
-msgstr "%s commands:"
-
-#, c-format
-msgid "%s coverage is too wide; Please use a more specific mask."
-msgstr ""
-
-#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s actualment te %d memos, dels quals %d encara no han estat llegits."
-
-#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s actualment te %d memos, dels quals 1 encara no ha estat llegit."
-
-#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s actualment te %d memos."
-
-#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s actualment te %d memos, dels quals cap ha estat llegit."
-
-#, c-format
-msgid "%s currently has 1 memo, and it has not yet been read."
-msgstr "%s actualment te 1 memo i encara no ha estat llegit."
-
-#, c-format
-msgid "%s currently has 1 memo."
-msgstr "%s te 1 memo."
-
-#, c-format
-msgid "%s currently has no memos."
-msgstr "%s no te memos."
-
-#, fuzzy, c-format
-msgid "%s deleted from the %s forbid list."
-msgstr "%s esborrada de la llista de paraules malsonants de %s."
-
-#, fuzzy, c-format
-msgid "%s for %s set to %s."
-msgstr "vhost for %s set to %s."
-
-#, fuzzy, c-format
-msgid "%s for %s unset."
-msgstr "Sucessor de %s desabilitat."
-
-#, c-format
-msgid "%s had an invalid key specified, and was thus ignored."
-msgstr ""
-
-#, c-format
-msgid "%s has no memo limit."
-msgstr "%s no te límit per a memos."
-
-#, fuzzy, c-format
-msgid "%s has no memos."
-msgstr "%s no te límit per a memos."
-
-#, fuzzy, c-format
-msgid "%s has no new memos."
-msgstr "%s no te límit per a memos."
-
-#, c-format
-msgid "%s is %s"
-msgstr "%s es %s"
-
-#, fuzzy, c-format
-msgid "%s is a Services Operator of type %s."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy, c-format
-msgid "%s is a client on services."
-msgstr "%s Esta actualment online."
-
-#, fuzzy, c-format
-msgid "%s is a network service."
-msgstr "%s Esta actualment online."
-
-#, fuzzy, c-format
-msgid "%s is already covered by %s."
-msgstr "%s ja esta cobert per %s."
-
-#, fuzzy, c-format
-msgid "%s is already on %s's auto join list."
-msgstr "%s afegit a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "%s is an unconfirmed nickname."
-msgstr "Aquest nickname no caducara."
-
-#, c-format
-msgid ""
-"%s is another way to modify the channel access list, similar to\n"
-"the XOP and ACCESS methods."
-msgstr ""
-
-#, c-format
-msgid "%s is currently online."
-msgstr "%s Esta actualment online."
-
-#, c-format
-msgid "%s is disabled"
-msgstr "%s is disabled"
-
-#, c-format
-msgid "%s is enabled"
-msgstr "%s is enable"
-
-#, fuzzy, c-format
-msgid "%s is not a valid IP address."
-msgstr "%s no es un tipus de ban valid."
-
-#, fuzzy, c-format
-msgid "%s is not a valid command."
-msgstr "%s no es un tipus de ban valid."
-
-#, fuzzy, c-format
-msgid "%s is not a valid logging method."
-msgstr "%s no es un tipus de ban valid."
-
-#, c-format
-msgid "%s is not notified of new memos."
-msgstr "%s no es notificat per memos nous."
-
-#, c-format
-msgid "%s is notified of new memos at logon and when they arrive."
-msgstr ""
-"%s es notificat per memos nous quant es connecta i quant li són enviats."
-
-#, c-format
-msgid "%s is notified of new memos at logon."
-msgstr "%s es notificat de nous memos quant es connecta."
-
-#, c-format
-msgid "%s is notified when new memos arrive."
-msgstr "%s es notificat quant nous memos li són enviats."
-
-#, c-format
-msgid "%s is on the channel right now (as %s)!"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s is on the channel right now!"
-msgstr "%s inhabilitat(s) en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s list for %s"
-msgstr "Lllista d'accés per %s:"
-
-#, fuzzy, c-format
-msgid "%s list is empty."
-msgstr "La llista AOP de %s esta buida."
-
-#, fuzzy, c-format
-msgid "%s locked on %s."
-msgstr "%s no es notificat per memos nous."
-
-#, fuzzy, c-format
-msgid "%s not found."
-msgstr "%s no trobat a la llista AOP de %s."
-
-#, c-format
-msgid "%s settings:"
-msgstr ""
-
-#, c-format
-msgid "%s was last seen here %s ago."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s was not found on %s's auto join list."
-msgstr "%s no trobat a la llista de kicks automàtics en el canal %s."
-
-#, fuzzy, c-format
-msgid "%s was removed from %s's auto join list."
-msgstr "%s esborrat de la llista de kicks automàtics del canal %s."
-
-#, c-format
-msgid "%s will not send you any notification of memos."
-msgstr "%s no t'enviara cap notificació dels teus memos."
-
-#, c-format
-msgid "%s will now notify you of memos when they are sent to you."
-msgstr "%s ara te notificara dels teus memos quant se t'enviin."
-
-#, c-format
-msgid ""
-"%s will now notify you of memos when you log on and when they are sent to "
-"you."
-msgstr ""
-"%s ara et notificara dels teus memos quant et conectis i quant et siguin "
-"enviats."
-
-#, c-format
-msgid "%s will now notify you of memos when you log on or unset /AWAY."
-msgstr ""
-"%s ara et notificara dels teus memos quant et conectis o treguis el teu /"
-"AWAY."
-
-#, c-format
-msgid "%s!%s@%s (%s) added to the bot list."
-msgstr "%s!%s@%s (%s) afegit a la llista de bots."
-
-#, fuzzy, c-format
-msgid "%s's access list is empty."
-msgstr "La llista d'accés de %s esta buida."
-
-#, fuzzy, c-format
-msgid "%s's auto join list is empty."
-msgstr "La llista de kicks automàtics del canal %s esta buida."
-
-#, fuzzy, c-format
-msgid "%s's auto join list:"
-msgstr " AKICK Manté la llista d'AutoKick"
-
-#, fuzzy, c-format
-msgid "%s's certificate list is empty."
-msgstr "Your access list is empty."
-
-#, c-format
-msgid "%s's memo limit is %d, and may not be changed."
-msgstr "El límit de memos per a %s es %d, i no pot ser canviat."
-
-#, c-format
-msgid "%s's memo limit is %d."
-msgstr "El límit de memos per a %s es %d."
-
-#, c-format
-msgid "(%s ago)"
-msgstr ""
-
-#, c-format
-msgid "(%s from now)"
-msgstr ""
-
-msgid "(Split)"
-msgstr ""
-
-#, c-format
-msgid "(by %s on %s) %s"
-msgstr ""
-
-#, fuzzy
-msgid "(disabled)"
-msgstr "%s is enable"
-
-msgid "(founder only)"
-msgstr ""
-
-msgid "(now)"
-msgstr ""
-
-msgid "* AKILL any new clients connecting"
-msgstr "* AKILL any new clients connecting"
-
-#, fuzzy, c-format
-msgid "* Force channel modes (%s) to be set on all channels"
-msgstr "* Force Chan Modes (%s) to be set on all channels"
-
-#, fuzzy
-msgid "* Ignore non-opers with a message"
-msgstr "* Ignore any non-opers with message"
-
-#, fuzzy
-msgid "* Kill any new clients connecting"
-msgstr "* Kill any NEW clients connecting"
-
-#, fuzzy
-msgid "* No mode lock changes"
-msgstr "* No MLOCK changes"
-
-msgid "* No new channel registrations"
-msgstr "* No new channel registrations"
-
-msgid "* No new memos sent"
-msgstr "* No new memos sent"
-
-msgid "* No new nick registrations"
-msgstr "* No new nick registrations"
-
-msgid "* Silently ignore non-opers"
-msgstr "* Silently ignore non-opers"
-
-#, c-format
-msgid "* Use the reduced session limit of %d"
-msgstr "* Use the reduced session limit of %d"
-
-#, c-format
-msgid ", but %s mysteriously dematerialized."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ". %s is still online."
-msgstr "%s Esta actualment online."
-
-msgid "<unknown>"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"A confirmation e-mail has been sent to %s. Follow the instructions in it to "
-"change your e-mail address."
-msgstr ""
-"A passcode has been sent to %s, please type /msg %s confirm <passcode> to "
-"complete registration"
-
-msgid "A massmemo has been sent to all registered users."
-msgstr "A massmemo has been sent to all registered users."
-
-msgid ""
-"A memo informing the user will also be sent, which includes the reason for "
-"the rejection if supplied."
-msgstr ""
-
-msgid "A memo informing the user will also be sent."
-msgstr ""
-
-#, c-format
-msgid ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
-msgstr ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
-
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr ""
-
-msgid "A vHost must be in the format of a valid hostname."
-msgstr ""
-
-#, fuzzy
-msgid "ADD expiry {nick|mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-msgid "ADD oper type"
-msgstr ""
-
-#, fuzzy
-msgid "ADD target info"
-msgstr "GROUP grup clau"
-
-msgid "ADD text"
-msgstr ""
-
-#, fuzzy
-msgid "ADD [+expiry] mask limit reason"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-#, fuzzy
-msgid "ADD [nickname] channel [key]"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-#, fuzzy
-msgid "ADD [nickname] mask"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-#, fuzzy
-msgid "ADD [nickname] [fingerprint]"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "ADD [+expiry] mask reason"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-#, fuzzy
-msgid "ADD [+expiry] mask:reason"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-#, fuzzy
-msgid "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiry] entry reason"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-msgid "ADDIP server.name ip"
-msgstr ""
-
-msgid "ADDSERVER server.name [zone.name]"
-msgstr ""
-
-msgid "ADDZONE zone.name"
-msgstr ""
-
-#, c-format
-msgid "AKICK ENFORCE for %s complete; %d users were affected."
-msgstr "AKICK ENFORCE en %s completa; %d usuaris afectats."
-
-#, fuzzy
-msgid "AKILL all users on a specific channel"
-msgstr " CHANKILL AKILL all users on a specific channel"
-
-msgid "AKILL list is empty."
-msgstr "La llista de AKILLS esta buida."
-
-#, fuzzy
-msgid "AMSG kicker"
-msgstr " Kicker per majuscules : %s"
-
-#, fuzzy
-msgid "Access"
-msgstr "Lllista d'accés:"
-
-#, fuzzy
-msgid "Access denied."
-msgstr "Lllista d'accés:"
-
-#, fuzzy, c-format
-msgid "Access for %s on %s:"
-msgstr "Nivell d'accés per a %s en %s cambiada a %d."
-
-#, fuzzy, c-format
-msgid "Access level must be between %d and %d inclusive."
-msgstr "El nivell ha d'estar entre %d i %d inclosos."
-
-msgid "Access level must be non-zero."
-msgstr "El nivell de accés no pot ser zero."
-
-#, c-format
-msgid "Access level settings for channel %s:"
-msgstr "Opcions del nivell d'accés pel canal %s:"
-
-#, c-format
-msgid "Access levels for %s reset to defaults."
-msgstr "Nivells d'accés per a %s canviats als valors originals."
-
-#, fuzzy, c-format
-msgid "Access list for %s:"
-msgstr "Lllista d'accés per %s:"
-
-#, c-format
-msgid ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-msgstr ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-
-#, c-format
-msgid ""
-"Account %s has already reached the maximum number of simultaneous logins "
-"(%u)."
-msgstr ""
-
-#, fuzzy
-msgid "Activate security features"
-msgstr " SECURE Activa les opcions de seguretat de %s"
-
-msgid "Activate the requested vHost for the given nick."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Activates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see the vhost instead of your real host/IP address."
-msgstr ""
-"Syntax: ON\n"
-"Activates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see the vhost instead of your real IP address."
-
-#, fuzzy
-msgid "Activates your assigned vhost"
-msgstr " ON Activates your assigned vhost"
-
-msgid ""
-"Add or delete oper information for a given nick or channel.\n"
-"This will show to opers in the respective info command for\n"
-"the nick or channel."
-msgstr ""
-
-#, c-format
-msgid "Added IP %s to %s."
-msgstr ""
-
-#, c-format
-msgid "Added a forbid on %s of type %s to expire on %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Added info to %s."
-msgstr "Memo enviat a %s."
-
-#, fuzzy
-msgid "Added new logon news item."
-msgstr "Noves notícies d'entrada afegida (#%d)."
-
-#, fuzzy
-msgid "Added new oper news item."
-msgstr "Nueva noticia de oper anadida (#%d)."
-
-#, fuzzy
-msgid "Added new random news item."
-msgstr "Nova noticia a l'atzar afegida (#%d)."
-
-#, fuzzy, c-format
-msgid "Added server %s."
-msgstr "Uplink server: %s"
-
-#, c-format
-msgid "Added zone %s."
-msgstr ""
-
-msgid ""
-"Adding, deleting, or clearing entry messages requires the\n"
-"SET permission."
-msgstr ""
-
-msgid ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
-msgstr ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
-
-#, c-format
-msgid ""
-"Additionally, if fantasy is enabled fantasy commands\n"
-"can be executed by prefixing the command name with\n"
-"one of the following characters: %s"
-msgstr ""
-
-#, c-format
-msgid "All O:lines of %s have been reset."
-msgstr "Totes les linees O de %s han estat esborrades."
-
-#, fuzzy, c-format
-msgid "All akick entries from %s have been cloned to %s."
-msgstr "All vhost's in the group %s have been set to %s"
-
-#, fuzzy, c-format
-msgid "All available commands for %s:"
-msgstr "No existeix ajuda per %s."
-
-#, fuzzy, c-format
-msgid "All badword entries from %s have been cloned to %s."
-msgstr "All vhost's in the group %s have been set to %s"
-
-#, fuzzy, c-format
-msgid "All level entries from %s have been cloned into %s."
-msgstr "All vhost's in the group %s have been set to %s"
-
-msgid "All logon news items deleted."
-msgstr "Totes les notícies d'entrada esborrades."
-
-#, c-format
-msgid "All memos for channel %s have been deleted."
-msgstr "All memos for channel %s have been deleted."
-
-#, c-format
-msgid "All modes cleared on %s."
-msgstr ""
-
-msgid ""
-"All new accounts must be validated by an administrator. Please wait for your "
-"registration to be confirmed."
-msgstr ""
-
-msgid "All of your memos have been deleted."
-msgstr "Tots els teus memos han estat esborrats."
-
-msgid "All oper news items deleted."
-msgstr "Totes les notícies de oper esborrades."
-
-#, fuzzy, c-format
-msgid "All operators from %s have been removed."
-msgstr "Totes les linees O de %s han estat esborrades."
-
-msgid "All random news items deleted."
-msgstr "Totes les notícies al azar esborrades."
-
-#, fuzzy, c-format
-msgid "All settings from %s have been cloned to %s."
-msgstr "All vhost's in the group %s have been set to %s"
-
-#, fuzzy, c-format
-msgid "All user modes on %s have been synced."
-msgstr "Totes les linees O de %s han estat esborrades."
-
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s."
-msgstr "All vhost's in the group %s have been set to %s"
-
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "All vhost's in the group %s have been set to %s@%s"
-
-msgid "Allowed to (de)halfop him/herself"
-msgstr ""
-
-msgid "Allowed to (de)halfop users"
-msgstr ""
-
-msgid "Allowed to (de)op him/herself"
-msgstr ""
-
-msgid "Allowed to (de)op users"
-msgstr ""
-
-msgid "Allowed to (de)owner him/herself"
-msgstr ""
-
-msgid "Allowed to (de)owner users"
-msgstr ""
-
-msgid "Allowed to (de)protect him/herself"
-msgstr ""
-
-msgid "Allowed to (de)protect users"
-msgstr ""
-
-msgid "Allowed to (de)voice him/herself"
-msgstr ""
-
-msgid "Allowed to (de)voice users"
-msgstr ""
-
-msgid "Allowed to assign/unassign a bot"
-msgstr ""
-
-msgid "Allowed to ban users"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to change channel topics"
-msgstr "%s changed your usermodes."
-
-msgid "Allowed to get full INFO output"
-msgstr ""
-
-msgid "Allowed to issue commands restricted to channel founders"
-msgstr ""
-
-msgid "Allowed to modify channel badwords list"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to modify the access list"
-msgstr "%s esborrat de la llista d'accés de %s."
-
-msgid "Allowed to read channel memos"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to set channel settings"
-msgstr "* No new channel registrations"
-
-msgid "Allowed to unban users"
-msgstr ""
-
-msgid "Allowed to use GETKEY command"
-msgstr ""
-
-msgid "Allowed to use SAY and ACT commands"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to use fantasy commands"
-msgstr " PEACE Regula l'ús de comandes critiques"
-
-#, fuzzy
-msgid "Allowed to use the AKICK command"
-msgstr "You cannot use this command."
-
-msgid "Allowed to use the INVITE command"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to use the KICK command"
-msgstr "You cannot use this command."
-
-#, fuzzy
-msgid "Allowed to use the MODE command"
-msgstr "You cannot use this command."
-
-#, fuzzy
-msgid "Allowed to view the access list"
-msgstr "%s esborrat de la llista d'accés de %s."
-
-#, fuzzy, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
-msgstr ""
-"Sintàxi: GLOBAL missatge\n"
-"\n"
-"Permet als Administrators a enviar missatges als usuaris de\n"
-"la xarxa. El missatge sera enviat desde el nick %s."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to change modes for any channel.\n"
-"Parameters are the same as for the standard /MODE command.\n"
-"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
-"If CLEAR ALL is given then all modes, including user status, is removed."
-msgstr ""
-"Sintàxi: MODE canal Modes\n"
-"\n"
-"Permet als operadors de serveis establir modes de canal\n"
-"per a qualsevol canal. Els parametres son els mateixos que per la\n"
-"comando estandart /MODE.\n"
-"\n"
-"Limitat a operadors de serveis."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to change modes for any user.\n"
-"Parameters are the same as for the standard /MODE command."
-msgstr ""
-"Sintàxi: MODE canal Modes\n"
-"\n"
-"Permet als operadors de serveis establir modes de canal\n"
-"per a qualsevol canal. Els parametres son els mateixos que per la\n"
-"comando estandart /MODE.\n"
-"\n"
-"Limitat a operadors de serveis."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to create, modify, and delete\n"
-"bots that users will be able to use on their own\n"
-"channels.\n"
-" \n"
-"BOT ADD adds a bot with the given nickname, username,\n"
-"hostname and realname. Since no integrity checks are done\n"
-"for these settings, be really careful.\n"
-" \n"
-"BOT CHANGE allows you to change the nickname, username, hostname\n"
-"or realname of a bot without deleting it (and\n"
-"all the data associated with it).\n"
-" \n"
-"BOT DEL removes the given bot from the bot list.\n"
-" \n"
-"Note: You cannot create a bot with a nick that is\n"
-"currently registered. If an unregistered user is currently\n"
-"using the nick, they will be killed."
-msgstr ""
-"Sintaxi: BOT ADD nick usuari host real\n"
-" BOT CHANGE nick-ant nick-nue [usuari [host [real]]]\n"
-" BOT DEL nick\n"
-"\n"
-"Permet als administradors de serveis crear, modificar\n"
-"i esborrar bots que usuaris podran usar en els seus propis\n"
-"canals.\n"
-"\n"
-"BOT ADD afegeix un bot con el nickname, usuari, host\n"
-"i nombre reial donats. Ja que no es fan comprovacions \n"
-"d'integritat per aquests parametres, tingues molta cura.\n"
-"BOT CHANGE permet cambiar el nickname, usuari, host\n"
-"o nom real d'un bot sense tenir que esborrar-lo (i la\n"
-"informació associada a ell).\n"
-"BOT DEL esborra el bot donat de la llista de bots.\n"
-"\n"
-"Nota: Si fas un bot amb un nick ja enregistrat,\n"
-"sera eliminat. A més, si un usuari està actualment\n"
-"usant el nick, serà killejat."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Syntax: OLINE user flags\n"
-"\n"
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes,\n"
-"h for hours and d for days.\n"
-"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format nick!user@host,\n"
-"everything else will be considered a nick. Wildcards are permitted.\n"
-" \n"
-"Ignores will not be enforced on IRC Operators."
-msgstr ""
-"Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask]\n"
-"\n"
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes, \n"
-"h for hours and d for days. \n"
-"Combinations of these units are not permitted. To make\n"
-"Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format user@host\n"
-"or nick!user@host, everything else will be considered a nick.\n"
-"Wildcards are permitted.\n"
-"\n"
-"Ignores will not be enforced on IRC Operators."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
-"will issue a KILL for that user and, on supported server\n"
-"types, will instruct all servers to add a ban for the mask\n"
-"which the user matched.\n"
-" \n"
-"AKILL ADD adds the given mask to the AKILL\n"
-"list for the given reason, which must be given.\n"
-"Mask should be in the format of nick!user@host#real name,\n"
-"though all that is required is user@host. If a real name is specified,\n"
-"the reason must be prepended with a :.\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an AKILL which does not expire, use +0. If the\n"
-"usermask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current AKILL default expiry time can be found with the\n"
-"STATS AKILL command."
-msgstr ""
-"Sintàxi: AKILL ADD [+expiració] mascara raó\n"
-" AKILL DEL {mascara | nom | llista}\n"
-" AKILL LIST [mascara | llista]\n"
-" AKILL VIEW [mascara | llista]\n"
-" AKILL CLEAR\n"
-"\n"
-"Permet als operadors de serveis manipular la llista de\n"
-"AKILLS. Si un usuari coincideix amb una mascara en la\n"
-"llista de AKILLS i s'esta intentant connectar, els serveis enviaran\n"
-"un KILL a aquest usuari i, en tipus de servidors soportats,\n"
-"notificara a tots els servidors que afegeixin un ban (linea K)\n"
-"per la mascara de l'usuari.\n"
-"\n"
-"AKILL ADD afegeix la mascara usuari@host especificada a la llista\n"
-"de AKILLS per la raó especificada (que HA DE SER especificada).\n"
-"expiració es especificada com un sencer seguit de\n"
-" d (dies), h (hores), o m (minuts). Combinacions (com\n"
-"1h30m) no estan permesses. Si un especificador d'unitats no\n"
-"es inclòs, per defecte seran dies (o sigui +30 nomès\n"
-"significa 30 dies). Per afegir un AKILL que no caduqui, utilitza +0.\n"
-"Si la mascara a afegir comença amb un +, s'ha d'especificar\n"
-"un temps d'expiració. El temps d'expiració per defecte actual de AKILLS\n"
-"pot ser consultat amb la comanda STATS AKILL.\n"
-"\n"
-"La comanda AKILL DEL esborra la mascara especificada de la llista\n"
-"d'AKILLS si esta present. Si s'especifica una llista de noms,\n"
-"aquestes instàncies son esborrades. (Veure l'exemple per LIST \n"
-"especificat més endavant.)\n"
-"\n"
-"La comanda AKILL LIST mostra la llista d'AKILLS. \n"
-"Si s'especifica una mascara, nomès les instàncies coincidents\n"
-"amb la mascara són mostrades. Si s'especifica una llista de noms,\n"
-"nomès aquestes instàncies son mostrades; per exemple:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" Llista les instàncies de AKILL enumerades de 2 a 5 i de 7 \n"
-" a 9.\n"
-" \n"
-"AKILL VIEW es una versió més verbal d'AKILL LIST, i \n"
-"mostrara qui va afegir un AKILL, la data en que va ser afegit,\n"
-"i quan caducara, així com tambe la mascara usuari@host\n"
-"i la raó.\n"
-"\n"
-"AKILL CLEAR neteja totes les instàncies de la llista d'AKILLS.\n"
-"\n"
-"Limitat a operadors de serveis."
-
-msgid ""
-"Allows Services Operators to manipulate the SNLINE list. If\n"
-"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
-"session."
-msgstr ""
-
-msgid ""
-"Allows Services Operators to manipulate the SQLINE list. If\n"
-"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
-"session.\n"
-"If the first character of the mask is #, services will\n"
-"prevent the use of matching channels. If the mask is a\n"
-"regular expression, the expression will be matched against\n"
-"channels too."
-msgstr ""
-
-msgid ""
-"Allows Services Operators to manipulate the list of hosts that\n"
-"have specific session limits - allowing certain machines,\n"
-"such as shell servers, to carry more than the default number\n"
-"of clients at a time. Once a host reaches its session limit,\n"
-"all clients attempting to connect from that host will be\n"
-"killed. Before the user is killed, they are notified, of a\n"
-"source of help regarding session limiting. The content of\n"
-"this notice is a config setting."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to view the session list.\n"
-" \n"
-"SESSION LIST lists hosts with at least threshold sessions.\n"
-"The threshold must be a number greater than 1. This is to\n"
-"prevent accidental listing of the large number of single\n"
-"session hosts.\n"
-" \n"
-"SESSION VIEW displays detailed information about a specific\n"
-"host - including the current session count and session limit.\n"
-"The host value may not include wildcards.\n"
-" \n"
-"See the EXCEPTION help for more information about session\n"
-"limiting and how to set session limits specific to certain\n"
-"hosts and groups thereof."
-msgstr ""
-"Sintaxis: SESSION LIST umbral\n"
-" SESSION VIEW host\n"
-"\n"
-"Permet als administradors de serveis veure la llista de sessions.\n"
-"\n"
-"SESSION LIST llista hosts amb un mínim de umbral sessions.\n"
-"L'umbral ha de ser un numero superior a 1. Això es per a prevenir\n"
-"llistats accidentals del gran nombre de hosts de sessió.\n"
-"SESSION VIEW mostra informació detallada sobre un host \n"
-"específic - incloent el compte de sessió i el límit de sessió\n"
-"actual.\n"
-"El valor host no pot incluir comodins.\n"
-"\n"
-"Mireu l'ajuda sobre EXCEPTION per a més informació sobre\n"
-"límits de sessió i como establir-los per a hosts i grups específics\n"
-"d'ara endavant. \n"
-"\n"
-"Limitat a administradors de serveis."
-
-msgid ""
-"Allows manipulating the topic of the specified channel.\n"
-"The SET command changes the topic of the channel to the given topic\n"
-"or unsets the topic if no topic is given. The APPEND command appends\n"
-"the given topic to the existing topic.\n"
-" \n"
-"LOCK and UNLOCK may be used to enable and disable topic lock. When\n"
-"topic lock is set, the channel topic will be unchangeable by users who do "
-"not have\n"
-"the TOPIC privilege."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Allows staff to kick a user from any channel.\n"
-"Parameters are the same as for the standard /KICK\n"
-"command. The kick message will have the nickname of the\n"
-"IRCop sending the KICK command prepended; for example:\n"
-" \n"
-"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
-msgstr ""
-"Sintàxi: KICK canal usuari raó\n"
-"\n"
-"Permet als IRCops kickejar un usuari de qualsevol\n"
-"canal. Els parametres son els mateixos que per la comanda\n"
-"/KICK. El missatge de kick tindra el nickname del IRCop\n"
-"que envia la comanda KICK; per exemple:\n"
-"\n"
-"*** SpamMan ha estat kickejat del canal #aujac per %s (cistus (Flood))\n"
-"\n"
-"Limitat a operadors de serveis."
-
-#, fuzzy
-msgid ""
-"Allows the channel founder to set various channel options\n"
-"and other information.\n"
-" \n"
-"Available options:"
-msgstr ""
-"Sintaxis: SET canal opció parametres\n"
-"\n"
-"Li permet al fundador del canal establir varies opcions\n"
-"del canal i altres informacions.\n"
-"\n"
-"Opcions disponibles:"
-
-msgid ""
-"Allows you to change and view Services Operators.\n"
-"Note that operators removed by this command but are still set in\n"
-"the configuration file are not permanently affected by this."
-msgstr ""
-
-msgid ""
-"Allows you to change and view configuration settings.\n"
-"Settings changed by this command are temporary and will not be reflected\n"
-"back into the configuration file, and will be lost if Anope is shut down,\n"
-"restarted, or the configuration is reloaded.\n"
-" \n"
-"Example:\n"
-" MODIFY nickserv forcemail no"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
-msgstr ""
-"Syntax: SASET nickname MSG {ON | OFF}\n"
-"\n"
-"Allows you to choose the way Services are communicating with \n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
-"use notices."
-msgstr ""
-"Sintaxis: SET MSG {ON | OFF}\n"
-"\n"
-"Et permet escollir la forma en la que els serveis es\n"
-"comunicaran amb tu. Amb MSG establert, els serveis\n"
-"utilitzaran msgs, de l'altra forma utilitzaran notícies. "
-
-msgid ""
-"Allows you to ignore users by nick or host from memoing\n"
-"you or a channel. If someone on the memo ignore list tries\n"
-"to memo you or a channel, they will not be told that you have\n"
-"them ignored."
-msgstr ""
-
-msgid ""
-"Allows you to kill a user from the network.\n"
-"Parameters are the same as for the standard /KILL\n"
-"command."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-msgstr ""
-"Syntax: SASET nickname HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), your services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-msgstr ""
-"Sintaxis: SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Permet prevenir que certa informació sobre el teu nick sigui donada\n"
-"quant es sol.licitada mitjançant la comanda %s INFO.\n"
-"Pots ocultar la teva adreça e-mail (EMAIL), l'ultima\n"
-"mascara usuari@host (USERMASK), i el teu últim missatge\n"
-"quit (QUIT).\n"
-"El segon parametre especifica si la informació ha de ser\n"
-"ocultada (OFF) o mostrada (ON)."
-
-#, fuzzy, c-format
-msgid "Allows you to see %s information about a channel or a bot"
-msgstr ""
-"INFO Allows you to see BotServ information about a channel or "
-"a bot"
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to see %s information about a channel or a bot.\n"
-"If the parameter is a channel, then you'll get information\n"
-"such as enabled kickers. If the parameter is a nick,\n"
-"you'll get information about a bot, such as creation\n"
-"time or number of channels it is on."
-msgstr ""
-"Sintàxi: INFO {canal | nick}\n"
-"\n"
-"Permet veure la informació de %s sobre un canal o\n"
-"bot. Si el parametre es un canal, rebràs informació\n"
-"així como kickers activats. Si el parametre es un nick,\n"
-"rebràs informació sobre el bot, així com temps\n"
-"de creació o nom de canals en els que aquest estigui."
-
-msgid ""
-"Alternative methods of modifying channel access lists are\n"
-"available."
-msgstr ""
-
-#, fuzzy
-msgid "Approve the requested vHost of a user"
-msgstr " DEL Delete the vhost of another user"
-
-#, fuzzy
-msgid "As a Services Operator, you may drop any nick."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "Assigns a bot to a channel"
-msgstr "ASSIGN Assigna un bot a un canal"
-
-#, fuzzy
-msgid ""
-"Assigns the specified bot to a channel. You\n"
-"can then configure the bot for the channel so it fits\n"
-"your needs."
-msgstr ""
-"Sintàxi: ASSIGN canal nick\n"
-"\n"
-"Assigna un bot especificat per nick al canal.\n"
-"Desprès d'això pots configurar el bot segons\n"
-"les teves necessitats."
-
-#, fuzzy
-msgid "Associate a URL with the channel"
-msgstr "ASSIGN Assigna un bot a un canal"
-
-msgid "Associate a URL with this account"
-msgstr ""
-
-#, fuzzy
-msgid "Associate a URL with your account"
-msgstr " GREET Associa un salutació amb el teu nickname"
-
-#, fuzzy
-msgid "Associate a greet message with your nickname"
-msgstr " GREET Associa un salutació amb el teu nickname"
-
-#, fuzzy
-msgid "Associate an E-mail address with the channel"
-msgstr " EMAIL Associa un E-mail amb el teu nickname"
-
-#, fuzzy
-msgid "Associate an E-mail address with your nickname"
-msgstr " EMAIL Associa un E-mail amb el teu nickname"
-
-#, fuzzy
-msgid "Associate oper info with a nick or channel"
-msgstr "ASSIGN Assigna un bot a un canal"
-
-#, fuzzy
-msgid "Associates the given E-mail address with the nickname."
-msgstr " EMAIL Associa un E-mail amb el teu nickname"
-
-#, fuzzy
-msgid ""
-"Associates the given E-mail address with your nickname.\n"
-"This address will be displayed whenever someone requests\n"
-"information on the nickname with the INFO command."
-msgstr ""
-"Sintaxis: SET EMAIL direccion\n"
-"\n"
-"Associa el E-mail donat amb el teu nickname. L'e-mail\n"
-"sera mostrat quant algu demani informació\n"
-"sobre el teu nick amb la comanda INFO."
-
-msgid "Auto-op"
-msgstr "Auto-op"
-
-#, c-format
-msgid "Autokick list for %s:"
-msgstr "Llista de kicks automàtics pel canal %s:"
-
-msgid "Automatic channel operator status upon join"
-msgstr ""
-
-msgid "Automatic halfop upon join"
-msgstr ""
-
-msgid "Automatic owner upon join"
-msgstr ""
-
-msgid "Automatic protect upon join"
-msgstr ""
-
-msgid "Automatic voice on join"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Available commands for %s:"
-msgstr "No existeix ajuda per %s."
-
-#, fuzzy
-msgid "Available opertypes:"
-msgstr "No existeix ajuda per %s."
-
-#, c-format
-msgid "Available privileges for %s:"
-msgstr ""
-
-msgid "BANS enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "Bad words kicker"
-msgstr " Kicker per paraules malsonants : %s"
-
-#, fuzzy, c-format
-msgid "Bad words list for %s:"
-msgstr "Lllista d'accés per %s:"
-
-msgid "Bad words list is now empty."
-msgstr "La llista de paraules malsonants esta ara buida."
-
-msgid "Ban expiry may not be longer than 1 day."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Ban on %s expires in %s."
-msgstr "El bot %s ja existeix."
-
-msgid "Ban type"
-msgstr ""
-
-#, c-format
-msgid "Ban type for channel %s is now #%d."
-msgstr "Tipus de ban pel canal %s es ara #%d."
-
-#, fuzzy
-msgid "Bans a given nick or mask on a channel"
-msgstr " BAN Bans a selected nick on a channel"
-
-#, fuzzy
-msgid ""
-"Bans a given nick or mask on a channel. An optional expiry may\n"
-"be given to cause services to remove the ban after a set amount\n"
-"of time.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders may ban masks."
-msgstr ""
-"Sintàxi: BAN #canal nick [raó]\n"
-"\n"
-"Baneja un nick seleccionat en un canal.\n"
-"\n"
-"Per defecte, limitat a AOPs o aquells amb nivell d'\n"
-"accés 5 i major en el canal."
-
-#, fuzzy, c-format
-msgid "Bans enforced on %s."
-msgstr "%s no es notificat per memos nous."
-
-#, fuzzy
-msgid "Bolds kicker"
-msgstr " Kicker per negretes : %s"
-
-#, c-format
-msgid "Bot %s already exists."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy, c-format
-msgid "Bot %s does not exist."
-msgstr "El bot %s ja existeix."
-
-#, c-format
-msgid "Bot %s has been assigned to %s."
-msgstr "El bot %s ha estat assignat al canal %s."
-
-#, fuzzy, c-format
-msgid "Bot %s has been changed to %s!%s@%s (%s)."
-msgstr "El bot %s ha estat canviat a %s!%s@%s (%s)"
-
-#, c-format
-msgid "Bot %s has been deleted."
-msgstr "El bot %s ha estat esborrat."
-
-#, c-format
-msgid "Bot %s is already assigned to channel %s."
-msgstr "Bot %s is already assigned to channel %s."
-
-#, c-format
-msgid "Bot will kick ops on channel %s."
-msgstr "Bot kickejara ops en el canal %s."
-
-#, c-format
-msgid "Bot will kick voices on channel %s."
-msgstr "Bot kickejara voices en el canal %s."
-
-#, c-format
-msgid "Bot won't kick ops on channel %s."
-msgstr "Bot no kickejara ops en el canal %s."
-
-#, c-format
-msgid "Bot won't kick voices on channel %s."
-msgstr "Bot no kickejara voices en el canal %s."
-
-#, fuzzy, c-format
-msgid "Bot %s is not changeable."
-msgstr "Mode no bot ara activat en el canal %s."
-
-#, fuzzy, c-format
-msgid "Bot %s is not deletable."
-msgstr "El bot %s ha estat esborrat."
-
-#, c-format
-msgid "Bot bans will automatically expire after %s."
-msgstr ""
-
-#, fuzzy
-msgid "Bot bans will no longer automatically expire."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Bot Hosts may only contain %d characters."
-
-#, fuzzy
-msgid "Bot hosts may only contain valid host characters."
-msgstr "Bot Hosts may only contain valid host characters."
-
-#, fuzzy, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Bot Idents may only contain %d characters."
-
-#, fuzzy
-msgid "Bot idents may only contain valid ident characters."
-msgstr "Bot Idents may only contain valid characters."
-
-#, fuzzy, c-format
-msgid "Bot is not on channel %s."
-msgstr "Bot kickejara ops en el canal %s."
-
-msgid "Bot list:"
-msgstr "Llista de bots:"
-
-msgid "Bot nick"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Bot Idents may only contain %d characters."
-
-#, fuzzy
-msgid "Bot nicks may only contain valid nick characters."
-msgstr "Bot Nicks may only contain valid nick characters."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for %s, and will place a ban\n"
-"after %d kicks for the same user."
-msgstr ""
-"Bot will now kick italics, and will place a ban after\n"
-"%d kicks for the same user."
-
-#, fuzzy, c-format
-msgid "Bot will now kick for %s."
-msgstr "El bot ara kickjeara negretes."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message), and will\n"
-"place a ban after %d kicks for the same user."
-msgstr ""
-"El bot ara kickejara majusculas (han de ser al menys\n"
-"%d caràcters i %d%% del missatge senser), i banegara\n"
-"després de %d kicks al mateix usuari."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message)."
-msgstr ""
-"El bot ara kickejara majuscules (han de ser al menys\n"
-"%d caràcters i %d%% del missatge senser)."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for flood (%d lines in %d seconds\n"
-"and will place a ban after %d kicks for the same user."
-msgstr ""
-"El bot ara kickejara flood (%d linees in %d segons), i \n"
-"banejara després de %d kicks al mateix usuari."
-
-#, fuzzy, c-format
-msgid "Bot will now kick for flood (%d lines in %d seconds)."
-msgstr "El bot ara kickejara flood (%d linees en %d segons)."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time), and will place a ban after %d\n"
-"kicks for the same user."
-msgstr ""
-"El bot ara kickejara repeticions (usuaris que repeteixin %d vegades\n"
-"el mateix), i banejara després de %d \n"
-"kicks al mateix usuari."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time)."
-msgstr ""
-"El bot ara kickejara repeticions (usuaris que repeteixin %d vegades\n"
-"el mateix)."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times), and will place a ban after %d\n"
-"kicks for the same user."
-msgstr ""
-"El bot ara kickejara repeticions (usuaris que repeteixin %d vegades\n"
-"el mateix), i banejara després de %d \n"
-"kicks al mateix usuari."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times)."
-msgstr ""
-"El bot ara kickejara repeticions (usuaris que repeteixin %d vegades\n"
-"el mateix)."
-
-#, fuzzy, c-format
-msgid "Bot won't kick for %s anymore."
-msgstr "El bot ja no kickejara majuscules."
-
-#, fuzzy
-msgid "Bot won't kick for caps anymore."
-msgstr "El bot ja no kickejara majuscules."
-
-#, fuzzy
-msgid "Bot won't kick for flood anymore."
-msgstr "El bot ja no kickejara flood."
-
-#, fuzzy
-msgid "Bot won't kick for repeats anymore."
-msgstr "El bot ja no kickejara repeticions."
-
-msgid "By"
-msgstr ""
-
-msgid "CLEAR target"
-msgstr ""
-
-msgid "CLEAR time"
-msgstr ""
-
-#, fuzzy
-msgid "Cancel the last memo you sent"
-msgstr " CANCEL Cancela l'últim memo enviat"
-
-#, fuzzy
-msgid "Cancel the registration of a channel"
-msgstr " DROP Cancel.la l'enregistrament d'un canal"
-
-#, fuzzy
-msgid "Cancel the registration of a nickname"
-msgstr " DROP Cancela el registre d'un nickname"
-
-#, fuzzy
-msgid ""
-"Cancels the last memo you sent to the given nick or channel,\n"
-"provided it has not been read at the time you use the command."
-msgstr ""
-"Sintàxi: CANCEL {nick | canal}\n"
-"\n"
-"Cancela l'ultim memo enviat al nick o canal donat,\n"
-"sempre i quan no hagi sigut llegit al moment en el que\n"
-"vas fer servir la comanda."
-
-#, fuzzy, c-format
-msgid "Cannot clone channel %s to itself!"
-msgstr "Bot kickejara ops en el canal %s."
-
-msgid "Cannot send mail now; please retry a little later."
-msgstr "Imposible enviar email ara; per favor intenta en uns instants."
-
-#, fuzzy
-msgid "Caps kicker"
-msgstr " Kicker per majuscules : %s"
-
-#, fuzzy
-msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
-"not saved. This command should not be used unless\n"
-"damage to the in-memory copies of the databases is feared\n"
-"and they should not be saved."
-msgstr ""
-"Sintàxi: QUIT\n"
-"\n"
-"Força als serveis a parar inmediatament; les bases de\n"
-"dades no son guardades. Aquesta comanda no ha de ser utilitzada\n"
-"excepte que les còpies en la memòria semblin espatllades i no\n"
-"hagin de ser guardades. Per parar normalment, utilitza la comanda\n"
-"SHUTDOWN.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
-"session limitation, etc.)."
-msgstr ""
-"Sintàxi: RELOAD\n"
-"\n"
-"Força als serveis a recarregar l'arxiu de\n"
-"configuració. Tenir en compe que algunes directives\n"
-"necessiten que els serveis es reinicin de nou per tenir\n"
-"efecte (tal com nicknames dels serveis, activació\n"
-"de la limitació de sessions, etc.)\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Causes Services to save all databases and then restart\n"
-"(i.e. exit and immediately re-run the executable)."
-msgstr ""
-"Sintàxi: RESTART\n"
-"\n"
-"Força als serveis a guardar totes les bases de\n"
-"dades i després parar i arrancar de nou.\n"
-"(es a dir, finalitzar el programa e inmediatament reiniciar\n"
-"el programa de nou).\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy
-msgid "Causes Services to save all databases and then shut down."
-msgstr ""
-"Sintàxi: SHUTDOWN\n"
-"\n"
-"Força als serveis a guardar totes les bases de\n"
-"datos i parar.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Causes Services to update all database files as soon as you\n"
-"send the command."
-msgstr ""
-"Sintàxi: UPDATE\n"
-"\n"
-"Força als serveis a actualitzar tots els arxius de\n"
-"la base de dades tan aviat como enviis la comanda.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy, c-format
-msgid "Certificate list for %s:"
-msgstr "Lllista d'accés per %s:"
-
-msgid "ChanServ is required to enable persist on this network."
-msgstr ""
-
-#, fuzzy
-msgid "Change channel modes"
-msgstr "%s changed your usermodes."
-
-#, fuzzy
-msgid "Change the communication method of Services"
-msgstr ""
-" MSG canvia el metode de comunicació amb els\n"
-" serveis"
-
-#, fuzzy
-msgid "Change user modes"
-msgstr "%s changed your usermodes."
-
-#, fuzzy, c-format
-msgid "Changed usermodes of %s to %s."
-msgstr "Changed usermodes of %s."
-
-#, fuzzy
-msgid ""
-"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
-msgstr ""
-"Sintaxis: SET DISPLAY nou-display\n"
-"\n"
-"canvia el display utilitzat per referir-te al teu grup de\n"
-"nicks en serveis. El nou display HA DE SER un nick\n"
-"del teu grup."
-
-#, fuzzy
-msgid ""
-"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
-msgstr ""
-"Sintaxis: SET DISPLAY nou-display\n"
-"\n"
-"canvia el display utilitzat per referir-te al teu grup de\n"
-"nicks en serveis. El nou display HA DE SER un nick\n"
-"del teu grup."
-
-#, fuzzy
-msgid ""
-"Changes the founder of a channel. The new nickname must\n"
-"be a registered one."
-msgstr ""
-"Sintaxis: %s canal FOUNDER nick\n"
-"\n"
-"Canvia el fundador d'un canal. El nou nickname ha de\n"
-"ser un d'enregistrat."
-
-#, fuzzy
-msgid ""
-"Changes the language Services uses when sending messages to\n"
-"the given user (for example, when responding to a command they send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
-msgstr ""
-"Sintaxis: SET LANGUAGE numero\n"
-"\n"
-"Canvia el llenguatge que serveis utilitza per enviar-te missatges\n"
-"(per exemple, al respondre a una comanda que enviis).\n"
-"numero ha de ser escollit de la llista de llenguatges\n"
-"soportats:"
-
-#, fuzzy
-msgid ""
-"Changes the language Services uses when sending messages to\n"
-"you (for example, when responding to a command you send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
-msgstr ""
-"Sintaxis: SET LANGUAGE numero\n"
-"\n"
-"Canvia el llenguatge que serveis utilitza per enviar-te missatges\n"
-"(per exemple, al respondre a una comanda que enviis).\n"
-"numero ha de ser escollit de la llista de llenguatges\n"
-"soportats:"
-
-#, fuzzy
-msgid "Changes the password used to identify as the nick's owner."
-msgstr ""
-"Sintaxis: SET PASSWORD nueva-clau\n"
-"\n"
-"Canvia la clau utilitzada per identificar-te com el\n"
-"propietari del nick."
-
-#, fuzzy
-msgid ""
-"Changes the password used to identify you as the nick's\n"
-"owner."
-msgstr ""
-"Sintaxis: SET PASSWORD nueva-clau\n"
-"\n"
-"Canvia la clau utilitzada per identificar-te com el\n"
-"propietari del nick."
-
-#, fuzzy
-msgid ""
-"Changes the successor of a channel. If the founder's\n"
-"nickname expires or is dropped while the channel is still\n"
-"registered, the successor will become the new founder of the\n"
-"channel. The successor's nickname must be a registered one.\n"
-"If there's no successor set, then the first nickname on the\n"
-"access list (with the highest access, if applicable) will\n"
-"become the new founder, but if the access list is empty, the\n"
-"channel will be dropped."
-msgstr ""
-"Sintaxis: %s canal SUCCESSOR nick\n"
-"\n"
-"Canvia el successor d'un canal. Si el nickname fundador\n"
-"caduca o es eliminat mentres el canal esta encara registrat,\n"
-"el successor es convertira en el nou fundador del canal.\n"
-"Però, si el successor ja te molts canals\n"
-"registrats (%d), el canal sera eliminat, tal i com\n"
-"si no hi haguès un successor. El nou nickname ha de ser un\n"
-"d'enregistrat."
-
-#, fuzzy
-msgid "Channel"
-msgstr "DROP canal"
-
-#, fuzzy, c-format
-msgid "Channel %s doesn't exist."
-msgstr "Channel %s is now persistant."
-
-#, c-format
-msgid "Channel %s has been dropped."
-msgstr "El canal %s ha estat eliminat."
-
-#, fuzzy, c-format
-msgid "Channel %s has no key."
-msgstr "The channel %s has no key."
-
-#, c-format
-msgid "Channel %s is already registered!"
-msgstr "El canal %s ja esta enregistrat!"
-
-#, fuzzy, c-format
-msgid "Channel %s is forbidden by %s: %s"
-msgstr "Aquest canal ha estat registrat amb %s."
-
-#, fuzzy, c-format
-msgid "Channel %s is forbidden."
-msgstr "Channel %s is now persistant."
-
-#, fuzzy, c-format
-msgid "Channel %s is no longer persistent."
-msgstr "Channel %s is no longer persistant."
-
-#, fuzzy, c-format
-msgid "Channel %s is now persistent."
-msgstr "Channel %s is now persistant."
-
-#, c-format
-msgid "Channel %s is now released."
-msgstr "Channel %s is now released."
-
-#, c-format
-msgid "Channel %s is now suspended."
-msgstr "Channel %s is now suspended."
-
-#, fuzzy, c-format
-msgid "Channel %s isn't registered."
-msgstr "El canal %s no pot ser enregistrat."
-
-#, fuzzy, c-format
-msgid "Channel %s isn't suspended."
-msgstr "Channel %s is now suspended."
-
-#, fuzzy, c-format
-msgid "Channel %s registered under your account: %s"
-msgstr "El nickname %s ja esta registrat sota el teu compte: %s"
-
-#, c-format
-msgid "Channel %s will expire."
-msgstr "El canal %s caducara."
-
-#, c-format
-msgid "Channel %s will not expire."
-msgstr "El canal %s no caducara."
-
-#, fuzzy, c-format
-msgid "Channel %s %s list has been cleared."
-msgstr "La llista AOP de canals %s ha estat netegada."
-
-#, c-format
-msgid "Channel %s access list has been cleared."
-msgstr "La llista d'accés pel canal %s ha estat netegada."
-
-#, c-format
-msgid "Channel %s akick list has been cleared."
-msgstr "La llista de kicks automàtics en canal %s ha estat netegada."
-
-#, fuzzy, c-format
-msgid "Channel %s has no mode locks."
-msgstr "Channel %s is now released."
-
-#, fuzzy, c-format
-msgid "Channel %s is currently suspended."
-msgstr "Channel %s is now suspended."
-
-#, fuzzy, c-format
-msgid "Channel %s is not a valid channel."
-msgstr "%s no es un tipus de ban valid."
-
-#, fuzzy
-msgid "Channel list:"
-msgstr "Llista de bots:"
-
-#, fuzzy, c-format
-msgid "Channel stats for %s on %s:"
-msgstr ""
-"Channels that %s has access on:\n"
-" Num Channel Level Description "
-
-#, fuzzy
-msgid "Channels may not be on access lists."
-msgstr "%s no trobat a la llista d'accés de %s."
-
-#, fuzzy, c-format
-msgid "Channels that %s has access on:"
-msgstr ""
-"Channels that %s has access on:\n"
-" Num Channel Level Description "
-
-#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-msgid "Chanstats"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Chanstats statistics are now disabled for %s"
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-msgid "Chanstats statistics are now disabled for this channel."
-msgstr ""
-
-#, fuzzy
-msgid "Chanstats statistics are now disabled for your nick."
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-#, fuzzy, c-format
-msgid "Chanstats statistics are now enabled for %s"
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-msgid "Chanstats statistics are now enabled for this channel."
-msgstr ""
-
-#, fuzzy
-msgid "Chanstats statistics are now enabled for your nick."
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-msgid ""
-"Checks for the last time nick was seen joining, leaving,\n"
-"or changing nick on the network and tells you when and, depending\n"
-"on channel or user settings, where it was."
-msgstr ""
-
-#, fuzzy
-msgid "Checks if last memo to a nick was read"
-msgstr " CHECK Checks if last memo to a nick was read"
-
-#, fuzzy
-msgid ""
-"Checks whether the _last_ memo you sent to nick has been read\n"
-"or not. Note that this only works with nicks, not with channels."
-msgstr ""
-"Syntax: CHECK nick\n"
-"\n"
-"Checks whether the _last_ memo you sent to nick has been read\n"
-"or not. Note that this does only work with nicks, not with chans."
-
-#, c-format
-msgid "Cleared info from %s."
-msgstr ""
-
-#, fuzzy
-msgid "Colors kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Command"
-msgstr "%s commands:"
-
-#, fuzzy
-msgid "Configures AMSG kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures badwords kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures bolds kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures bot kickers. option can be one of:"
-msgstr ""
-"Sintaxis: SET Opció parametres\n"
-"\n"
-"Estableix varies opcions per a nicknames. Opció pot ser\n"
-"una de:"
-
-#, fuzzy
-msgid "Configures bot options"
-msgstr "SET Configura opcions de bots"
-
-#, fuzzy
-msgid ""
-"Configures bot options.\n"
-" \n"
-"Available options:"
-msgstr "SET Configura opcions de bots"
-
-#, fuzzy
-msgid "Configures caps kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures channel logging settings"
-msgstr "* No new channel registrations"
-
-#, fuzzy
-msgid "Configures color kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures flood kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures italics kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures kickers"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures repeat kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures reverses kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Configures the time bot bans expire in"
-msgstr "SET Configura opcions de bots"
-
-#, fuzzy
-msgid "Configures underlines kicker"
-msgstr "KICK Configura kickers"
-
-#, fuzzy
-msgid "Confirm a passcode"
-msgstr " CONFIRM Confirm a nickserv auth code"
-
-#, fuzzy
-msgid "Control modes and mode locks on a channel"
-msgstr " CLEARMODES neteja els Modes d'un canal"
-
-msgid ""
-"Controls what messages will be sent to users when they join the channel."
-msgstr ""
-
-msgid ""
-"Copies all settings, access, akicks, etc from channel to the\n"
-"target channel. If what is ACCESS, AKICK, BADWORDS,\n"
-"or LEVELS then only the respective settings are cloned.\n"
-"You must be the founder of channel and target."
-msgstr ""
-
-#, fuzzy
-msgid "Copy all settings from one channel to another"
-msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-
-#, fuzzy
-msgid "Created"
-msgstr " Creat : %s"
-
-#, fuzzy
-msgid "Creator"
-msgstr " Creat : %s"
-
-#, fuzzy, c-format
-msgid "Current %s list:"
-msgstr "Llista actual de AKILLs:"
-
-#, fuzzy
-msgid "Current AKILL list:"
-msgstr "Llista actual de AKILLs:"
-
-msgid "Current Session Limit Exception list:"
-msgstr "llista d'excepcions al límit de sessions actual:"
-
-#, fuzzy
-msgid "Current module list:"
-msgstr "Current Module list:"
-
-#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Numero actual de AKILLs: %d"
-
-#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Numero actual de SNLINEs: %d"
-
-#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Numero actual de SQLINEs: %d"
-
-#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Actuals usuaris: %d (%d ops)"
-
-#, fuzzy
-msgid "DEL oper"
-msgstr "DEL <nick>."
-
-#, fuzzy
-msgid "DEL target info"
-msgstr "GROUP grup clau"
-
-#, fuzzy
-msgid "DEL [nickname] channel"
-msgstr "MODE canal Modes"
-
-#, fuzzy
-msgid "DEL [nickname] fingerprint"
-msgstr "FORBID nickname rao"
-
-#, fuzzy
-msgid "DEL [nickname] mask"
-msgstr "MODE canal Modes"
-
-#, fuzzy
-msgid "DEL {mask | entry-num | list | id}"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-#, fuzzy
-msgid "DEL {mask | entry-num | list}"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-#, fuzzy
-msgid "DEL {nick|mask}"
-msgstr "DEL <nick>."
-
-#, fuzzy
-msgid "DEL {num | ALL}"
-msgstr "Sintaxis: OPERNEWS DEL {numero | ALL}"
-
-msgid "DEL {NICK|CHAN|EMAIL|REGISTER} entry"
-msgstr ""
-
-msgid "DELIP server.name ip"
-msgstr ""
-
-msgid "DELSERVER server.name [zone.name]"
-msgstr ""
-
-msgid "DELZONE zone.name"
-msgstr ""
-
-#, fuzzy
-msgid "DEPOOL server.name"
-msgstr "NOOP {SET|REVOKE} servidor"
-
-#, c-format
-msgid "Database cleared, removed %lu nicks that were added after %s."
-msgstr ""
-
-msgid "Date/Time"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Deactivates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see your real host/IP address."
-msgstr ""
-"Syntax: OFF\n"
-"Deactivates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see your real IP address."
-
-#, fuzzy
-msgid "Deactivates your assigned vhost"
-msgstr " OFF Deactivates your assigned vhost"
-
-#, c-format
-msgid "Default AKILL expiry time: %d days"
-msgstr "Temps d'expiració per defecte de AKILL: %d dies"
-
-#, c-format
-msgid "Default AKILL expiry time: %d hours"
-msgstr "Temps d'expiració per defecte de AKILL: %d hores"
-
-#, c-format
-msgid "Default AKILL expiry time: %d minutes"
-msgstr "Temps d'expiració per defecte de AKILL: %d minuts"
-
-msgid "Default AKILL expiry time: 1 day"
-msgstr "Temps d'expiració per defecte de AKILL: 1 dia"
-
-msgid "Default AKILL expiry time: 1 hour"
-msgstr "Temps d'expiració per defecte de AKILL: 1 hora"
-
-msgid "Default AKILL expiry time: 1 minute"
-msgstr "Temps d'expiració per defecte de AKILL: 1 minut"
-
-msgid "Default AKILL expiry time: No expiration"
-msgstr "Temps d'expiració per defecte de AKILL: Sense expiració"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d days"
-msgstr "Temps d'expiració per defecte de SNLINE: %d dies"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d hours"
-msgstr "Temps d'expiració per defecte de SNLINE: %d hores"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d minutes"
-msgstr "Temps d'expiració per defecte de SNLINE: %d minuts"
-
-msgid "Default SNLINE expiry time: 1 day"
-msgstr "Temps d'expiració per defecte de SNLINE: 1 dia"
-
-msgid "Default SNLINE expiry time: 1 hour"
-msgstr "Temps d'expiració per defecte de SNLINE: 1 hora"
-
-msgid "Default SNLINE expiry time: 1 minute"
-msgstr "Temps d'expiració per defecte de SNLINE: 1 minut"
-
-msgid "Default SNLINE expiry time: No expiration"
-msgstr "Temps d'expiració per defecte de SNLINE: Sense expiració"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d days"
-msgstr "Temps d'expiració per defecte de SQLINE: %d dies"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d hours"
-msgstr "Temps d'expiració per defecte de SQLINE: %d hores"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d minutes"
-msgstr "Temps d'expiració per defecte de SQLINE: %d minuts"
-
-msgid "Default SQLINE expiry time: 1 day"
-msgstr "Temps d'expiració per defecte de SQLINE: 1 dia"
-
-msgid "Default SQLINE expiry time: 1 hour"
-msgstr "Temps d'expiració per defecte de SQLINE: 1 hora"
-
-msgid "Default SQLINE expiry time: 1 minute"
-msgstr "Temps d'expiració per defecte de SQLINE: 1 minut"
-
-msgid "Default SQLINE expiry time: No expiration"
-msgstr "Temps d'expiració per defecte de SQLINE: Sense expiració"
-
-#, fuzzy
-msgid "Define messages to be randomly shown to users at logon"
-msgstr ""
-" LOGONNEWS Defineix missatges per a ser mostrats a usuaris\n"
-" al conectarse"
-
-#, fuzzy
-msgid "Define messages to be shown to users at logon"
-msgstr ""
-" LOGONNEWS Defineix missatges per a ser mostrats a usuaris\n"
-" al conectarse"
-
-#, fuzzy
-msgid "Define messages to be shown to users who oper"
-msgstr ""
-" OPERNEWS Defineix missatges per a ser mostrats a usuaris\n"
-" al transformar-se en operadors"
-
-#, fuzzy
-msgid "Delete a memo or memos"
-msgstr " DEL Esborra un o més memos"
-
-#, fuzzy
-msgid "Delete the vhost of another user"
-msgstr " DEL Delete the vhost of another user"
-
-#, fuzzy, c-format
-msgid "Deleted %d entries from %s %s list."
-msgstr "%d instàncies esborrades de la llista AOP de %s."
-
-#, c-format
-msgid "Deleted %d entries from %s access list."
-msgstr "%d instàncies esborrades de la llista d'accés de %s."
-
-#, c-format
-msgid "Deleted %d entries from %s autokick list."
-msgstr ""
-"%d instàncies esborrades de la llista de kicks automàtics del canal %s."
-
-#, c-format
-msgid "Deleted %d entries from %s bad words list."
-msgstr "%d paraules esborrades de la llista de paraules malsonants de %s."
-
-#, c-format
-msgid "Deleted %d entries from session-limit exception list."
-msgstr ""
-"%d instàncies esborrades de la llista d'excepcions al límit de sessions."
-
-#, fuzzy, c-format
-msgid "Deleted %d entries from the %s list."
-msgstr "%d instàncies esborrades de la llista AOP de %s."
-
-#, c-format
-msgid "Deleted %d entries from the AKILL list."
-msgstr "%d instàncies esborrades de la llista de AKILLs."
-
-#, c-format
-msgid "Deleted 1 entry from %s access list."
-msgstr "1 instància esborrada de la llista d'accés de %s."
-
-#, c-format
-msgid "Deleted 1 entry from %s autokick list."
-msgstr "1 instància esborrada de la llista de kicks automàtics del canal %s."
-
-#, c-format
-msgid "Deleted 1 entry from %s bad words list."
-msgstr "1 paraula esborrada de la llista de paraules malsonants de %s."
-
-msgid "Deleted 1 entry from session-limit exception list."
-msgstr "1 instància esborrada de la llista d'excepcions al límit de sessions."
-
-#, fuzzy, c-format
-msgid "Deleted 1 entry from the %s list."
-msgstr "1 instància esborrada de la llista de AKILLs."
-
-msgid "Deleted 1 entry from the AKILL list."
-msgstr "1 instància esborrada de la llista de AKILLs."
-
-#, fuzzy, c-format
-msgid "Deleted info from %s."
-msgstr "1 instància esborrada de la llista de AKILLs."
-
-#, fuzzy, c-format
-msgid "Deleted one entry from %s %s list."
-msgstr "1 instància esborrada de la llista AOP de %s."
-
-#, fuzzy
-msgid ""
-"Deletes the specified memo or memos. You can supply\n"
-"multiple memo numbers or ranges of numbers instead of a\n"
-"single number, as in the second example below.\n"
-" \n"
-"If LAST is given, the last memo will be deleted.\n"
-"If ALL is given, deletes all of your memos.\n"
-" \n"
-"Examples:\n"
-" \n"
-" DEL 1\n"
-" Deletes your first memo.\n"
-" \n"
-" DEL 2-5,7-9\n"
-" Deletes memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Sintàxi: DEL [canal] {nombre | llista | LAST | ALL}\n"
-"\n"
-"Esorra el o els memos especificats. pots donar multiples\n"
-"nombres o rangs de nombres en lloc d'un solo, com en el\n"
-"exemple.\n"
-"\n"
-"If LAST is given, the last memo will be deleted.\n"
-"Si ALL és donat, esborra tots els teus memos.\n"
-"\n"
-"exemples:\n"
-"\n"
-" DEL 1\n"
-" Esorra el teu primer memo.\n"
-"\n"
-" DEL 2-5,7-9\n"
-" Esborra els memos enumerats 2 a 5 i 7 a 9."
-
-#, fuzzy
-msgid ""
-"Deletes the vhost assigned to the given nick from the\n"
-"database."
-msgstr ""
-"Syntax: DEL <nick>\n"
-"Deletes the vhost assigned to the given nick from the\n"
-"database.\n"
-"Limited to Services operators."
-
-#, fuzzy
-msgid "Deletes the vhost for all nicks in a group"
-msgstr " DELALL Delete the vhost for all nicks in a group"
-
-#, fuzzy
-msgid ""
-"Deletes the vhost for all nicks in the same group as\n"
-"that of the given nick."
-msgstr ""
-"Syntax: DELALL <nick>.\n"
-"Deletes the vhost for all nick's in the same group as\n"
-"that of the given nick.\n"
-"Limited to Host Removers."
-
-#, c-format
-msgid "Depooled %s."
-msgstr ""
-
-#, fuzzy
-msgid "Description"
-msgstr "La descripció de %s canviada a%s."
-
-#, c-format
-msgid "Description of %s changed to %s."
-msgstr "La descripció de %s canviada a%s."
-
-#, fuzzy, c-format
-msgid "Description of %s unset."
-msgstr "La descripció de %s canviada a%s."
-
-#, fuzzy
-msgid "Disabled"
-msgstr "%s is enable"
-
-#, fuzzy
-msgid ""
-"Disallows anyone from using the given channel.\n"
-"May be cancelled by using the UNSUSPEND\n"
-"command to preserve all previous channel data/settings.\n"
-"If an expiry is given the channel will be unsuspended after\n"
-"that period of time, else the default expiry from the\n"
-"configuration is used.\n"
-" \n"
-"Reason may be required on certain networks."
-msgstr ""
-"Syntax: SUSPEND channel [reason]\n"
-"\n"
-"Disallows anyone from registering or using the given\n"
-"channel. May be cancelled by using the UNSUSPEND\n"
-"command to preserve all previous channel data/settings.\n"
-"\n"
-"Reason may be required on certain networks."
-
-#, fuzzy, c-format
-msgid "Displayed %d records (%d total)."
-msgstr "Displayed all records (Count: %d)"
-
-#, fuzzy, c-format
-msgid "Displayed all records (count: %d)."
-msgstr "Displayed all records (Count: %d)"
-
-#, fuzzy, c-format
-msgid "Displayed records from %d to %d."
-msgstr "Displayed records from %d to %d"
-
-#, fuzzy, c-format
-msgid "Displayed records matching key %s (count: %d)."
-msgstr "Displayed records matching key %s (Count: %d)"
-
-#, fuzzy
-msgid "Displays information about a given nickname"
-msgstr " INFO Displays information about a given nickname"
-
-#, fuzzy
-msgid ""
-"Displays information about the given nickname, such as\n"
-"the nick's owner, last seen address and time, and nick\n"
-"options. If no nick is given, and you are identified,\n"
-"your account name is used, else your current nickname is\n"
-"used."
-msgstr ""
-"Sintaxis: INFO nickname\n"
-"\n"
-"Mostra informació relativa al nick que s'especifiqui,\n"
-"tal com el propietari del nick, l'ultima adreça utilitzada\n"
-"i temps, i opcions del nick."
-
-#, fuzzy
-msgid "Displays information about your memos"
-msgstr " INFO Displays information about your memos"
-
-#, fuzzy
-msgid "Displays one or more vhost entries"
-msgstr " LIST Displays one or more vhost entries."
-
-#, fuzzy
-msgid "Displays the top 10 users of a channel"
-msgstr " FOUNDER Estableix el fundador d'un canal"
-
-msgid "Displays the top 10 users of the network"
-msgstr ""
-
-#, fuzzy
-msgid "Displays the top 3 users of a channel"
-msgstr " FOUNDER Estableix el fundador d'un canal"
-
-msgid "Displays the top 3 users of the network"
-msgstr ""
-
-#, fuzzy
-msgid "Displays this list and give information about commands"
-msgstr " INFO Displays information about your memos"
-
-msgid "Displays your Channel Stats"
-msgstr ""
-
-msgid "Displays your Global Stats"
-msgstr ""
-
-msgid "Don't use AMSGs!"
-msgstr ""
-
-msgid "Don't use bolds on this channel!"
-msgstr "No utilitzis negreta en aquest canal!"
-
-msgid "Don't use colors on this channel!"
-msgstr "No utilitzis colors en aquest canal!"
-
-msgid "Don't use italics on this channel!"
-msgstr "Don't use italics on this channel!"
-
-msgid "Don't use reverses on this channel!"
-msgstr "No utilitzis reversos en aquest canal!"
-
-#, c-format
-msgid "Don't use the word \"%s\" on this channel!"
-msgstr "No utilitzis la paraula %s en aquest canal!"
-
-msgid "Don't use underlines on this channel!"
-msgstr "No utilitzis subratllats en aquest canal!"
-
-msgid ""
-"Drops the given nick from the database. Once your nickname\n"
-"is dropped you may lose all of your access and channels that\n"
-"you may own. Any other user will be able to gain control of\n"
-"this nick."
-msgstr ""
-
-#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "E-mail address for %s changed to %s."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "E-mail address for %s unset."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "E-mail per %s es invalid."
-
-#, fuzzy, c-format
-msgid ""
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. However, no more than %d messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
-msgstr ""
-"Syntax: LOGONNEWS ADD text\n"
-" LOGONNEWS DEL {num | ALL}\n"
-" LOGONNEWS LIST\n"
-"\n"
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. (However, no more than %d messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent.)\n"
-"NewsCount can be configured in services.conf.\n"
-"\n"
-"LOGONNEWS may only be used by Services Operators."
-
-#, fuzzy, c-format
-msgid ""
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. However, no more than %d messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
-msgstr ""
-"Syntax: OPERNEWS ADD text\n"
-" OPERNEWS DEL {num | ALL}\n"
-" OPERNEWS LIST\n"
-"\n"
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. (However, no more than %d messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent.)\n"
-"NewsCount can be configured in services.conf.\n"
-"\n"
-"OPERNEWS may only be used by Services Operators."
-
-#, fuzzy
-msgid ""
-"Edits or displays the list of random news messages. When a\n"
-"user connects to the network, one (and only one) of the\n"
-"random news will be randomly chosen and sent to them."
-msgstr ""
-"Sintaxis: RANDOMNEWS ADD text\n"
-" RANDOMNEWS DEL {numero | ALL}\n"
-" RANDOMNEWS LIST\n"
-"\n"
-"Edita o mostra la llista de missatges de noticia a l'atzar.\n"
-"Quant un usuari es connecta a la xarxa, un (i nomès un) dels\n"
-"missatges a l'atzar sera escollit i enviat a ells.\n"
-"\n"
-"RANDOMNEWS may only be used by Services Operators."
-
-#, fuzzy
-msgid "Email address"
-msgstr " \t\tAdreça E-mail: %s"
-
-#, fuzzy, c-format
-msgid "Email matched: %s (%s) to %s."
-msgstr "Emails Match %s to %s."
-
-msgid "Enable fantaisist commands"
-msgstr ""
-
-msgid "Enable greet messages"
-msgstr ""
-
-msgid "Enable or disable keep modes"
-msgstr ""
-
-#, fuzzy
-msgid "Enabled"
-msgstr "%s is enable"
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables %s's autoop feature for a\n"
-"channel. When disabled, users who join the channel will\n"
-"not automatically gain any status from %s."
-msgstr ""
-"Sintàxi: %s canal SECUREOPS {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita l'opció seguretat de ops per a un\n"
-"canal. Quan seguretat de ops està establerta, usuaris\n"
-"que no estaven a la llista d'usuaris no els serà permès \n"
-"obtenir l' estatus d'operador de canal."
-
-#, fuzzy
-msgid ""
-"Enables or disables keepmodes for the given channel. If keep\n"
-"modes is enabled, services will remember modes set on the channel\n"
-"and attempt to re-set them the next time the channel is created."
-msgstr ""
-"Sintaxis: %s canal KEEPTOPIC {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita l'opció de retenció de topic \n"
-"per un canal. Quant la retenció de topic esta\n"
-"establerta, el topic pel canal sera recordat \n"
-"%s fins i tot després de que l'últim usuari\n"
-"sorti del canal, i sigui restaurat la pròxima vegada que\n"
-"el canal sigui creat."
-
-msgid ""
-"Enables or disables keepmodes for the given nick. If keep\n"
-"modes is enabled, services will remember users' usermodes\n"
-"and attempt to re-set them the next time they authenticate."
-msgstr ""
-
-msgid ""
-"Enables or disables keepmodes for your nick. If keep\n"
-"modes is enabled, services will remember your usermodes\n"
-"and attempt to re-set them the next time you authenticate."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Sintàxi: %s canal SECURE {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita les característiques de seguretat\n"
-"de %s per a un canal. Quan SECURE està\n"
-"establert, només usuaris que haguin registrat els seus nicknames\n"
-"amb %s i haguin utilitzat IDENTIFY amb la seva clau els serà\n"
-"atorgat accés al canal controlat per la llista de\n"
-"accés."
-
-#, fuzzy
-msgid ""
-"Enables or disables signed kicks for a\n"
-"channel. When SIGNKICK is set, kicks issued with\n"
-"the KICK command will have the nick that used the\n"
-"command in their reason.\n"
-" \n"
-"If you use LEVEL, those who have a level that is superior\n"
-"or equal to the SIGNKICK level on the channel won't have their\n"
-"kicks signed."
-msgstr ""
-"Sintàxi: %s canal SIGNKICK {ON | LEVEL | OFF}\n"
-"\n"
-"Habilita o deshabilita els kicks firmats per a un\n"
-"canal. Quan SIGNKICK està establert, kicks\n"
-"fets amb la comanda %s KICK tindran el\n"
-"nick que ha fet servir la comanda en la raó.\n"
-"\n"
-"Si uses LEVEL, aquells que tenen nivelll superior o\n"
-"igual al nivelll SIGNKICK en el canal no tindran els seus kicks \n"
-"firmats. Veure /msg %s HELP LEVELS per a més informació."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the peace option for a channel.\n"
-"When peace is set, a user won't be able to kick,\n"
-"ban or remove a channel status of a user that has\n"
-"a level superior or equal to his via %s commands."
-msgstr ""
-"Sintàxi: %s canal PEACE {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita l'opció de pau per a un\n"
-"canal. Quan pau està establerta, un usuari no\n"
-"podra expulsar, banejar o esborrar un estatus de canal\n"
-"d'un usuari amb nivelll igual o superior a ell via\n"
-"comandes de %s."
-
-msgid "Enables or disables the private option for a channel."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-msgstr ""
-"Sintàxi: %s canal RESTRICTED {ON | OFF}\n"
-"\n"
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-
-#, fuzzy
-msgid ""
-"Enables or disables the secure founder option for a channel.\n"
-"When secure founder is set, only the real founder will be\n"
-"able to drop the channel, change its founder and its successor,\n"
-"and not those who have founder level access through\n"
-"the access/qop command."
-msgstr ""
-"Sintàxi: %s canal SECUREFOUNDER {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita l'opció seguretat de fundador per a\n"
-"un canal. Quan seguretat de fundador està establerta, només\n"
-"el fundador real podrà eliminar el canal, canviar la seva clau,\n"
-"el seu fundador i el seu sucesor, i no aquells que estiguin identificats\n"
-"amb %s."
-
-#, fuzzy
-msgid ""
-"Enables or disables the secure ops option for a channel.\n"
-"When secure ops is set, users who are not on the access list\n"
-"will not be allowed channel operator status."
-msgstr ""
-"Sintàxi: %s canal SECUREOPS {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita l'opció seguretat de ops per a un\n"
-"canal. Quan seguretat de ops està establerta, usuaris\n"
-"que no estaven a la llista d'usuaris no els serà permès \n"
-"obtenir l' estatus d'operador de canal."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the topic retention option for a\n"
-"channel. When %s is set, the topic for the\n"
-"channel will be remembered by %s even after the\n"
-"last user leaves the channel, and will be restored the\n"
-"next time the channel is created."
-msgstr ""
-"Sintaxis: %s canal KEEPTOPIC {ON | OFF}\n"
-"\n"
-"Habilita o deshabilita l'opció de retenció de topic \n"
-"per un canal. Quant la retenció de topic esta\n"
-"establerta, el topic pel canal sera recordat \n"
-"%s fins i tot després de que l'últim usuari\n"
-"sorti del canal, i sigui restaurat la pròxima vegada que\n"
-"el canal sigui creat."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the persistent channel setting.\n"
-"When persistent is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-" \n"
-"If your IRCd does not have a permanent (persistent) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-" \n"
-"If this network does not have %s enabled and does\n"
-"not have a permanent channel mode, %s will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-" \n"
-"If your IRCd has a permanent (persistent) channel mode\n"
-"and it is set or unset (for any reason, including MODE LOCK),\n"
-"persist is automatically set and unset for the channel as well.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-msgstr ""
-"Syntax: %s channel PERSIST {ON | OFF}\n"
-"Enables or disables the persistant channel setting.\n"
-"When persistant is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-"\n"
-"If your IRCd does not a permanent (persistant) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-"\n"
-"If this network does not have BotServ enabled and does\n"
-"not have a permanent channel mode, ChanServ will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-"\n"
-"If your IRCd has a permanent (persistant) channel mode\n"
-"and is is set or unset (for any reason, including MLOCK),\n"
-"persist is automatically set and unset for the channel aswell.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-
-#, fuzzy
-msgid "End of AKILL list."
-msgstr "Fi de la llista d'usuaris."
-
-#, fuzzy
-msgid "End of access list"
-msgstr "fi de llista d'accés."
-
-#, fuzzy, c-format
-msgid "End of access list - %d/%d entries shown."
-msgstr "Fi de la lllista - %d/%d resultat(s) mostrat(s)."
-
-msgid "End of access list."
-msgstr "fi de llista d'accés."
-
-#, fuzzy
-msgid "End of autokick list"
-msgstr "fi de llista d'accés."
-
-#, fuzzy
-msgid "End of bad words list."
-msgstr "Fi de la llista d'usuaris."
-
-#, fuzzy, c-format
-msgid "End of channel list. %u channels shown."
-msgstr "Fi de la lllista - %d/%d resultat(s) mostrat(s)."
-
-msgid "End of configuration."
-msgstr ""
-
-#, fuzzy
-msgid "End of entry message list."
-msgstr "Fi de la llista d'usuaris."
-
-#, fuzzy, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Fi de la lllista - %d/%d resultat(s) mostrat(s)."
-
-#, fuzzy
-msgid "End of forbid list."
-msgstr "Fi de la llista d'usuaris."
-
-#, fuzzy, c-format
-msgid "End of list - %d channels shown."
-msgstr "Fi de la lllista - %d/%d resultat(s) mostrat(s)."
-
-#, c-format
-msgid "End of list - %d/%d matches shown."
-msgstr "Fi de la lllista - %d/%d resultat(s) mostrat(s)."
-
-#, fuzzy
-msgid "End of news list."
-msgstr "Fi de la llista d'usuaris."
-
-#, fuzzy, c-format
-msgid "End of users list. %u users shown."
-msgstr "Fi de la lllista - %d/%d resultat(s) mostrat(s)."
-
-msgid "Enforce various channel modes and set options"
-msgstr ""
-
-msgid ""
-"Enforce various channel modes and set options. The channel\n"
-"option indicates what channel to enforce the modes and options\n"
-"on. The what option indicates what modes and options to\n"
-"enforce, and can be any of SECUREOPS, RESTRICTED, REGONLY, SSLONLY,\n"
-"BANS, or LIMIT.\n"
-" \n"
-"Use SECUREOPS to enforce the SECUREOPS option, even if it is not\n"
-"enabled. Use RESTRICTED to enforce the RESTRICTED option, also\n"
-"if it's not enabled. Use REGONLY to kick all unregistered users\n"
-"from the channel. Use SSLONLY to kick all users not using a secure\n"
-"connection from the channel. BANS will enforce bans on the channel by\n"
-"kicking users affected by them, and LIMIT will kick users until the\n"
-"user count drops below the channel limit, if one is set."
-msgstr ""
-
-msgid "English"
-msgstr "Catala"
-
-#, fuzzy, c-format
-msgid "Entry message %i for %s deleted."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid "Entry message %s not found on channel %s."
-msgstr "Mode fantasia ara activada en el canal %s."
-
-#, fuzzy, c-format
-msgid "Entry message added to %s"
-msgstr "Greet message for %s changed to %s."
-
-#, fuzzy, c-format
-msgid "Entry message list for %s is empty."
-msgstr "Access list for %s is empty."
-
-#, fuzzy, c-format
-msgid "Entry message list for %s:"
-msgstr "Lllista d'accés per %s:"
-
-#, fuzzy, c-format
-msgid "Entry messages for %s have been cleared."
-msgstr "All memos for channel %s have been deleted."
-
-#, fuzzy, c-format
-msgid "Error reloading configuration file: %s"
-msgstr " RELOAD Recarrega la configuració dels serveis"
-
-#, c-format
-msgid ""
-"Error! The vHost ident is too long, please use an ident shorter than %d "
-"characters."
-msgstr ""
-
-#, c-format
-msgid ""
-"Error! The vHost is too long, please use a hostname shorter than %d "
-"characters."
-msgstr ""
-
-msgid ""
-"Examples:\n"
-" \n"
-" CERT ADD\n"
-" Adds your current fingerprint to the certificate list and\n"
-" automatically identifies you when you connect to IRC\n"
-" using this fingerprint.\n"
-" \n"
-" CERT DEL <fingerprint>\n"
-" Removes the fingerprint <fingerprint> from your certificate list.\n"
-" \n"
-" CERT LIST\n"
-" Displays the current certificate list."
-msgstr ""
-
-#, c-format
-msgid "Exception for %s has been updated to %d."
-msgstr "Exception for %s has been updated to %d."
-
-#, fuzzy
-msgid "Expires"
-msgstr "Expires in: %s"
-
-#, fuzzy, c-format
-msgid "Expiry and reason updated for %s."
-msgstr "Exception for %s has been updated to %d."
-
-#, fuzzy, c-format
-msgid "Expiry for %s updated."
-msgstr "Temps d'expiració per a %s canviat."
-
-msgid "Fantasy"
-msgstr "Fantasia"
-
-#, fuzzy, c-format
-msgid "Fantasy mode is now off on channel %s."
-msgstr "Mode fantasia ara activada en el canal %s."
-
-#, fuzzy, c-format
-msgid "Fantasy mode is now on on channel %s."
-msgstr "Mode fantasia ara activada en el canal %s."
-
-#, fuzzy
-msgid "Find a user's status on a channel"
-msgstr " DEOWNER Removes your owner status on a channel"
-
-#, fuzzy, c-format
-msgid "Fingerprint %s already present on %s's certificate list."
-msgstr "La mascara %s ja esta present a la teva lllista d'accés."
-
-#, fuzzy, c-format
-msgid "Fingerprint %s is already in use."
-msgstr "You are already in %s! "
-
-msgid "Flags"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Flags for %s on %s set to +%s"
-msgstr "Nivell d'accés per a %s en %s cambiada a %d."
-
-#, fuzzy, c-format
-msgid "Flags list for %s"
-msgstr "Lllista d'accés per %s:"
-
-#, fuzzy
-msgid "Flood kicker"
-msgstr " Kicker per flood : %s"
-
-msgid ""
-"Forbid allows you to forbid usage of certain nicknames, channels,\n"
-"and email addresses. Wildcards are accepted for all entries."
-msgstr ""
-
-#, fuzzy
-msgid "Forbid list is empty."
-msgstr "La llista ignore esta buida."
-
-#, fuzzy
-msgid "Forbid list:"
-msgstr "Llista de bots:"
-
-#, c-format
-msgid "Forbid on %s was not found."
-msgstr ""
-
-msgid "Forbid usage of nicknames, channels, and emails"
-msgstr ""
-
-#, fuzzy
-msgid "Force the Services databases to be updated immediately"
-msgstr ""
-" UPDATE Força a la base de dades dels serveis a\n"
-" ser actualitzada a disc inmediatament"
-
-#, fuzzy
-msgid "Forcefully change a user's nickname"
-msgstr " SVSNICK Forcefully change a user's nickname"
-
-#, fuzzy
-msgid "Forcefully changes a user's nickname from nick to newnick."
-msgstr ""
-"Syntax: SVSNICK nick newnick\n"
-"\n"
-"Forcefully changes a user's nickname from nick to newnick."
-
-#, fuzzy
-msgid "Forcefully join a user to a channel"
-msgstr " SVSNICK Forcefully change a user's nickname"
-
-#, fuzzy
-msgid "Forcefully join a user to a channel."
-msgstr " SVSNICK Forcefully change a user's nickname"
-
-#, fuzzy
-msgid "Forcefully part a user from a channel"
-msgstr " KICK Kickeja un usuari d'un canal"
-
-#, fuzzy
-msgid "Forcefully part a user from a channel."
-msgstr " KICK Kickeja un usuari d'un canal"
-
-#, fuzzy
-msgid "Founder"
-msgstr "Fundador Segur"
-
-#, fuzzy, c-format
-msgid "Founder of %s changed to %s."
-msgstr "El Fundador de %s cambiat a %s."
-
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "La comanda GETPASS no esta disponible per l'us d'encriptació."
-
-msgid "Ghost with your nick has been killed."
-msgstr "El ghost amb el teu nick ha estat expulsat."
-
-#, fuzzy
-msgid "Give Operflags to a certain user"
-msgstr " OLINE Give Operflags to a certain user"
-
-#, c-format
-msgid ""
-"Gives %s status to the selected nick on a channel. If nick is\n"
-"not given, it will %s you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Gives you or the specified nick %s status on a channel"
-msgstr " OWNER Gives you owner status on channel"
-
-msgid "Greet"
-msgstr "Salutació"
-
-#, fuzzy
-msgid "Greet message displayed on join"
-msgstr "Greet message for %s changed to %s."
-
-#, c-format
-msgid "Greet message for %s changed to %s."
-msgstr "Greet message for %s changed to %s."
-
-#, c-format
-msgid "Greet message for %s unset."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid "Greet mode is now off on channel %s."
-msgstr "Mode salutació ara activat en el canal %s."
-
-#, fuzzy, c-format
-msgid "Greet mode is now on on channel %s."
-msgstr "Mode salutació ara activat en el canal %s."
-
-#, fuzzy
-msgid "Helps you reset lost passwords"
-msgstr " RESETPASS Helps you reset lost passwords."
-
-#, fuzzy
-msgid "Hide certain pieces of nickname information"
-msgstr " HIDE Oculta algunes parts de la teva informació"
-
-#, fuzzy
-msgid "Hide channel from the LIST command"
-msgstr " PRIVATE Oculta el canal de la comanda LIST"
-
-msgid "Host"
-msgstr ""
-
-#, c-format
-msgid "Hosts with at least %d sessions:"
-msgstr "Hosts amb un mínim de %d sessions:"
-
-#, c-format
-msgid "I don't know who %s is."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "I've never seen %s on this channel."
-msgstr "No utilitzis reversos en aquest canal!"
-
-msgid "ID"
-msgstr ""
-
-msgid "INFO [type]"
-msgstr ""
-
-msgid "IP"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "IP %s already exists for %s."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy, c-format
-msgid "IP %s does not exist for %s."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy
-msgid "Identify yourself with your password"
-msgstr " IDENTIFY Per identificar-te amb la teva clau"
-
-#, fuzzy, c-format
-msgid "If you do not change within %s, I will change your nick."
-msgstr "Si no canvies el teu nick en 20 segons, el canviare jo."
-
-msgid "Ignore list has been cleared."
-msgstr "Ignore list has been cleared."
-
-msgid "Ignore list is empty."
-msgstr "La llista ignore esta buida."
-
-#, fuzzy
-msgid "Ignore list:"
-msgstr "Llista de bots:"
-
-#, fuzzy
-msgid "Immediate protection"
-msgstr "Protecció de Voices"
-
-#, fuzzy
-msgid "Incorrect email address."
-msgstr " \t\tAdreça E-mail: %s"
-
-msgid "Incorrect range specified. The correct syntax is #from-to."
-msgstr ""
-
-#, fuzzy
-msgid "Info about a loaded module"
-msgstr " MODINFO Info about a loaded module"
-
-#, c-format
-msgid "Information for bot %s:"
-msgstr "Informació pel bot %s:"
-
-#, fuzzy, c-format
-msgid "Information for channel %s:"
-msgstr "Informació pel bot %s:"
-
-#, c-format
-msgid "Invalid duration %s, using %d days."
-msgstr ""
-
-msgid "Invalid expiry time."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Invalid hostmask. Only real hostmasks are valid, as exceptions are not "
-"matched against nicks or usernames."
-msgstr ""
-"Mascara invalida. Nomès mascares reals son valides ja que excepcions no son "
-"comparades a nicks o usernames."
-
-#, c-format
-msgid "Invalid limit %s, using %d."
-msgstr ""
-
-msgid ""
-"Invalid passcode has been entered, please check the e-mail again, and retry."
-msgstr ""
-
-msgid "Invalid passcode."
-msgstr ""
-
-#, c-format
-msgid ""
-"Invalid session limit. It must be a valid integer greater than or equal to "
-"zero and less than %d."
-msgstr ""
-"Límit de sessió invàlid. Ha de ser un sencer vàlido més gran o igual a zero "
-"i mes petit que %d."
-
-msgid "Invalid threshold value. It must be a valid integer greater than 1."
-msgstr "Valor de umbral invàlid. Ha de ser un sencer vàlid més gran a 1."
-
-msgid "Invalid value for LIMIT. Must be numerical."
-msgstr ""
-
-#, fuzzy
-msgid "Invites you or an optionally specified nick into a channel"
-msgstr " OP Gives Op status to a selected nick on a channel"
-
-#, fuzzy
-msgid "Italics kicker"
-msgstr " Italics kicker : %s"
-
-#, fuzzy
-msgid "Join a group"
-msgstr " GROUP Ingresa en un grup"
-
-#, fuzzy
-msgid "Keep modes"
-msgstr "Mode de missatge"
-
-#, fuzzy, c-format
-msgid "Keep modes for %s is now off."
-msgstr "Peace option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Keep modes for %s is now on."
-msgstr "Peace option for %s is now ON."
-
-msgid "Key"
-msgstr ""
-
-#, c-format
-msgid "Key for channel %s is %s."
-msgstr "Key for channel %s is %s."
-
-#, fuzzy
-msgid "Kick a user from a channel"
-msgstr " KICK Kickeja un usuari d'un canal"
-
-#, c-format
-msgid "Kicked %d/%d users matching %s from %s."
-msgstr ""
-
-#, fuzzy
-msgid "Kicks a specified nick from a channel"
-msgstr " KICK Kicks a selected nick from a channel"
-
-#, fuzzy
-msgid ""
-"Kicks a specified nick from a channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders can also specify masks."
-msgstr ""
-"Sintàxi: KICK #canal nick [raó]\n"
-"\n"
-"Kickeja al nick seleccionat en el canal.\n"
-"\n"
-"Per defecte, limitat a AOPs o aquells amb nivell d'\n"
-"accés 5 i major en el canal."
-
-msgid "Kill a user"
-msgstr ""
-
-msgid "LIMIT enforced by "
-msgstr ""
-
-#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr ""
-
-msgid "LIST threshold"
-msgstr ""
-
-#, fuzzy
-msgid "LIST [mask | list | id]"
-msgstr "LIST [canal] [llista | NEW]"
-
-#, fuzzy
-msgid "LIST [mask | list]"
-msgstr "LIST [canal] [llista | NEW]"
-
-#, fuzzy
-msgid "LIST [nickname]"
-msgstr "CHECK nickname"
-
-msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "LOGONNEWS {ADD|DEL|LIST} [text|numero]"
-
-msgid "Language changed to English."
-msgstr "Llenguatge canviat a Català."
-
-#, fuzzy, c-format
-msgid "Language for %s changed to %s."
-msgstr "Sucessor de %s cambiat a %s."
-
-#, c-format
-msgid "Last memo to %s has been cancelled."
-msgstr "Ultim memo enviat a %s va ser cancel.lat."
-
-#, fuzzy
-msgid "Last quit message"
-msgstr " Ùltim missatge quit: %s"
-
-#, fuzzy
-msgid "Last seen"
-msgstr " Ultima vegada vist: %s"
-
-#, fuzzy
-msgid "Last seen address"
-msgstr "Ultima adreça vista: %s"
-
-msgid "Last topic"
-msgstr ""
-
-#, fuzzy
-msgid "Last used"
-msgstr " Ultima vegada vist: %s"
-
-#, fuzzy
-msgid "Last usermask"
-msgstr " Ultima vegada vist: %s"
-
-msgid "Level"
-msgstr ""
-
-#, c-format
-msgid "Level for %s on channel %s changed to %d."
-msgstr "Nivell per a %s en el canal %s cambiat a %d."
-
-#, c-format
-msgid "Level for %s on channel %s changed to founder only."
-msgstr "Level for %s on channel %s changed to founder only."
-
-#, c-format
-msgid "Level must be between %d and %d inclusive."
-msgstr "El nivell ha d'estar entre %d i %d inclosos."
-
-msgid "Limit"
-msgstr ""
-
-#, fuzzy
-msgid "List all registered nicknames that match a given pattern"
-msgstr ""
-" LIST List all registered nicknames that match a given pattern"
-
-#, fuzzy
-msgid "List channels you have access on"
-msgstr " ALIST List channels you have access on"
-
-#, c-format
-msgid "List for mode %c is full."
-msgstr ""
-
-#, fuzzy
-msgid "List loaded modules"
-msgstr " MODLIST List loaded modules"
-
-#, fuzzy, c-format
-msgid "List of entries matching %s:"
-msgstr "Lllista de nicknames en el grup de %s:"
-
-#, c-format
-msgid "List of nicknames in the group of %s:"
-msgstr "Lllista de nicknames en el grup de %s:"
-
-msgid "List of nicknames in your group:"
-msgstr "Lllista de nicknames en el teu grup:"
-
-#, fuzzy
-msgid "List your memos"
-msgstr " LIST llista els teus memos"
-
-#, fuzzy
-msgid ""
-"Lists all available bots on this network.\n"
-"Bots prefixed by a * are reserved for IRC Operators."
-msgstr ""
-"Sintàxi: BOTLIST\n"
-"\n"
-"Llista tots els bots disponibles en aquesta xarxa."
-
-#, fuzzy
-msgid "Lists all channel records"
-msgstr " CHANLIST Llista tots els records de canal"
-
-#, fuzzy
-msgid ""
-"Lists all channels currently in use on the IRC network, whether they\n"
-"are registered or not.\n"
-" \n"
-"If pattern is given, lists only channels that match it. If a nickname\n"
-"is given, lists only the channels the user using it is on. If SECRET is\n"
-"specified, lists only channels matching pattern that have the +s or\n"
-"+p mode."
-msgstr ""
-"Sintàxi: CHANLIST [{patró | nick} [SECRET]]\n"
-"\n"
-"Llista tots els canals actualment en ús en la xarxa IRC,\n"
-"estiguin registrats o no.\n"
-"\n"
-"Si s'especifica patró, llista nomès els canals que concordin amb ell. \n"
-"Si s'especifica un nickname, llista nomès els canals en els que l'usuari\n"
-"hi sigui. Si s'especifica SECRET, llista nomès els canals que\n"
-"concordin amb patró i que tinguin modes +s o +p.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-msgid ""
-"Lists all channels you have access on.\n"
-" \n"
-"Channels that have the NOEXPIRE option set will be\n"
-"prefixed by an exclamation mark. The nickname parameter is\n"
-"limited to Services Operators"
-msgstr ""
-
-#, fuzzy
-msgid "Lists all nicknames in your group"
-msgstr "Lllista de nicknames en el teu grup:"
-
-#, fuzzy
-msgid "Lists all registered channels matching the given pattern"
-msgstr ""
-" LIST Lists all registered channels matching the given pattern"
-
-#, fuzzy
-msgid ""
-"Lists all registered channels matching the given pattern.\n"
-"Channels with the PRIVATE option set will only be\n"
-"displayed to Services Operators with the proper access.\n"
-"Channels with the NOEXPIRE option set will have\n"
-"a ! prefixed to the channel for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range, channel names\n"
-"are to be written without '#'.\n"
-" \n"
-"If the SUSPENDED or NOEXPIRE options are given, only channels\n"
-"which, respectively, are SUSPENDED or have the NOEXPIRE\n"
-"flag set will be displayed. If multiple options are given,\n"
-"all channels matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *anope*\n"
-" Lists all registered channels with anope in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered channels which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered channels within the given range (51-100)."
-msgstr ""
-"Sintaxis: LIST patró [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\n"
-"\n"
-"Llista tots els nicknames registrats que concordin amb el\n"
-"patró donat, en el format nick!usuari@host. Nicks amb\n"
-"L'opció PRIVATE tan sols sera mostrada a administradors\n"
-"de serveis. Nicks amb l'opció NOEXPIRE establerta tindran\n"
-"un ! avantposat al nickname per a administradors de\n"
-"serveis.\n"
-"\n"
-"If the FORBIDDEN, SUSPENDED, NOEXPIRE or UNCONFIRMED options are given, "
-"only\n"
-"nicks which, respectively, are FORBIDDEN, SUSPENDED, UNCONFIRMED or have "
-"the\n"
-"NOEXPIRE flag set will be displayed. If multiple options are\n"
-"given, all nicks matching at least one option will be displayed.\n"
-"These options are limited to Services Operators. \n"
-"\n"
-"Exemples:\n"
-"\n"
-" LIST *!cistus@aujac.org\n"
-" Llista tots els nicks registrats per cistus@aujac.org.\n"
-"\n"
-" LIST *Bot*!*@*\n"
-" Llista tots els nicks registrats amb Bot en\n"
-" els seus noms. (no sensible a majuscules i minuscules).\n"
-"\n"
-" LIST * NOEXPIRE\n"
-" Llista tots els nicks registrats que hagin estat establerts\n"
-" a no caducitat."
-
-#, fuzzy
-msgid ""
-"Lists all registered nicknames which match the given\n"
-"pattern, in nick!user@host format. Nicks with the PRIVATE\n"
-"option set will only be displayed to Services Operators with the\n"
-"proper access. Nicks with the NOEXPIRE option set will have\n"
-"a ! prefixed to the nickname for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range.\n"
-" \n"
-"If the SUSPENDED, UNCONFIRMED or NOEXPIRE options are given, only\n"
-"nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n"
-"NOEXPIRE flag set will be displayed. If multiple options are\n"
-"given, all nicks matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *!joeuser@foo.com\n"
-" Lists all registered nicks owned by joeuser@foo.com.\n"
-" \n"
-" LIST *Bot*!*@*\n"
-" Lists all registered nicks with Bot in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered nicks which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered nicks within the given range (51-100)."
-msgstr ""
-"Sintaxis: LIST patró [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\n"
-"\n"
-"Llista tots els nicknames registrats que concordin amb el\n"
-"patró donat, en el format nick!usuari@host. Nicks amb\n"
-"L'opció PRIVATE tan sols sera mostrada a administradors\n"
-"de serveis. Nicks amb l'opció NOEXPIRE establerta tindran\n"
-"un ! avantposat al nickname per a administradors de\n"
-"serveis.\n"
-"\n"
-"If the FORBIDDEN, SUSPENDED, NOEXPIRE or UNCONFIRMED options are given, "
-"only\n"
-"nicks which, respectively, are FORBIDDEN, SUSPENDED, UNCONFIRMED or have "
-"the\n"
-"NOEXPIRE flag set will be displayed. If multiple options are\n"
-"given, all nicks matching at least one option will be displayed.\n"
-"These options are limited to Services Operators. \n"
-"\n"
-"Exemples:\n"
-"\n"
-" LIST *!cistus@aujac.org\n"
-" Llista tots els nicks registrats per cistus@aujac.org.\n"
-"\n"
-" LIST *Bot*!*@*\n"
-" Llista tots els nicks registrats amb Bot en\n"
-" els seus noms. (no sensible a majuscules i minuscules).\n"
-"\n"
-" LIST * NOEXPIRE\n"
-" Llista tots els nicks registrats que hagin estat establerts\n"
-" a no caducitat."
-
-#, fuzzy
-msgid "Lists all user records"
-msgstr " USERLIST Llista tots els records d'usuaris"
-
-#, fuzzy
-msgid ""
-"Lists all users currently online on the IRC network, whether their\n"
-"nick is registered or not.\n"
-" \n"
-"If pattern is given, lists only users that match it (it must be in\n"
-"the format nick!user@host[#realname]). If channel is given, lists\n"
-"only users that are on the given channel. If INVISIBLE is specified, only "
-"users\n"
-"with the +i flag will be listed."
-msgstr ""
-"Sintàxi: USERLIST [{patró | canal} [INVISIBLE]]\n"
-"\n"
-"Llista tots els usuaris actualment en linea en la xarxa IRC,\n"
-"estiguin registrats o no.\n"
-"\n"
-"Si s'especifica patró, llista nomès els usuaris que concordin\n"
-"amb ell (ha de ser amb el format nick!usuari@host). Si s'especifica canal,\n"
-"llista nomès els usuaris que estiguin en el canal donat. Si s'especifica\n"
-"INVISIBLE, nomès els usuaris amb la bandera +i seran\n"
-"llistats.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Lists any memos you currently have. With NEW, lists only\n"
-"new (unread) memos. Unread memos are marked with a \"*\"\n"
-"to the left of the memo number. You can also specify a list\n"
-"of numbers, as in the example below:\n"
-" LIST 2-5,7-9\n"
-" Lists memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Sintàxi: LIST [canal] [llista | NEW]\n"
-"\n"
-"llista els memos que tens actualment. Amb NEW, llista\n"
-"només els memos nous (no llegits). Memos nous estan\n"
-"marcats amb un \"*\" a l'esquerra del nobre del memo.\n"
-"També pots especificar una llista de nombres, com en el\n"
-"exemple més endevant:\n"
-"\n"
-" LIST 2-5,7-9\n"
-" llista memos enumerats 2 a 5 i 7 a 9."
-
-#, fuzzy
-msgid "Lists available bots"
-msgstr "BOTLIST Llista bots disponibles"
-
-#, fuzzy
-msgid "Lists currently loaded modules."
-msgstr " MODLIST List loaded modules"
-
-#, fuzzy
-msgid "Lists information about the specified registered channel"
-msgstr " INFO Lists information about the named registered channel"
-
-#, fuzzy
-msgid ""
-"Lists information about the specified registered channel,\n"
-"including its founder, time of registration, last\n"
-"time used, and description. If the user issuing the\n"
-"command has the appropriate access for it, then the\n"
-"successor, last topic set, settings and expiration\n"
-"time will also be displayed when applicable."
-msgstr ""
-"Sintàxi: INFO canal\n"
-"\n"
-"llista informació sobre el canal registrat donat,\n"
-"incloent el seu fundador, temps de registració, últim\n"
-"cop utilitzat, descripció i fixació de Modes, si existeixen.\n"
-"Si ALL és especificat, el misatge d'entrada i\n"
-"sucsesor també seran mostrats."
-
-#, fuzzy
-msgid "Load a module"
-msgstr " MODLOAD Load a module"
-
-msgid "Local channels cannot be registered."
-msgstr "Canals locals no poden ser enregistrats."
-
-#, fuzzy, c-format
-msgid "Log list for %s:"
-msgstr "Lllista d'accés per %s:"
-
-#, c-format
-msgid "Logging changed for command %s on %s, now using log method %s%s%s."
-msgstr ""
-
-#, c-format
-msgid "Logging for command %s on %s with log method %s%s%s has been removed."
-msgstr ""
-
-#, c-format
-msgid "Logging is now active for command %s on %s, using log method %s%s%s."
-msgstr ""
-
-#, c-format
-msgid "Login to %s"
-msgstr ""
-
-#, c-format
-msgid "Logon news item #%d deleted."
-msgstr "Notícia d'entrada #%d esborrada."
-
-#, fuzzy, c-format
-msgid "Logon news item #%s not found!"
-msgstr "Notícia d'entrada #%d no trobada!"
-
-msgid "Logon news items:"
-msgstr "Notícies d'entrada:"
-
-#, fuzzy, c-format
-msgid "Logout from %s"
-msgstr "Lllista d'accés per %s:"
-
-#, c-format
-msgid ""
-"Logs you in to %s so you gain Services Operator privileges.\n"
-"This command may be unnecessary if your oper block is\n"
-"configured without a password."
-msgstr ""
-
-#, c-format
-msgid ""
-"Logs you out from %s so you lose Services Operator privileges.\n"
-"This command is only useful if your oper block is configured\n"
-"with a password."
-msgstr ""
-
-#, c-format
-msgid "Looking for yourself, eh %s?"
-msgstr ""
-
-#, c-format
-msgid ""
-"Mainly controls mode locks and mode access (which is different from channel "
-"access)\n"
-"on a channel.\n"
-" \n"
-"The %s LOCK command allows you to add, delete, and view mode locks on a "
-"channel.\n"
-"If a mode is locked on or off, services will not allow that mode to be "
-"changed. The SET\n"
-"command will clear all existing mode locks and set the new one given, while "
-"ADD and DEL\n"
-"modify the existing mode lock.\n"
-"Example:\n"
-" MODE #channel LOCK ADD +bmnt *!*@*aol*\n"
-" \n"
-"The %s SET command allows you to set modes through services. Wildcards * "
-"and ? may\n"
-"be given as parameters for list and status modes.\n"
-"Example:\n"
-" MODE #channel SET +v *\n"
-" Sets voice status to all users in the channel.\n"
-" \n"
-" MODE #channel SET -b ~c:*\n"
-" Clears all extended bans that start with ~c:\n"
-" \n"
-"The %s CLEAR command is an easy way to clear modes on a channel. what may "
-"be\n"
-"any mode name. Examples include bans, excepts, inviteoverrides, ops, "
-"halfops, and voices. If what\n"
-"is not given then all basic modes are removed."
-msgstr ""
-
-#, fuzzy
-msgid "Maintain the AutoKick list"
-msgstr " AKICK Manté la llista d'AutoKick"
-
-#, fuzzy
-msgid "Maintains network bot list"
-msgstr "BOT Manté la llista de bots de la xarxa"
-
-#, c-format
-msgid ""
-"Maintains the %s list for a channel. Users who match an access entry\n"
-"on the %s list receive the following privileges:\n"
-" "
-msgstr ""
-
-#, c-format
-msgid ""
-"Maintains the AutoKick list for a channel. If a user\n"
-"on the AutoKick list attempts to join the channel,\n"
-"%s will ban that user from the channel, then kick\n"
-"the user.\n"
-" \n"
-"The AKICK ADD command adds the given nick or usermask\n"
-"to the AutoKick list. If a reason is given with\n"
-"the command, that reason will be used when the user is\n"
-"kicked; if not, the default reason is \"User has been\n"
-"banned from the channel\".\n"
-"When akicking a registered nick the %s account\n"
-"will be added to the akick list instead of the mask.\n"
-"All users within that nickgroup will then be akicked.\n"
-msgstr ""
-
-#, c-format
-msgid ""
-"Maintains the access list for a channel. The access\n"
-"list specifies which users are allowed chanop status or\n"
-"access to %s commands on the channel. Different\n"
-"user levels allow for access to different subsets of\n"
-"privileges. Any registered user not on the access list has\n"
-"a user level of 0, and any unregistered user has a user level\n"
-"of -1."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Maintains the bad words list for a channel. The bad\n"
-"words list determines which words are to be kicked\n"
-"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
-" \n"
-"The ADD command adds the given word to the\n"
-"bad words list. If SINGLE is specified, a kick will be\n"
-"done only if a user says the entire word. If START is\n"
-"specified, a kick will be done if a user says a word\n"
-"that starts with word. If END is specified, a kick\n"
-"will be done if a user says a word that ends with\n"
-"word. If you don't specify anything, a kick will\n"
-"be issued every time word is said by a user.\n"
-" \n"
-msgstr ""
-"Sintàxi: BADWORDS canal ADD paraula [SINGLE | START | END]\n"
-" BADWORDS canal DEL {paraula | nom | llista}\n"
-" BADWORDS canal LIST [mascara | llista]\n"
-" BADWORDS canal CLEAR\n"
-"\n"
-"Mante la llista de paraules malsonants per un canal. La llista\n"
-"de paraules malsonants determina quines paraules han de donar peu a ser "
-"kickejats\n"
-"Quan el kick per paraules malsonants esta habilitat. Per més\n"
-"informació, escriu /msg %s HELP KICK BADWORDS.\n"
-"\n"
-"La comanda BADWORDS ADD afegeix una paraula a la llista\n"
-"de paraules malsonants. Si s'especifica SINGLE, el kick es\n"
-"fara nomès si l'usuari du la paraula completa. Si s'especifica\n"
-"START, el kick es fara nomès si l'usuari\n"
-"escriu una paraula que comenci amb paraula.\n"
-"Si no s'especifica END, el kick es fara nomès si\n"
-"l'usuari escriu una paraula que finalitzi amb paraula. Si\n"
-"no s'especifica res, un kick es farà cada vegada que\n"
-"paraula sigui escrita per un usuari.\n"
-"\n"
-"La comanda BADWORDS DEL esborra la paraula esmantada de la\n"
-"llista de paraules malsonants. Si s'especifica una llista de noms, aquestes\n"
-"instàncies son esborrades. (Veure l'exemple per LIST especificat més\n"
-"endavant).\n"
-"\n"
-"La comanda BADWORDS LIST mostra la llista de bad\n"
-"words. Si s'especifica una mascara, nomès les instàncies\n"
-"concordant amb la mascara són mostrades. Si s'especifica una llista\n"
-"de noms, nomès aquestes instàncies son mostrades;\n"
-"per exemple:\n"
-"\n"
-" BADWORDS #canal LIST 2-5,7-9\n"
-" Llista paraules malsonants enumerades de 2 a 5 i de 7 a 9.\n"
-" \n"
-"La comanda BADWORDS CLEAR neteja totes les instàncies\n"
-"de la llista de paraules malsonants."
-
-#, fuzzy
-msgid "Maintains the bad words list"
-msgstr "BADWORDS Manté una llista de paraules malsonants"
-
-#, fuzzy
-msgid "Makes the bot do the equivalent of a \"/me\" command"
-msgstr ""
-"ACT Makes the bot do the equivalent of a \"/me\" command"
-
-#, fuzzy
-msgid ""
-"Makes the bot do the equivalent of a \"/me\" command\n"
-"on the specified channel using the specified text."
-msgstr ""
-"Sintàxi: ACT canal text\n"
-"\n"
-"Fa que el bot fagi l'equivalent a la comanda \"/me\"\n"
-"en el canal especificat utilitzant el text especificat."
-
-#, fuzzy
-msgid "Makes the bot say the specified text on the specified channel"
-msgstr ""
-"SAY Makes the bot say the given text on the given channel"
-
-#, fuzzy
-msgid "Makes the bot say the specified text on the specified channel."
-msgstr ""
-"SAY Makes the bot say the given text on the given channel"
-
-#, fuzzy
-msgid ""
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary\n"
-"access on it."
-msgstr ""
-"Syntax: SASET nickname GREET message\n"
-"\n"
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary \n"
-"access on it."
-
-#, fuzzy
-msgid ""
-"Makes the given message the greet of your nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that you have the necessary\n"
-"access on it."
-msgstr ""
-"Sintaxis: SET GREET missatge\n"
-"\n"
-"Fa que el missatge introduit sigui la salutació pel teu nickname, \n"
-"el que sera mostrat quant entris a un canal amb la\n"
-"opció GREET habilitada, sempre i quant tinguis \n"
-"l'accés necessari."
-
-#, fuzzy
-msgid "Manage DNS zones for this network"
-msgstr "No pots establir la teva adreça e-mail en aquesta xarxa."
-
-#, fuzzy
-msgid "Manage the channel's entry messages"
-msgstr " PERSIST Set the channel as permanent"
-
-#, fuzzy
-msgid "Manage the memo ignore list"
-msgstr " IGNORE Modify the Services ignore list"
-
-#, fuzzy
-msgid "Manage your auto join list"
-msgstr " AKICK Manté la llista d'AutoKick"
-
-#, fuzzy, c-format
-msgid "Manipulate the %s list"
-msgstr " AKILL Manipula la llista AKILL"
-
-#, fuzzy
-msgid "Manipulate the AKILL list"
-msgstr " AKILL Manipula la llista AKILL"
-
-#, fuzzy
-msgid "Manipulate the DefCon system"
-msgstr " DEFCON Manipulate the DefCon system"
-
-#, fuzzy
-msgid "Manipulate the topic of the specified channel"
-msgstr " TOPIC Manipulate the topic of the specified channel"
-
-msgid "Mask"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "La mascara %s ja esta present a la teva lllista d'accés."
-
-msgid "Mask must be in the form user@host."
-msgstr ""
-
-#, fuzzy
-msgid "Masks and unregistered users may not be on access lists."
-msgstr "La mascara %s ja esta present a la teva lllista d'accés."
-
-#, fuzzy
-msgid "Matches and returns all users that registered using given email"
-msgstr ""
-" GETEMAIL Matches and returns all users that registered using given "
-"email"
-
-#, fuzzy, c-format
-msgid "Matches for %s:"
-msgstr " Mode de lock: %s"
-
-#, c-format
-msgid "Maximum users: %d (%s)"
-msgstr "Màxim numero d'usuaris: %d (%s)"
-
-#, fuzzy, c-format
-msgid "Memo %d from %s (%s)."
-msgstr " Mode de lock: %s"
-
-#, c-format
-msgid "Memo %d has been deleted."
-msgstr "Memo %d ha estat esborrat."
-
-#, fuzzy
-msgid "Memo ignore list is empty."
-msgstr "La llista ignore esta buida."
-
-#, c-format
-msgid "Memo limit disabled for %s."
-msgstr "Límit de memos per a %s deshabilitat."
-
-#, c-format
-msgid "Memo limit for %s set to %d."
-msgstr "Límite de memos per a %s establert a %d."
-
-#, c-format
-msgid "Memo limit for %s set to 0."
-msgstr "Límit de memos per a %s establert a 0."
-
-#, c-format
-msgid "Memo sent to %s."
-msgstr "Memo enviat a %s."
-
-#, fuzzy, c-format
-msgid "Memos for %s:"
-msgstr " Mode de lock: %s"
-
-#, fuzzy
-msgid "Message"
-msgstr "GLOBAL missatge"
-
-msgid "Message mode"
-msgstr "Mode de missatge"
-
-msgid "Method"
-msgstr ""
-
-#, c-format
-msgid "Missing parameter for mode %c."
-msgstr ""
-
-msgid "Mode"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Mode %s is a virtual mode and can't be cleared."
-msgstr "Nick %s is an illegal nickname and cannot be used."
-
-#, fuzzy, c-format
-msgid "Mode %s is not a status or list mode."
-msgstr "%s not found on ignore list."
-
-#, fuzzy
-msgid "Mode lock"
-msgstr " Mode de lock: %s"
-
-#, fuzzy, c-format
-msgid "Mode locks for %s:"
-msgstr " Mode de lock: %s"
-
-msgid "Modes"
-msgstr ""
-
-#, c-format
-msgid "Modes cleared on %s and the channel destroyed."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
-msgstr ""
-"Sintaxis: ACCESS ADD mascara\n"
-" ACCESS DEL mascara\n"
-" ACCESS LIST\n"
-"\n"
-"Modifica o mostra la llista d'accés pel teu nick. Aquesta\n"
-"és la llista d'adreces que seran automaticament\n"
-"reconegudes per %s com autoritzades a utilitzar el nick. Si\n"
-"vols utilitzar el nick des d'una adreça diferent,\n"
-"has d'enviar una comanda IDENTIFY per fer que %s et\n"
-"reconegui.\n"
-"\n"
-"Exemples:\n"
-"\n"
-" ACCESS ADD anyone@*.aujac.org\n"
-" Permet accés a l'usuari anyone des de\n"
-" qualsevol maquina en el domini aujac.org.\n"
-"\n"
-" ACCESS DEL anyone@*.aujac.org\n"
-" Anul.la la comanda anterior.\n"
-"\n"
-" ACCESS LIST\n"
-" Mostra la llista d'accés actual."
-
-msgid ""
-"Modifies or displays the certificate list for your nick.\n"
-"If you connect to IRC and provide a client certificate with a\n"
-"matching fingerprint in the cert list, you will be\n"
-"automatically identified to services. Services Operators\n"
-"may provide a nick to modify other users' certificate lists.\n"
-" \n"
-msgstr ""
-
-#, fuzzy
-msgid "Modify the Services ignore list"
-msgstr " IGNORE Modify the Services ignore list"
-
-#, fuzzy, c-format
-msgid "Modify the list of %s users"
-msgstr " AOP Modifica la llista d'usuaris AOP"
-
-#, fuzzy
-msgid "Modify the list of authorized addresses"
-msgstr " ACCESS Modifica la llista d'adreçes autoritzades"
-
-#, fuzzy
-msgid "Modify the list of privileged users"
-msgstr " ACCESS Modifica la llista d'usuaris privilegiats"
-
-#, fuzzy
-msgid "Modify the nickname client certificate list"
-msgstr " IGNORE Modify the Services ignore list"
-
-#, fuzzy
-msgid "Modify the session-limit exception list"
-msgstr " EXCEPTION Modifica la llista de límit de sessió"
-
-#, c-format
-msgid "Module %s is already loaded."
-msgstr "Module %s is already loaded."
-
-#, c-format
-msgid "Module %s isn't loaded."
-msgstr "Module %s isn't loaded."
-
-#, fuzzy, c-format
-msgid "Module %s loaded."
-msgstr "Module %s loaded"
-
-#, fuzzy, c-format
-msgid "Module %s reloaded."
-msgstr "Module %s loaded"
-
-#, fuzzy, c-format
-msgid "Module %s unloaded."
-msgstr "Module %s unloaded"
-
-#, fuzzy
-msgid "Module Name"
-msgstr "Module %s loaded"
-
-msgid "Module settings:"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Module: %s Version: %s Author: %s Loaded: %s"
-msgstr "Module: %s Version: %s Author: %s loaded: %s"
-
-#, c-format
-msgid "Module: %s [%s] [%s]"
-msgstr "Module: %s [%s] [%s]"
-
-msgid "Name"
-msgstr ""
-
-msgid "Name Type"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Network stats for %s:"
-msgstr "Lllista d'accés per %s:"
-
-msgid "Never"
-msgstr ""
-
-#, fuzzy
-msgid "Nick"
-msgstr "INFO nick"
-
-#, fuzzy, c-format
-msgid "Nick %s has been confirmed."
-msgstr "Nickname %s ha estat expulsat."
-
-#, fuzzy, c-format
-msgid "Nick %s is already an operator."
-msgstr "El nickname %s ja esta registrat!"
-
-#, fuzzy, c-format
-msgid "Nick %s is already confirmed."
-msgstr "El nickname %s ja esta registrat!"
-
-#, c-format
-msgid "Nick %s is an illegal nickname and cannot be used."
-msgstr "Nick %s is an illegal nickname and cannot be used."
-
-#, c-format
-msgid "Nick %s is currently in use."
-msgstr "Nick %s is currently in use."
-
-#, fuzzy, c-format
-msgid "Nick %s is forbidden by %s: %s"
-msgstr "Nick %s is currently in use."
-
-#, fuzzy, c-format
-msgid "Nick %s is forbidden."
-msgstr "El nick %s no esta sent utilitzat."
-
-#, fuzzy, c-format
-msgid "Nick %s is not a Services Operator."
-msgstr "%s is a services operator of type %s."
-
-#, c-format
-msgid "Nick %s is part of this Network's Services."
-msgstr "Nick %s is part of this Network's Services."
-
-#, fuzzy, c-format
-msgid "Nick %s isn't currently in use."
-msgstr "Nick %s is currently in use."
-
-#, fuzzy, c-format
-msgid "Nick %s isn't registered."
-msgstr "Nickname %s registered."
-
-#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Nick %s was truncated to %d characters."
-
-#, c-format
-msgid "Nick %s will expire."
-msgstr "Nick %s will expire."
-
-#, c-format
-msgid "Nick %s will not expire."
-msgstr "Nick %s will not expire."
-
-#, c-format
-msgid "Nick %s doesn't have a memo from you."
-msgstr "Nick %s doesn't have a memo from you."
-
-#, c-format
-msgid "Nick %s has been logged out."
-msgstr "Nick %s ha estat desconnectat."
-
-#, c-format
-msgid "Nick %s has been ungrouped from %s."
-msgstr "Nick %s has been ungrouped from %s."
-
-#, fuzzy, c-format
-msgid "Nick %s is currently suspended."
-msgstr "Nick %s is now suspended."
-
-#, fuzzy, c-format
-msgid "Nick %s is not in your group."
-msgstr "The nick %s is not in your group."
-
-#, fuzzy, c-format
-msgid "Nick %s is not suspended."
-msgstr "Nick %s is now suspended."
-
-#, c-format
-msgid "Nick %s is now released."
-msgstr "Nick %s is now released."
-
-#, c-format
-msgid "Nick %s is now suspended."
-msgstr "Nick %s is now suspended."
-
-#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr ""
-
-#, c-format
-msgid "Nickname %s has been dropped."
-msgstr "Nickname %s ha estat expulsat."
-
-#, fuzzy, c-format
-msgid "Nickname %s is already registered!"
-msgstr "El canal %s ja esta enregistrat!"
-
-#, fuzzy, c-format
-msgid "Nickname %s may not be registered."
-msgstr "El canal %s no pot ser enregistrat."
-
-#, fuzzy, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr "El nickname %s ja esta registrat sota el teu compte: %s"
-
-#, fuzzy, c-format
-msgid "Nickname %s registered."
-msgstr "Nickname %s registered."
-
-#, fuzzy
-msgid "No auto-op"
-msgstr "Auto-op"
-
-msgid "No bot"
-msgstr "Sense bot"
-
-#, fuzzy
-msgid "No expire"
-msgstr "no expira"
-
-#, c-format
-msgid "No help available for %s."
-msgstr "No existeix ajuda per %s."
-
-#, fuzzy, c-format
-msgid "No information about module %s is available."
-msgstr "No information about module %s is available"
-
-#, fuzzy, c-format
-msgid "No limit is set on %s."
-msgstr "Límite de memos per a %s establert a %d."
-
-msgid "No logon news items to delete!"
-msgstr "No hi ha notícies d'entrada per a esborrar!"
-
-#, fuzzy, c-format
-msgid "No matches for %s found."
-msgstr "No Emails listed for %s."
-
-#, fuzzy, c-format
-msgid "No matching entries on %s %s list."
-msgstr "No existeixen instàncies coincidents a la llista AOP de %s."
-
-#, c-format
-msgid "No matching entries on %s access list."
-msgstr "No hi ha instàncies que concordin a la llista d'accés de %s ."
-
-#, c-format
-msgid "No matching entries on %s autokick list."
-msgstr ""
-"No existeixen instàncies que concordin a la llista de kicks automàtics en el "
-"canal %s."
-
-#, c-format
-msgid "No matching entries on %s bad words list."
-msgstr ""
-"No existeixen paraules que concordin a la llista de paraules malsonants de "
-"%s."
-
-msgid "No matching entries on session-limit exception list."
-msgstr ""
-"No existeixen instàncies similars a la llista d'excepcions al límit de "
-"sessions."
-
-#, fuzzy, c-format
-msgid "No matching entries on the %s list."
-msgstr "No existeixen instàncies coincidents a la llista AOP de %s."
-
-msgid "No matching entries on the AKILL list."
-msgstr "No existeixen instàncies similars a la llista de AKILLs."
-
-msgid "No memo was cancelable."
-msgstr "Cap memo pot ser cancelat."
-
-msgid "No memos to display."
-msgstr ""
-
-#, fuzzy
-msgid "No modules currently loaded matching that criteria."
-msgstr "No modules currently loaded"
-
-msgid "No one is using your nick, and services are not holding it."
-msgstr ""
-
-msgid "No oper block for your nick."
-msgstr ""
-
-msgid "No oper news items to delete!"
-msgstr "No hi ha notícies de oper per esborrar!"
-
-msgid "No random news items to delete!"
-msgstr "No hi ha notícies a l'atzar per esborrar!"
-
-msgid "No records to display."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "No registrations matching %s were found."
-msgstr "* No new nick registrations"
-
-#, c-format
-msgid "No request for nick %s found."
-msgstr ""
-
-msgid "No signed kick when SIGNKICK LEVEL is used"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "No stats for %s."
-msgstr "Lllista d'accés per %s:"
-
-#, fuzzy, c-format
-msgid "No such info \"%s\" on %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "No users on %s match %s."
-msgstr "Changed usermodes of %s."
-
-#, fuzzy, c-format
-msgid "No-bot mode is now off on channel %s."
-msgstr "Mode no bot ara activat en el canal %s."
-
-#, fuzzy, c-format
-msgid "No-bot mode is now on on channel %s."
-msgstr "Mode no bot ara activat en el canal %s."
-
-#, c-format
-msgid "Non-status modes cleared on %s."
-msgstr ""
-
-msgid "None"
-msgstr "Cap"
-
-#, c-format
-msgid ""
-"Note, however, if the successor already has too many\n"
-"channels registered (%d), they will not be able to\n"
-"become the new founder and it will be as if the\n"
-"channel had no successor set."
-msgstr ""
-
-msgid "Nothing to do."
-msgstr ""
-
-msgid "Number"
-msgstr ""
-
-msgid "OPERNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "OPERNEWS {ADD|DEL|LIST} [texto|numero]"
-
-#, fuzzy
-msgid "Online from"
-msgstr " Esta en linea desde: %s"
-
-#, c-format
-msgid ""
-"Oper %s is configured in the configuration file(s) and can not be removed by "
-"this command."
-msgstr ""
-
-msgid "Oper Info"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Oper info list for %s is empty."
-msgstr "Access list for %s is empty."
-
-#, c-format
-msgid "Oper news item #%d deleted."
-msgstr "Noticia de oper #%d esborrada."
-
-#, fuzzy, c-format
-msgid "Oper news item #%s not found!"
-msgstr "Noticia de oper #%d no trobada!"
-
-msgid "Oper news items:"
-msgstr "notícies de oper:"
-
-#, c-format
-msgid "Oper privileges removed from %s (%s)."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Oper type %s has not been configured."
-msgstr "Nickname %s ha estat expulsat."
-
-#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "An O:Line with the flags %s has been added for %s."
-
-#, fuzzy, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "An O:Line with the flags %s has been added for %s."
-
-#, c-format
-msgid "Opertype %s has no allowed commands."
-msgstr ""
-
-#, c-format
-msgid "Opertype %s has no allowed privileges."
-msgstr ""
-
-#, c-format
-msgid "Opertype %s receives modes %s once identified."
-msgstr ""
-
-msgid "Ops protection"
-msgstr "Protecció de Ops"
-
-#, fuzzy
-msgid "Options"
-msgstr " Opcions : %s"
-
-#, fuzzy
-msgid "POOL server.name"
-msgstr "NOOP {SET|REVOKE} servidor"
-
-msgid "Param"
-msgstr ""
-
-msgid "Password accepted - you are now recognized."
-msgstr "Clau aceptada - Has estat reconegut."
-
-#, fuzzy
-msgid "Password accepted."
-msgstr "Clau incorrecta."
-
-msgid "Password authentication required for that command."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Password for %s changed to %s."
-msgstr "Sucessor de %s cambiat a %s."
-
-#, fuzzy, c-format
-msgid "Password for %s changed."
-msgstr "La clau de %s ha estat enviada."
-
-#, c-format
-msgid "Password for %s is %s."
-msgstr "La clau per %s es %s."
-
-#, fuzzy
-msgid "Password incorrect."
-msgstr "Clau incorrecta."
-
-#, c-format
-msgid "Password reset email for %s has been sent."
-msgstr "Password reset email for %s has been sent."
-
-msgid "Peace"
-msgstr "Pau"
-
-#, fuzzy, c-format
-msgid "Peace option for %s is now off."
-msgstr "Peace option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Peace option for %s is now on."
-msgstr "Peace option for %s is now ON."
-
-#, fuzzy
-msgid "Persistent"
-msgstr "Persistant"
-
-msgid "Please contact an Operator to get a vHost assigned to this nick."
-msgstr ""
-
-msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab "
-"characters."
-msgstr ""
-
-#, fuzzy
-msgid "Please use a valid server name when juping."
-msgstr "Please use a valid server name when juping"
-
-msgid "Please use the symbol of # when attempting to register."
-msgstr ""
-
-#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Per favor espera %d segons i intenta un altre cop."
-
-#, fuzzy, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr ""
-"Per favor espera %d segons abans d'utilizar la comanda SEND un altre cop."
-
-#, fuzzy, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr ""
-"Per favor espera %d segons abans d'utilizar la comanda SEND un altre cop."
-
-#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr ""
-"Per favor espera %d segons abans d'utilitzar la comanda GROUP novament."
-
-#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr ""
-"Per favor espera %d segons abans d'utilitzar la comanda REGISTER novament."
-
-#, c-format
-msgid "Pooled %s."
-msgstr ""
-
-msgid "Pooled/Active"
-msgstr ""
-
-msgid "Pooled/Not Active"
-msgstr ""
-
-msgid "Prevent a bot from being assigned by non IRC operators"
-msgstr ""
-
-#, fuzzy
-msgid "Prevent a bot from being assigned to a channel"
-msgstr ""
-" SUSPEND Prevent a channel from being used preserving\n"
-" channel data and settings"
-
-#, fuzzy
-msgid "Prevent a channel from being used preserving channel data and settings"
-msgstr ""
-" SUSPEND Prevent a channel from being used preserving\n"
-" channel data and settings"
-
-#, fuzzy
-msgid "Prevent the channel from expiring"
-msgstr " NOEXPIRE Prevent the channel from expiring"
-
-#, fuzzy
-msgid "Prevent the nickname from appearing in the LIST command"
-msgstr ""
-" PRIVATE Prevent the nickname from appearing in a\n"
-" /msg %s LIST"
-
-#, fuzzy
-msgid "Prevent the nickname from expiring"
-msgstr " NOEXPIRE Prevent the nickname from expiring"
-
-msgid "Prevents users being kicked by Services"
-msgstr ""
-
-msgid "Private"
-msgstr "Privat"
-
-#, fuzzy, c-format
-msgid "Private mode of bot %s is now off."
-msgstr "Mode privado del bot %s esta ara activat."
-
-#, fuzzy, c-format
-msgid "Private mode of bot %s is now on."
-msgstr "Mode privado del bot %s esta ara activat."
-
-#, fuzzy, c-format
-msgid "Private option for %s is now off."
-msgstr "Private option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Private option for %s is now on."
-msgstr "Private option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Private option is now off for %s."
-msgstr "Private option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Private option is now on for %s."
-msgstr "Private option is now ON for %s."
-
-#, c-format
-msgid "Privilege %s added to %s on %s, new flags are +%s"
-msgstr ""
-
-#, c-format
-msgid "Privilege %s removed from %s on %s, new flags are +%s"
-msgstr ""
-
-msgid "Protection"
-msgstr "Protecció"
-
-#, fuzzy, c-format
-msgid "Protection is now off for %s."
-msgstr "Protection is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s, with a reduced delay."
-msgstr "Protection is now ON for %s, with a reduced delay."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s, with no delay."
-msgstr "Protection is now ON for %s, with no delay."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s."
-msgstr "Protection is now ON for %s."
-
-#, fuzzy
-msgid ""
-"Puts an AKILL for every nick on the specified channel. It\n"
-"uses the entire real ident@host for every nick, and\n"
-"then enforces the AKILL."
-msgstr ""
-"Syntax: CHANKILL [+expiry] channel reason\n"
-"Puts an AKILL for every nick on the specified channel. It\n"
-"uses the entire and complete real ident@host for every nick,\n"
-"then enforces the AKILL. "
-
-#, fuzzy
-msgid "Quick protection"
-msgstr "Protecció de Voices"
-
-msgid "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "RANDOMNEWS {ADD|DEL|LIST} [text|numero]"
-
-msgid "REGONLY enforced by "
-msgstr ""
-
-msgid "RESTRICTED enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "REVOKE server"
-msgstr "NOOP {SET|REVOKE} servidor"
-
-#, c-format
-msgid "Random news item #%d deleted."
-msgstr "Notícia a l'atzar #%d esborrada."
-
-#, fuzzy, c-format
-msgid "Random news item #%s not found!"
-msgstr "Noticia a l'atzar #%d no trobada!"
-
-msgid "Random news items:"
-msgstr "Notícies al Azar:"
-
-#, fuzzy
-msgid "Read a memo or memos"
-msgstr " READ Llegeix un o més memos"
-
-#, fuzzy
-msgid "Real name"
-msgstr " Nom real : %s"
-
-#, fuzzy
-msgid "Realname"
-msgstr " Nom real : %s"
-
-msgid "Reason"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Reason for %s updated."
-msgstr "Sucessor de %s desabilitat."
-
-msgid ""
-"Recovers your nick from another user or from services.\n"
-"If services are currently holding your nick, the hold\n"
-"will be released. If another user is holding your nick\n"
-"and is identified they will be killed (similar to the old\n"
-"GHOST command). If they are not identified they will be\n"
-"forced off of the nick."
-msgstr ""
-
-#, fuzzy
-msgid "Redefine the meanings of access levels"
-msgstr " LEVELS Redefine el significat de nivells d'accés"
-
-#, fuzzy
-msgid "Regains control of your nick"
-msgstr " RELEASE Repren possesió del teu nick després de RECOVER"
-
-#, fuzzy
-msgid "Regex is disabled."
-msgstr "%s is enable"
-
-#, c-format
-msgid ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your mask in // if this is desired."
-msgstr ""
-
-#, c-format
-msgid ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your pattern in // if this is desired."
-msgstr ""
-
-#, fuzzy
-msgid "Register a channel"
-msgstr " REGISTER Registra un nickname"
-
-#, fuzzy
-msgid "Register a nickname"
-msgstr " REGISTER Registra un nickname"
-
-#, fuzzy
-msgid "Registered"
-msgstr " Temps registrat: %s"
-
-#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered only enforced on %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which is optional, is a\n"
-"general description of the channel's purpose.\n"
-" \n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel."
-msgstr ""
-"Sintaxis: REGISTER canal descripció\n"
-"\n"
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which must be included, is a\n"
-"general description of the channel's purpose.\n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel.\n"
-"See the ACCESS command (/msg %s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname. If you haven't,\n"
-"/msg %s HELP for information on how to do so."
-
-#, fuzzy, c-format
-msgid ""
-"Registers your nickname in the %s database. Once\n"
-"your nick is registered, you can use the SET and ACCESS\n"
-"commands to configure your nick's settings as you like\n"
-"them. Make sure you remember the password you use when\n"
-"registering - you'll need it to make changes to your nick\n"
-"later. (Note that case matters! ANOPE, Anope, and\n"
-"anope are all different passwords!)\n"
-" \n"
-"Guidelines on choosing passwords:\n"
-" \n"
-"Passwords should not be easily guessable. For example,\n"
-"using your real name as a password is a bad idea. Using\n"
-"your nickname as a password is a much worse idea ;) and,\n"
-"in fact, %s will not allow it. Also, short\n"
-"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
-"Finally, the space character cannot be used in passwords."
-msgstr ""
-"Sintaxis: REGISTER clau [email]\n"
-"\n"
-"Registra el teu nickname a la base de dades de %s. Un\n"
-"cop registrat, pots utilitzar les comandes SET i ACCESS\n"
-"per configurar els parametres del teu nick al teu gust.\n"
-"Assegura't de recordar la clau que vas fer servir per\n"
-"registrar-te - la necessitaras per fer canvis en el teu nick\n"
-"(Tingues en compte que les majuscules importen! AUJAC,\n"
-"Aujac, i aujac són totes claus diferents!)\n"
-"\n"
-"Guies per escollir claus:\n"
-"\n"
-"Las claus no han de ser fàcils d'endevinar. Per exemple,\n"
-"utilitzar el teu nom real com clau es una mala idea. Utilitzar\n"
-"el teu nickname com a clau es una idea pitjor :( i,\n"
-"de fet, %s no ho permetria. A mes, claus curtes\n"
-"son vulnerables a ser encertades, aixi que hauries d'escollir una\n"
-"clau de com a mínim 5 caràcters.\n"
-"Per últim, el caràcter d'espai no pot ser utilitzat.\n"
-"\n"
-"El parametre email es opcional i establira l'email pel\n"
-"teu nick inmediatament. Com sigui, pot ser que sigui demanat\n"
-"en certes xarxes.\n"
-"La teva privacitat es respectada; aquest e-mail no sera donat a\n"
-"terceres persones.\n"
-"\n"
-"Aquesta comanda crea un nou grup pel teu nickname\n"
-"que et permetra registrar altres nicks després compartint\n"
-"la mateixa configuració, memos i privilegis. Per més\n"
-"informació sobre aquesta característica, escriu /msg %s\n"
-"HELP GROUP."
-
-#, fuzzy
-msgid "Registration is currently disabled."
-msgstr "Ho sento, el registre de canals esta temporalment inhabilitat."
-
-#, fuzzy
-msgid "Regulate the use of critical commands"
-msgstr " PEACE Regula l'ús de comandes critiques"
-
-#, fuzzy
-msgid "Reject the requested vHost for the given nick."
-msgstr " STATUS Returns the owner status of the given nickname"
-
-#, fuzzy
-msgid "Reject the requested vHost of a user"
-msgstr " DEL Delete the vhost of another user"
-
-#, fuzzy
-msgid "Releases a suspended channel"
-msgstr " UNSUSPEND Releases a suspended channel"
-
-#, fuzzy
-msgid ""
-"Releases a suspended channel. All data and settings\n"
-"are preserved from before the suspension."
-msgstr ""
-"Syntax: UNSUSPEND channel\n"
-"\n"
-"Releases a suspended channel. All data and settings\n"
-"are preserved from before the suspension."
-
-#, fuzzy
-msgid "Reload a module"
-msgstr " MODLOAD Load a module"
-
-#, fuzzy
-msgid "Reload services' configuration file"
-msgstr " RELOAD Recarrega la configuració dels serveis"
-
-#, fuzzy
-msgid "Remove a nick from a group"
-msgstr " UNGROUP Remove a nick from a group"
-
-#, fuzzy
-msgid "Remove all bans preventing a user from entering a channel"
-msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-
-#, fuzzy
-msgid "Remove all operators from a server remotely"
-msgstr ""
-" NOOP Temporalment elimina totes les linees O:\n"
-" d'un servidor remotamente"
-
-#, fuzzy, c-format
-msgid "Removed IP %s from %s."
-msgstr " Mode de lock: %s"
-
-#, c-format
-msgid "Removed server %s from zone %s."
-msgstr ""
-
-#, c-format
-msgid "Removed server %s."
-msgstr ""
-
-#, c-format
-msgid ""
-"Removes %s status from the selected nick on a channel. If nick is\n"
-"not given, it will de%s you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Removes %s status from you or the specified nick on a channel"
-msgstr " OP Gives Op status to a selected nick on a channel"
-
-#, fuzzy
-msgid "Removes a selected nicks status from a channel"
-msgstr " KICK Kicks a selected nick from a channel"
-
-msgid ""
-"Removes a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is removed. If channel is omitted then\n"
-"your channel status is removed on every channel you are in."
-msgstr ""
-
-#, c-format
-msgid "Removing %s because %s covers it."
-msgstr ""
-
-#, fuzzy
-msgid "Repeat kicker"
-msgstr " Kicker per repetició : %s"
-
-#, fuzzy
-msgid "Request a vHost for your nick"
-msgstr "There's no email address set for your nick."
-
-msgid ""
-"Request the given vHost to be activated for your nick by the\n"
-"network administrators. Please be patient while your request\n"
-"is being considered."
-msgstr ""
-
-#, fuzzy
-msgid "Resend registration confirmation email"
-msgstr " RELOAD Recarrega la configuració dels serveis"
-
-#, fuzzy
-msgid "Restrict access to the channel"
-msgstr " RESTRICTED Restringeix l'accés al canal"
-
-#, fuzzy
-msgid "Restricted access"
-msgstr "accés restringit"
-
-#, fuzzy, c-format
-msgid "Restricted access option for %s is now off."
-msgstr "Restricted access option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Restricted access option for %s is now on."
-msgstr "Restricted access option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Restricted enforced on %s."
-msgstr "accés restringit"
-
-#, fuzzy
-msgid "Retain modes when channel is not in use"
-msgstr ""
-" KEEPTOPIC Rete el topic quant el canal no\n"
-" esta en uso"
-
-#, fuzzy
-msgid "Retain topic when channel is not in use"
-msgstr ""
-" KEEPTOPIC Rete el topic quant el canal no\n"
-" esta en uso"
-
-#, fuzzy
-msgid "Retrieve the password for a nickname"
-msgstr ""
-" GETPASS Recupera la clau per un nickname\n"
-" (sols si encriptació esta deshabilitada)"
-
-msgid "Retrieves the vhost requests"
-msgstr ""
-
-#, fuzzy
-msgid "Returns the key of the given channel"
-msgstr " GETKEY Returns the key of the given channel"
-
-#, fuzzy
-msgid "Returns the key of the given channel."
-msgstr " GETKEY Returns the key of the given channel"
-
-#, fuzzy
-msgid "Returns the matching accounts that used given email."
-msgstr " GETKEY Returns the key of the given channel"
-
-#, fuzzy
-msgid "Returns the owner status of the given nickname"
-msgstr " STATUS Returns the owner status of the given nickname"
-
-#, fuzzy
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Sintaxis: GETPASS nickname\n"
-"\n"
-"Retorna la clau pel nickname donat. Tingues en compte\n"
-"que quant aquesta comanda es utilitzada, un missatge inclouent\n"
-"la persona que va executar la comanda i el nickname en el qual\n"
-"va ser utilitzat sera establert i enviat com WALLOPS/GLOBOPS.\n"
-"\n"
-"Limitat a administradors de serveis.\n"
-"\n"
-"Aquesta comanda no esta disponible si encriptació esta habilitada."
-
-#, fuzzy
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
-msgstr ""
-"Sintaxis: STATUS nickname...\n"
-"\n"
-"Retorna informació sobre si l'usuari que utilitza el nick especificat\n"
-"ha estat reconegut com el propietari del nickname.\n"
-"La resposta te el següent format:\n"
-"\n"
-" nickname codi-del-status account\n"
-"\n"
-"where nickname is the nickname sent with the command,\n"
-"codi-del-status is one of the following, and account\n"
-"is the account they are logged in as.\n"
-"\n"
-" 0 - Usuari no esta en linea o el nick no esta registrat.\n"
-" 1 - Usuari no reconegut com el propietari del nick.\n"
-" 2 - Usuari reconegut sols mitjançant la llista d'accés.\n"
-" 3 - Usuari reconegut mitjançant autentificació per clau.\n"
-"\n"
-"Fins 16 nicknames poden ser enviats amb cada comanda. El\n"
-"reste seran ignorats. If no nickname is given, your status\n"
-"will be returned."
-
-#, fuzzy
-msgid "Reverses kicker"
-msgstr " Kicker per inversos : %s"
-
-#, fuzzy
-msgid "Reverses the effect of the IDENTIFY command"
-msgstr " LOGOUT Reverses the effect of the IDENTIFY command"
-
-#, fuzzy
-msgid "SET server"
-msgstr "NOOP {SET|REVOKE} servidor"
-
-msgid "SET server.name option value"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "SSL certificate fingerprint accepted, you are now identified to %s."
-msgstr "Clau aceptada - Has estat reconegut."
-
-#, fuzzy
-msgid "SSL certificate fingerprint accepted, you are now identified."
-msgstr "Clau aceptada - Has estat reconegut."
-
-#, c-format
-msgid "SSL only enforced on %s."
-msgstr ""
-
-msgid "SSLONLY enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "Save databases and restart Services"
-msgstr ""
-" RESTART Guarda la base de dades dels serveis i\n"
-" reinicia els serveis"
-
-msgid "Searches logs for a matching pattern"
-msgstr ""
-
-#, fuzzy
-msgid "Secure founder"
-msgstr "Fundador Segur"
-
-#, fuzzy, c-format
-msgid "Secure founder option for %s is now off."
-msgstr "Secure founder option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure founder option for %s is now on."
-msgstr "Secure founder option for %s is now ON."
-
-#, fuzzy
-msgid "Secure ops"
-msgstr "Ops Segurs"
-
-#, fuzzy, c-format
-msgid "Secure ops option for %s is now off."
-msgstr "Secure ops option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure ops option for %s is now on."
-msgstr "Secure ops option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now off."
-msgstr "Secure option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now on."
-msgstr "Secure option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure option is now off for %s."
-msgstr "Secure option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Secure option is now on for %s."
-msgstr "Secure option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Secureops enforced on %s."
-msgstr "Secure option is now ON for %s."
-
-msgid "Security"
-msgstr "Segur"
-
-#, fuzzy, c-format
-msgid ""
-"See %s%s HELP %s for more information\n"
-"about the access list."
-msgstr ""
-"Escriu /msg %s HELP opció per més informació\n"
-"sobre una opció en particular."
-
-#, fuzzy, c-format
-msgid ""
-"See %s%s HELP %s for more information\n"
-"about the flags system."
-msgstr ""
-"Escriu /msg %s HELP opció per més informació\n"
-"sobre una opció en particular."
-
-#, fuzzy
-msgid "Send a memo to a nick or channel"
-msgstr " SEND Envia un memo a un nick o canal"
-
-#, fuzzy
-msgid "Send a memo to all opers/admins"
-msgstr " STAFF Send a memo to all opers/admins"
-
-#, fuzzy
-msgid "Send a memo to all registered users"
-msgstr " SENDALL Send a memo to all registered users"
-
-#, fuzzy
-msgid "Send a message to all users"
-msgstr " GLOBAL Envia un missatge a totss els usuaris"
-
-#, fuzzy
-msgid "Sender"
-msgstr "Fundador Segur"
-
-#, fuzzy
-msgid "Sends a memo and requests a read receipt"
-msgstr " RSEND Sends a memo and requests a read receipt"
-
-#, fuzzy
-msgid ""
-"Sends a passcode to the nickname with instructions on how to\n"
-"reset their password. Email must be the email address associated\n"
-"to the nickname."
-msgstr ""
-"Syntax: RESETPASS nickname\n"
-"\n"
-"Sends a code key to the nickname with instructions on how to\n"
-"reset their password."
-
-#, fuzzy
-msgid "Sends all registered users a memo containing memo-text."
-msgstr ""
-"Syntax: SENDALL memo-text\n"
-"Sends all registered users a memo containing memo-text."
-
-#, fuzzy
-msgid "Sends all services staff a memo containing memo-text."
-msgstr ""
-"Syntax: STAFF memo-text\n"
-"Sends all services staff a memo containing memo-text."
-
-#, fuzzy
-msgid ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered."
-msgstr ""
-"Sintàxi: SEND {nick | canal} text-del-memo\n"
-"\n"
-"Envia un memo al nick o canal donat, que conté\n"
-"text-del-memo. A l'enviar a un nickname, aquest\n"
-"rebrà noticia de que ell/ella té un nou memo. El nick\n"
-"o canal receptors han d'estar registrats."
-
-#, fuzzy
-msgid ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered.\n"
-"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
-"has been read."
-msgstr ""
-"Syntax: RSEND {nick | channel} memo-text\n"
-"\n"
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered.\n"
-"Once the memo is read by its recepient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
-"has been read."
-
-#, fuzzy
-msgid ""
-"Sends you the text of the memos specified. If LAST is\n"
-"given, sends you the memo you most recently received. If\n"
-"NEW is given, sends you all of your new memos. If ALL is\n"
-"given, sends you all of your memos. Otherwise, sends you\n"
-"memo number num. You can also give a list of numbers,\n"
-"as in this example:\n"
-" \n"
-" READ 2-5,7-9\n"
-" Displays memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Sintàxi: READ [canal] {nombre | llista | LAST | NEW}\n"
-"\n"
-"T'envia el text dels memos especificats. Si LAST és\n"
-"donat, t'envia l'ultim memo rebut. si NEW és donat, t'\n"
-"envia tots els teus memos nous. D'altra forma, t'envia el\n"
-"memo nombre nombre. També pots donar una llista de\n"
-"nombres, com en el exemple:\n"
-"\n"
-" READ 2-5,7-9\n"
-" mostra els memos enumerats 2 a 5 i 7 a 9."
-
-#, fuzzy
-msgid "Server"
-msgstr "NOOP {SET|REVOKE} servidor"
-
-#, fuzzy, c-format
-msgid "Server %s added to zone %s."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s already exists."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy, c-format
-msgid "Server %s does not exist."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s has no configured IPs."
-msgstr "Nickname %s ha estat expulsat."
-
-#, fuzzy, c-format
-msgid "Server %s is already in zone %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "Server %s is already pooled."
-msgstr "Module %s is already loaded."
-
-#, fuzzy, c-format
-msgid "Server %s is not currently linked."
-msgstr "%s Esta actualment online."
-
-#, fuzzy, c-format
-msgid "Server %s is not in zone %s."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s is not linked to the network."
-msgstr "Ja no hi ha un bot assignat a %s."
-
-#, fuzzy, c-format
-msgid "Server %s is not pooled."
-msgstr " %s (does not expire)"
-
-#, c-format
-msgid "Server %s must be quit before it can be deleted."
-msgstr ""
-
-#, fuzzy
-msgid "Servers"
-msgstr "NOOP {SET|REVOKE} servidor"
-
-#, c-format
-msgid "Servers found: %d"
-msgstr "Servers found: %d"
-
-#, fuzzy
-msgid "Service"
-msgstr "Servers found: %d"
-
-#, fuzzy, c-format
-msgid "Service's hold on %s has been released."
-msgstr "El teu nick ha estat alliberat pels serveis."
-
-#, fuzzy
-msgid "Services Operator commands"
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "Services are in DefCon mode, please try again later."
-msgstr "This service is temporarly disabled, please try again later"
-
-#, fuzzy
-msgid "Services are in read-only mode!"
-msgstr "Serveis ara en Mode nomès lectura."
-
-#, fuzzy, c-format
-msgid "Services are now at DEFCON %d."
-msgstr "Services are now at DEFCON %d"
-
-#, fuzzy, c-format
-msgid "Services are now in debug mode (level %d)."
-msgstr "Serveis ara en Mode debug (nivell %d)."
-
-#, fuzzy
-msgid "Services are now in debug mode."
-msgstr "Serveis ara en Mode debug."
-
-msgid "Services are now in expire mode."
-msgstr "Serveis ara en Mode expire."
-
-msgid "Services are now in no expire mode."
-msgstr "Serveis ara en Mode no expire."
-
-#, fuzzy
-msgid "Services are now in non-debug mode."
-msgstr "Serveis ara en Mode no-debug."
-
-msgid "Services are now in read-only mode."
-msgstr "Serveis ara en Mode nomès lectura."
-
-msgid "Services are now in read-write mode."
-msgstr "Serveis ara en Mode de lectura-escriptura."
-
-msgid "Services have been configured to not send mail."
-msgstr "Els serveis han estat configurats per no enviar email"
-
-#, fuzzy
-msgid "Services ignore list:"
-msgstr " IGNORE Modify the Services ignore list"
-
-#, fuzzy
-msgid ""
-"Services is unable to change modes. Are your servers' U:lines configured "
-"correctly?"
-msgstr ""
-"Els serveis no han pogut canviar Modes. Estan les linees U: dels teus "
-"servidors configurades correctament?"
-
-#, fuzzy, c-format
-msgid "Services up %s."
-msgstr "Servers found: %d"
-
-#, fuzzy, c-format
-msgid "Services will from now on set status modes on %s in channels."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Services will no longer automatically give modes to users in %s."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Services will no longer set status modes on %s in channels."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Services will now automatically give modes to users in %s."
-msgstr "Services will now autoop %s in channels."
-
-#, c-format
-msgid "Services will now reply to %s with messages."
-msgstr "Services will now reply to %s with messages."
-
-#, c-format
-msgid "Services will now reply to %s with notices."
-msgstr "Services will now reply to %s with notices."
-
-#, fuzzy
-msgid "Services' configuration has been reloaded."
-msgstr "L'arxiu de configuració de serveis ha estat carregat novament."
-
-msgid "Session"
-msgstr ""
-
-#, c-format
-msgid "Session limit for %s set to %d."
-msgstr "Límit de sessió per a %s establert a %d."
-
-msgid "Session limiting is disabled."
-msgstr "Límits de sessions no disponibles."
-
-#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, fuzzy
-msgid "Set SET-options on another nickname"
-msgstr " SASET Set SET-options on another nickname"
-
-#, fuzzy
-msgid "Set channel options and information"
-msgstr " SET Establir opcions i informació d'un canal"
-
-#, fuzzy
-msgid "Set how Services make bans on the channel"
-msgstr ""
-" BANTYPE Estableix com els serveis posen bans\n"
-" en el canal"
-
-#, fuzzy
-msgid "Set options related to memos"
-msgstr " SET Estableix opcions relacionades a memos"
-
-#, fuzzy
-msgid "Set options, including kill protection"
-msgstr " SET Estableix proteccions, inclouent kills"
-
-#, fuzzy
-msgid "Set the channel as permanent"
-msgstr " PERSIST Set the channel as permanent"
-
-#, fuzzy
-msgid "Set the channel description"
-msgstr " DESC Estableix la descripció del canal"
-
-#, fuzzy
-msgid "Set the display of your group in Services"
-msgstr " DISPLAY Estableix el display del teu grup amb serveis"
-
-#, fuzzy
-msgid "Set the founder of a channel"
-msgstr " FOUNDER Estableix el fundador d'un canal"
-
-#, fuzzy
-msgid "Set the language Services will use when messaging you"
-msgstr ""
-" LANGUAGE Estableix el llenguatge amb el que els serveis\n"
-" t'enviaran missatges"
-
-#, fuzzy
-msgid "Set the nickname password"
-msgstr " PASSWORD Set the nickname password"
-
-#, fuzzy
-msgid "Set the successor for a channel"
-msgstr " SUCCESSOR Estableix el successor d'un canal"
-
-#, fuzzy
-msgid "Set the vhost for all nicks in a group"
-msgstr " SETALL Set the vhost for all nicks in a group"
-
-#, fuzzy
-msgid "Set the vhost of another user"
-msgstr " SET Set the vhost of another user"
-
-#, fuzzy
-msgid "Set various global Services options"
-msgstr " SET Estableix varies opcions globals dels serveis"
-
-#, fuzzy
-msgid "Set your nickname password"
-msgstr " PASSWORD Estableix la clau del teu nickname"
-
-#, fuzzy, c-format
-msgid ""
-"Sets the AMSG kicker on or off. When enabled, the bot will\n"
-"kick users who send the same message to multiple channels\n"
-"where %s bots are.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before they get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-
-#, fuzzy, c-format
-msgid ""
-"Sets the bad words kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who say certain words\n"
-"on the channels.\n"
-"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
-"more information.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK #canal BADWORDS {ON|OFF} [ttb]\n"
-"\n"
-"Estableix el kick per paraules malsonants a activat o desactivat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que utilitzin certes paraules al canal.\n"
-"\n"
-"Pots definir paraules malsonants pel teu canal utilitzant la comanda\n"
-"BADWORDS. Escriu /msg %s HELP BADWORDS per més informació.\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the ban type that will be used by services whenever\n"
-"they need to ban someone from your channel.\n"
-" \n"
-"Bantype is a number between 0 and 3 that means:\n"
-" \n"
-"0: ban in the form *!user@host\n"
-"1: ban in the form *!*user@host\n"
-"2: ban in the form *!*@host\n"
-"3: ban in the form *!*user@*.domain"
-msgstr ""
-"Sintaxis: %s canal BANTYPE tipus_de_ban\n"
-"\n"
-"Especifica el tipus de ban que sera utilitzat pels\n"
-"serveis quant necessitin banear algu\n"
-"del teu canal.\n"
-"\n"
-"Tipus de ban es un numero entre 0 i 3 que significa:\n"
-"\n"
-"0: ban de la forma *!usuari@host\n"
-"1: ban de la forma *!*usuari@host\n"
-"2: ban de la forma *!*@host\n"
-"3: ban de la forma *!*usuari@*.domini"
-
-#, fuzzy
-msgid ""
-"Sets the bolds kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use bolds.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK canal BOLDS {ON|OFF} [ttb]\n"
-"Estableix el kick per negretes a actvitat o desactivat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que utilitzin negretes.\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy, c-format
-msgid ""
-"Sets the caps kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are talking in\n"
-"CAPS.\n"
-"The bot kicks only if there are at least min caps\n"
-"and they constitute at least percent%% of the total\n"
-"text line (if not given, it defaults to 10 characters\n"
-"and 25%%).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK canal CAPS {ON|OFF} [ttb [min [porcentaje]]]\n"
-"Estableix el kick per mayusculas a activat o desactivat.\n"
-"En habilitar-lo, aquesta opció le diu al bot que kickegi\n"
-"usuaris que estiguin escrivint en majuscules.\n"
-"\n"
-"El bot kickeja nomès si hi ha com a mínim min majuscules\n"
-"i que constitueixin com a mínim porcentatge%% del total\n"
-"del text (si no s'especifica, per defecte s'estableix a 10\n"
-"caràcters i 25%%).\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the colors kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use colors.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK canal COLORS {ON|OFF} [ttb]\n"
-"\n"
-"Estableix el kick per colors a activat o desactivat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que utilitzin colors.\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the description for the channel, which shows up with\n"
-"the LIST and INFO commands."
-msgstr ""
-"Sintaxis: %s canal DESC descripció\n"
-"\n"
-"Estableix la descripció pel canal, la que es mostrada\n"
-"amb les comandes LIST i INFO."
-
-#, fuzzy
-msgid ""
-"Sets the flood kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are flooding\n"
-"the channel using at least ln lines in secs seconds\n"
-"(if not given, it defaults to 6 lines in 10 seconds).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK canal FLOOD {ON|OFF} [ttb [ln [segs]]]\n"
-"Estableix el kick per flood a activat o desactivat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que estiguin floodejant el canal utilitzant com a mínim\n"
-"ln linees en segs segons (si no s'especifica, per\n"
-"defecte es establert a 6 linees en 10 segons).\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-
-#, fuzzy
-msgid ""
-"Sets the repeat kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are repeating\n"
-"themselves num times (if num is not given, it\n"
-"defaults to 3).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK #canal REPEAT {ON|OFF} [ttb [num]]\n"
-"\n"
-"Estableix el kick per repetició a activat o desactivat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que estiguin repetint num cops (si num no s'especifica,\n"
-"per defecte es establert a 3).\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the reverses kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use reverses.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK canal REVERSES {ON|OFF} [ttb]\n"
-"\n"
-"Estableix el kick per reversos a activat o desactivat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que utilitzin reversos.\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the underlines kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use underlines.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Sintàxi: KICK canal UNDERLINES {ON|OFF} [ttb]\n"
-"\n"
-"Estableix el kick per subratllats a activat o apagat.\n"
-"En habilitar-lo, aquesta opció li diu al bot que kickegi\n"
-"usuaris que utilitzin subratllats.\n"
-"\n"
-"ttb es el numero de cops que un usuari sera kickejat\n"
-"abans de ser banejat. No cal especificar ttb per a deshabilitar\n"
-"el sistema de ban un cop activat."
-
-#, fuzzy
-msgid ""
-"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
-"using SETALL <nick> <ident>@<hostmask> will set idents\n"
-"for users as well as vhosts.\n"
-"* NOTE, this will not update the vhost for any nicks\n"
-"added to the group after this command was used."
-msgstr ""
-"Syntax: SETALL <nick> <hostmask>.\n"
-"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
-"using SETALL <nick> <ident>@<hostmask> will set idents\n"
-"for users as well as vhosts.\n"
-"* NOTE, this will not update the vhost for any nick's\n"
-"added to the group after this command was used.\n"
-"Limited to Services operators."
-
-#, fuzzy
-msgid ""
-"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
-"SET <nick> <ident>@<hostmask> set idents for users as\n"
-"well as vhosts."
-msgstr ""
-"Syntax: SET <nick> <hostmask>.\n"
-"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
-"SET <nick> <ident>@<hostmask> set idents for users as \n"
-"well as vhosts.\n"
-"Limited to Services operators."
-
-#, fuzzy
-msgid ""
-"Sets various global Services options. Option names\n"
-"currently defined are:\n"
-" READONLY Set read-only or read-write mode\n"
-" DEBUG Activate or deactivate debug mode\n"
-" NOEXPIRE Activate or deactivate no expire mode\n"
-" SUPERADMIN Activate or deactivate super admin mode\n"
-" LIST List the options"
-msgstr ""
-"Sintàxi: SET opció parametres\n"
-"\n"
-"Estableix varies opcions globals de serveis.\n"
-"Noms de opcions actualment definides són:\n"
-" READONLY Estableix Mode nomès lectura o nomès escritura\n"
-" LOGCHAN Report log messages to a channel\n"
-" DEBUG Activa o desactiva el Mode debug\n"
-" NOEXPIRE Activa o desactiva el Mode no expire\n"
-" SUPERADMIN Activate or deactivate super-admin mode\n"
-" IGNORE Activate or deactivate ignore mode\n"
-" LIST List the options\n"
-"\n"
-"Limitat a administradors de serveis."
-
-#, fuzzy, c-format
-msgid ""
-"Sets various memo options. option can be one of:\n"
-" \n"
-" NOTIFY Changes when you will be notified about\n"
-" new memos (only for nicknames)\n"
-" LIMIT Sets the maximum number of memos you can\n"
-" receive\n"
-" \n"
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
-msgstr ""
-"Sintàxi: SET Opció paràmetros\n"
-"\n"
-"Estableix varies opcions de memos. Opció pot ser una de:\n"
-"\n"
-" NOTIFY Canvia quan seràs notificat sobre de\n"
-" nous memos (sols per a nicknames)\n"
-" LIMIT Estableix el màxim nombre de memos que\n"
-" pots rebre\n"
-"\n"
-"escriu /msg %s HELP SET Opció per a més informació\n"
-"sobre una opció específica."
-
-#, fuzzy
-msgid "Sets various nickname options. option can be one of:"
-msgstr ""
-"Sintaxis: SET Opció parametres\n"
-"\n"
-"Estableix varies opcions per a nicknames. Opció pot ser\n"
-"una de:"
-
-msgid ""
-"Sets whether services should set channel status modes on you automatically."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Sets whether the given channel will expire. Setting this\n"
-"to ON prevents the channel from expiring."
-msgstr ""
-"Sintàxi: SET canal NOEXPIRE {ON | OFF}\n"
-"\n"
-"Estableix si el canal expirarà. Establint-lo \n"
-"a ON evita que el canal expiri.\n"
-"\n"
-"limitat a administradors de serveis."
-
-#, fuzzy, c-format
-msgid ""
-"Sets whether the given nickname will be given its status modes\n"
-"in channels automatically. Set to ON to allow %s\n"
-"to set status modes on the given nickname automatically when it\n"
-"is entering channels. Note that depending on channel settings\n"
-"some modes may not get set automatically."
-msgstr ""
-"Syntax: SASET nickname AUTOOP {ON | OFF}\n"
-"\n"
-"Sets whether the given nickname will be opped automatically.\n"
-"Set to ON to allow ChanServ to op the given nickname \n"
-"automatically when joining channels."
-
-#, fuzzy
-msgid ""
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
-msgstr ""
-"Syntax: SASET nickname NOEXPIRE {ON | OFF}\n"
-"\n"
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
-
-#, fuzzy, c-format
-msgid ""
-"Sets whether you will be given your channel status modes automatically.\n"
-"Set to ON to allow %s to set status modes on you automatically\n"
-"when entering channels. Note that depending on channel settings some modes\n"
-"may not get set automatically."
-msgstr ""
-"Syntax: SET AUTOOP {ON | OFF}\n"
-"\n"
-"Sets whether you will be opped automatically. Set to ON to \n"
-"allow ChanServ to op you automatically when entering channels."
-
-#, fuzzy, c-format
-msgid ""
-"Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
-msgstr ""
-"Opció %s no coneguda. Escriu /msg %s HELP LEVELS DESC per a una llista de "
-"opcións valides."
-
-#, fuzzy
-msgid "Setting for DEBUG must be ON, OFF, or a positive number."
-msgstr "L'establiment per a DEBUG ha de ser ON, OFF, o un numero positiu."
-
-#, fuzzy
-msgid "Setting for NOEXPIRE must be ON or OFF."
-msgstr "Establiment per a NOEXPIRE ha de ser ON o OFF."
-
-#, fuzzy
-msgid "Setting for READONLY must be ON or OFF."
-msgstr "L'establiment per a READONLY ha de ser ON o OFF."
-
-#, fuzzy
-msgid "Setting for super admin must be ON or OFF."
-msgstr "L'establiment per a READONLY ha de ser ON o OFF."
-
-#, fuzzy
-msgid "Should services automatically give status to users"
-msgstr " AUTOOP Should services op you automatically. "
-
-#, fuzzy
-msgid "Show status of Services and network"
-msgstr " STATS mostra estatus dels serveis i la xarxa"
-
-#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr ""
-
-#, fuzzy
-msgid "Sign kicks that are done with the KICK command"
-msgstr " SIGNKICK Firma kicks fets amb la comanda KICK"
-
-#, fuzzy, c-format
-msgid "Signed kick option for %s is now off."
-msgstr "Signed kick option for %s is now ON."
-
-#, fuzzy, c-format
-msgid ""
-"Signed kick option for %s is now on, but depends of the\n"
-"level of the user that is using the command."
-msgstr ""
-"Signed kick option for %s is now ON, but depends of the\n"
-"level of the user that is using the command."
-
-#, fuzzy, c-format
-msgid "Signed kick option for %s is now on."
-msgstr "Signed kick option for %s is now ON."
-
-msgid "Signed kicks"
-msgstr "Kicks Signats"
-
-#, fuzzy, c-format
-msgid "Sorry, %s currently has too many memos and cannot receive more."
-msgstr "%s actualment te molts memos i no pot rebre'n mes."
-
-#, c-format
-msgid "Sorry, I have not seen %s."
-msgstr ""
-
-#, fuzzy
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr ""
-"Ho sento, la llista de paraules malsonants per a canals esta temporalment "
-"inabilitada."
-
-#, fuzzy
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr ""
-"Ho sento, l'establiment d'opcions per a bot esta temporalment inhabilitat"
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "Ho sento, la modificació de bots esta temporalment inabilitada."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr ""
-"Ho sento, l'establiment d'opcions per a bot esta temporalment inhabilitat"
-
-#, fuzzy
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr ""
-"Ho sento, l'establiment d'opcions per a bot esta temporalment inhabilitat"
-
-#, fuzzy, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
-msgstr ""
-"Ho sento, la modificació de la llista AOP de canals esta\n"
-"temporalment deshabilitada."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr ""
-"Ho sento, la modificació d'accés a canals esta temporalment inabilitada."
-
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr ""
-"Ho sento, la modificació de kicks automàtics a canals esta temporalment "
-"inabilitada."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr ""
-"Ho sento, el desenregistrament de canals esta temporalment desabilitat."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Ho sento, el registre de canals esta temporalment inhabilitat."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
-msgstr "Ho sento, la configuració de kicker esta temporalment inabilitada."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr ""
-"Ho sento, l'establiment d'opcions per a memos esta temporalment inhabilitat."
-
-#, fuzzy
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr ""
-"Ho sento, l'establiment d'opcions per a memos esta temporalment inhabilitat."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Ho sento, desenregistrament de nickname esta temporalment inhabilitat."
-
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Ho sento, La agrupació de nicks esta temporalment inabilitada."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Ho sento, el registre de nicknames esta temporalment deshabilitat."
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
-msgstr ""
-"Ho sento, sols pots tenir %d instàncies d'accés en un determinat canal."
-
-#, c-format
-msgid "Sorry, the maximum of %d auto join entries has been reached."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d certificate entries has been reached."
-msgstr ""
-"Ho sento, sols pots tenir %d instàncies a la teva lllista d'accés per "
-"nickname."
-
-#, fuzzy, c-format
-msgid "Sorry, the memo ignore list for %s is full."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid ""
-"Sorry, you can only have %d access entries on a channel, including access "
-"entries from other channels."
-msgstr ""
-"Ho sento, sols pots tenir %d instàncies d'accés en un determinat canal."
-
-#, c-format
-msgid "Sorry, you can only have %d autokick masks on a channel."
-msgstr ""
-"Ho sento, sols pots tenir %d mascaras per a kicks automàtics a un canal."
-
-#, c-format
-msgid "Sorry, you can only have %d bad words entries on a channel."
-msgstr "Ho sento, sols pots tenir %d paraules malsonants en un canal."
-
-#, fuzzy, c-format
-msgid "Sorry, you have already exceeded your limit of %d channels."
-msgstr "Ho sento, sols pots tenir %d paraules malsonants en un canal."
-
-#, fuzzy, c-format
-msgid "Sorry, you have already reached your limit of %d channels."
-msgstr "Ho sento, sols pots tenir %d paraules malsonants en un canal."
-
-msgid "State"
-msgstr ""
-
-msgid "Statistics and maintenance for seen data"
-msgstr ""
-
-msgid "Statistics reset."
-msgstr "Estadistiques restablertes."
-
-msgid "Status updated (memos, vhost, chmodes, flags)."
-msgstr "Status updated (memos, vhost, chmodes, flags)."
-
-msgid "Stop flooding!"
-msgstr "Para de floodejar!"
-
-msgid "Stop repeating yourself!"
-msgstr "No repeteixis com l'allioli!"
-
-#, fuzzy
-msgid "Stricter control of channel founder status"
-msgstr ""
-" SECUREFOUNDER Estricto control de l'estatus de fundador\n"
-" del canal"
-
-#, fuzzy
-msgid "Stricter control of chanop status"
-msgstr " SECUREOPS Estricte control de l'estatus de chanop"
-
-msgid "Successor"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Successor for %s changed to %s."
-msgstr "Sucessor de %s cambiat a %s."
-
-#, c-format
-msgid "Successor for %s unset."
-msgstr "Sucessor de %s desabilitat."
-
-#, fuzzy
-msgid ""
-"Super admin can not be set because it is not enabled in the configuration."
-msgstr "SuperAdmin setting not enabled in services.conf"
-
-#, fuzzy
-msgid "Suspend a given nick"
-msgstr " SUSPEND Suspend a given nick"
-
-#, fuzzy
-msgid "Suspend reason"
-msgstr "JUPE nom-del-servidor [raó]"
-
-msgid "Suspended"
-msgstr ""
-
-msgid "Suspended by"
-msgstr ""
-
-#, fuzzy
-msgid "Suspended on"
-msgstr " SUSPEND Suspend a given nick"
-
-#, fuzzy
-msgid ""
-"Suspends a registered nickname, which prevents it from being used\n"
-"while keeping all the data for that nick. If an expiry is given\n"
-"the nick will be unsuspended after that period of time, else the\n"
-"default expiry from the configuration is used."
-msgstr ""
-"Syntax: SUSPEND channel [reason]\n"
-"\n"
-"Disallows anyone from registering or using the given\n"
-"channel. May be cancelled by using the UNSUSPEND\n"
-"command to preserve all previous channel data/settings.\n"
-"\n"
-"Reason may be required on certain networks."
-
-#, fuzzy
-msgid "Suspension expires"
-msgstr " %s (does not expire)"
-
-#, fuzzy
-msgid "Sync users channel modes"
-msgstr "%s changed your usermodes."
-
-msgid ""
-"Syncs all modes set on users on the channel with the modes\n"
-"they should have based on their access."
-msgstr ""
-
-#, fuzzy
-msgid "Syncs the vhost for all nicks in a group"
-msgstr " GROUP Syncs the vhost for all nicks in a group"
-
-msgid "Syntax"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: %s\n"
-" \n"
-"Lists all nicks in your group."
-msgstr ""
-"Sintaxis: GLIST\n"
-"\n"
-"Llista tots els nicks en el teu grup."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: %s [nickname]\n"
-" \n"
-"Without a parameter, lists all nicknames that are in\n"
-"your group.\n"
-" \n"
-"With a parameter, lists all nicknames that are in the\n"
-"group of the given nick.\n"
-"Specifying a nick is limited to Services Operators."
-msgstr ""
-"Sintaxis: GLIST [nickname]\n"
-"\n"
-"Sense un parametre, llista tots els nicknames en el teu\n"
-"grup.\n"
-"\n"
-"Amb un parametre, llista tots els nicknames que hi ha\n"
-"en el grup del nick esmentat.\n"
-"El seu ús esta limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Syntax: DEBUG {ON | OFF}\n"
-" \n"
-"Sets debug mode on or off.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--debug."
-msgstr ""
-"Sintàxi: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Estableix el mode no expire a activat o desactivat. En\n"
-"mode no expire, nicks, canals, akills i excepcions\n"
-"no caducaran fins que l'opció sigui desactivada.\n"
-"\n"
-"Aquaquesta opció es equivalent a l'opció -noexpire\n"
-"en la linea de comandes."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIMIT [channel] limit\n"
-" \n"
-"Sets the maximum number of memos you (or the given channel)\n"
-"are allowed to have. If you set this to 0, no one will be\n"
-"able to send any memos to you. However, you cannot set\n"
-"this any higher than %d."
-msgstr ""
-"Sintàxi: SET LIMIT [canal] límit\n"
-"\n"
-"Estableix el màxim nombre de memos que tu (o el canal donat)\n"
-"pots tenir. Si queda a 0, ningú podrà\n"
-"enviar-te memos. A més, no pots establir el límit més\n"
-"alt que %d."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIMIT [user | channel] {limit | NONE} [HARD]\n"
-" \n"
-"Sets the maximum number of memos a user or channel is\n"
-"allowed to have. Setting the limit to 0 prevents the user\n"
-"from receiving any memos; setting it to NONE allows the\n"
-"user to receive and keep as many memos as they want. If\n"
-"you do not give a nickname or channel, your own limit is\n"
-"set.\n"
-" \n"
-"Adding HARD prevents the user from changing the limit. Not\n"
-"adding HARD has the opposite effect, allowing the user to\n"
-"change the limit (even if a previous limit was set with\n"
-"HARD).\n"
-" \n"
-"This use of the SET LIMIT command is limited to Services\n"
-"Operators. Other users may only enter a limit for themselves\n"
-"or a channel on which they have such privileges, may not\n"
-"remove their limit, may not set a limit above %d, and may\n"
-"not set a hard limit."
-msgstr ""
-"Sintàxi: SET LIMIT [usuari | canal] {límit | NONE} [HARD]\n"
-"\n"
-"Estableix el màxim nombre de memos un usuari o canal està\n"
-"permès. Establir el límit a 0 evita a l'usuari\n"
-"de rebre memos; posar-lo a NONE permet a l'usuari\n"
-"de rebre i guardar els memos que vulgui. Si no dones un\n"
-"nickname o canal, el teu propi límit està establert.\n"
-"\n"
-"Afegir HARD evita al usuari de canviar el límit. No\n"
-"afegir HARD té l'efect contrari, permetent a l'\n"
-"usuari canviar el límit (encara que un límit previ hagui sigut establert\n"
-"amb HARD).\n"
-"\n"
-"L'us de la comanda SET LIMIT està limitat a\n"
-"administradors de serveis. altres usuaris poden\n"
-"només establir límits per a ells mateixos o per a un canal en\n"
-"el que tinguin certos privilegos, no podenn esborrar el seu\n"
-"límit, no poden establir el límit més enllà de %d, i no\n"
-"poden establir un límit hard."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIST\n"
-" \n"
-"Display the various %s settings."
-msgstr ""
-"Syntax: SET LIST\n"
-"Display the various %s settings"
-
-#, fuzzy
-msgid ""
-"Syntax: NOEXPIRE {ON | OFF}\n"
-" \n"
-"Sets no expire mode on or off. In no expire mode, nicks,\n"
-"channels, akills and exceptions won't expire until the\n"
-"option is unset.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--noexpire."
-msgstr ""
-"Sintàxi: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Estableix el mode no expire a activat o desactivat. En\n"
-"mode no expire, nicks, canals, akills i excepcions\n"
-"no caducaran fins que l'opció sigui desactivada.\n"
-"\n"
-"Aquaquesta opció es equivalent a l'opció -noexpire\n"
-"en la linea de comandes."
-
-#, fuzzy
-msgid ""
-"Syntax: NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-" \n"
-"Changes when you will be notified about new memos:\n"
-" \n"
-" ON You will be notified of memos when you log on,\n"
-" when you unset /AWAY, and when they are sent\n"
-" to you.\n"
-" LOGON You will only be notified of memos when you log\n"
-" on or when you unset /AWAY.\n"
-" NEW You will only be notified of memos when they\n"
-" are sent to you.\n"
-" MAIL You will be notified of memos by email as well as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF You will not receive any notification of memos.\n"
-" \n"
-"ON is essentially LOGON and NEW combined."
-msgstr ""
-"Sintàxi: SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-"\n"
-"Canvia quan se't notificarà de nous memos:\n"
-"\n"
-" ON Notificació de memos quan et conectis,\n"
-" quan treguis /AWAY, i quan \n"
-" s'enviin\n"
-" LOGON Sols seras notificat de memos quan et conectis\n"
-" o quan treguis /AWAY.\n"
-" NEW Sols seras notificat de memos quan se't \n"
-" enviin.\n"
-" MAIL You will be notified of memos by email aswell as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF No rebràs cap notificació per memos.\n"
-"\n"
-"ON és escencialment LOGON i NEW combinats."
-
-#, fuzzy
-msgid ""
-"Syntax: READONLY {ON | OFF}\n"
-" \n"
-"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
-"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
-"suspend or forbid nicknames and channels, and manage news,\n"
-"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
-"terminated or restarted.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--readonly."
-msgstr ""
-"Sintàxi: SET READONLY {ON | OFF}\n"
-"\n"
-"Estableix el mode nomès lectura a activat o desactivat. En mode\n"
-"nomès lectura, els usuaris normals no podran modificar dades\n"
-"de serveis, incloent accés a llistes de canals i\n"
-"nicknames, etc. IRCops amb suficients privilegis amb\n"
-"els serveis podren modificar la llista AKILL de\n"
-"serveis i eliminar o prohibir nicknames i canals, però\n"
-"cap d'aquests canvios sera guardat excepte que el\n"
-"mode nomès lectura es desactivi abans de que els serveis\n"
-"siguin desactivats o reiniciats.\n"
-"\n"
-"Aquesta opció es equivalent a l'opció -readonly en\n"
-"la linea de comandes."
-
-#, fuzzy
-msgid ""
-"Syntax: SUPERADMIN {ON | OFF}\n"
-" \n"
-"Setting this will grant you extra privileges such as the\n"
-"ability to be \"founder\" on all channel's etc...\n"
-" \n"
-"This option is not persistent, and should only be used when\n"
-"needed, and set back to OFF when no longer needed."
-msgstr ""
-"Syntax: SET SUPERADMIN {ON | OFF}\n"
-"Setting this will grant you extra privlages such as the\n"
-"ability to be \"founder\" on all channel's etc...\n"
-"This opion is _NOT_ persistant, and should only be used when\n"
-"needed, and set back to OFF when no longer needed."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s that you are really the owner of this\n"
-"nick. Many commands require you to authenticate yourself\n"
-"with this command before you use them. The password\n"
-"should be the same one you sent with the REGISTER\n"
-"command."
-msgstr ""
-"Sintaxis: IDENTIFY [account] clau\n"
-"\n"
-"Informa a %s que tu ets realment el propietari del teu nick.\n"
-"Moltes comandes requereixen que t'identifiquis amb aquesta\n"
-"comanda abans d'utilitzar-les. La clau hauria de ser la mateixa\n"
-"que va ser enviada amb la comanda REGISTER."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s to invite you or an optionally specified\n"
-"nick into the given channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
-msgstr ""
-"Sintàxi: INVITE canal\n"
-"\n"
-"Li diu a %s que et convidi al canal donat.\n"
-"\n"
-"Per defecte, limitat a AOPs o aquells amb nivell 5\n"
-"i major en el canal."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel. If no channel is\n"
-"given, all bans affecting you in channels you have access\n"
-"in are removed.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
-msgstr ""
-"Sintàxi: UNBAN canal [nick]\n"
-"\n"
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel.\n"
-"\n"
-"Per defecte, limitat a AOPs o aquells amb nivell 5\n"
-"i major en el canal."
-
-#, fuzzy
-msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
-"the real server of that name from connecting. The jupe\n"
-"may be removed using a standard SQUIT. If a reason is\n"
-"given, it is placed in the server information field;\n"
-"otherwise, the server information field will contain the\n"
-"text \"Juped by <nick>\", showing the nickname of the\n"
-"person who jupitered the server."
-msgstr ""
-"Sintàxi: JUPE servidor [raó]\n"
-"\n"
-"Li diu als serveis que fagin jupiter (saturn, mart,...) a un servidor\n"
-"-- és a dir, crear un \"servidor\" fals conectant als\n"
-"serveis el qual preveu al servidor real de\n"
-"connectar-se. El jupe pot ser eliminat utilitzant la comanda\n"
-"estandart SQUIT. Si una raó es especificada, es afegida\n"
-"en el camp d'informació sobre el servidor; d'altra\n"
-"banda, el camp de informació sobre el servidor tindra\n"
-"el text \"Juped per <nick>\", mostrant el nickname\n"
-"de la persona que va jupitejar el servidor.\n"
-"\n"
-"Limitat a administradors de serveis."
-
-msgid "Tells you about the last time a user was seen"
-msgstr ""
-
-#, fuzzy
-msgid "Terminate Services WITHOUT saving"
-msgstr ""
-" SHUTDOWN Termina el programa de serveis guardant els\n"
-" canvios"
-
-#, fuzzy
-msgid "Terminate services with save"
-msgstr ""
-" SHUTDOWN Termina el programa de serveis guardant els\n"
-" canvios"
-
-msgid "Text"
-msgstr ""
-
-msgid ""
-"The ACCESS ADD command adds the given mask to the\n"
-"access list with the given user level; if the mask is\n"
-"already present on the list, its access level is changed to\n"
-"the level specified in the command. The level specified\n"
-"may be a numerical level or the name of a privilege (eg AUTOOP).\n"
-"When a user joins the channel the access they receive is from the\n"
-"highest level entry in the access list."
-msgstr ""
-
-msgid ""
-"The ACCESS DEL command removes the given nick from the\n"
-"access list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-"You may remove yourself from an access list, even if you\n"
-"do not have access to modify that list otherwise."
-msgstr ""
-
-msgid ""
-"The ACCESS LIST command displays the access list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" ACCESS #channel LIST 2-5,7-9\n"
-" Lists access entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The ACCESS VIEW command displays the access list similar\n"
-"to ACCESS LIST but shows the creator and last used time.\n"
-" \n"
-"The ACCESS CLEAR command clears all entries of the\n"
-"access list."
-msgstr ""
-
-msgid ""
-"The CLEAR command clears the channel access list. This requires channel "
-"founder access."
-msgstr ""
-
-#, c-format
-msgid ""
-"The CLEAR command lets you clean the database by removing all entries from "
-"the\n"
-"database that were added within time.\n"
-" \n"
-"Example:\n"
-" %s CLEAR 30m\n"
-" Will remove all entries that were added within the last 30 minutes."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The DEL command removes the given word from the\n"
-"bad words list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The LIST command displays the bad words list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" #channel LIST 2-5,7-9\n"
-" Lists bad words entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The CLEAR command clears all entries from the\n"
-"bad words list."
-msgstr ""
-"Sintàxi: HOP canal ADD nick\n"
-" HOP canal DEL {nick | instancia | llista}\n"
-" HOP canal LIST [mascara | llista]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Manté la llista HOP (HalfOP) per a un canal. La llista\n"
-"HOP li dóna a l'usuari el dret de ser automàticament\n"
-"halfopejat en el teu canal.\n"
-"\n"
-"La comanda HOP ADD agrega al nickname donat a la llista\n"
-"HOP.\n"
-"\n"
-"La comanda HOP DEL esborra el nickname donat de la\n"
-"llista HOP. Si una llista d'instàncies és donada, aquestes\n"
-"instàncies són esborrades. (Veure l'exemple per a LIST més\n"
-"endevant.)\n"
-"\n"
-"La comanda HOP LIST mostra la llista HOP. Si una\n"
-"mascara amb comodí és donada, només les instàncies\n"
-"que concordin amb la mascara són mostrades. Si una llista de\n"
-"instàncies és donada, només aquestes instàncies són mostrades;\n"
-"per exemple:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Mostra instàncies de HOP enumerades 2 a 5 y\n"
-" 7 a 9.\n"
-"\n"
-"La comanda HOP CLEAR neteja totes les instàncies de la\n"
-"llista HOP.\n"
-"\n"
-"Les comandes HOP ADD i HOP DEL estan limitades a\n"
-"AOPs o superior, mentre que la comanda HOP CLEAR\n"
-"sols pot ser utilitzada per el fundador del canal.\n"
-"\n"
-"Aquesta comanda pot haber estat deshabilitada per al teu canal.\n"
-"Si aquest és el cas, has de fer servir la llista d'accés. Veure\n"
-"/msg %s HELP ACCESS per a informació sobre la llista\n"
-"d'accés i /msg %s HELP SET XOP per a saber com canviar\n"
-"entre la llista d'accés i el sistema de llistes xOP."
-
-msgid ""
-"The ENTRYMSG ADD command adds the given message to\n"
-"the list of messages shown to users when they join\n"
-"the channel."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG CLEAR command clears all entries from\n"
-"the list of messages shown to users when they join\n"
-"the channel, effectively disabling entry messages."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG DEL command removes the specified message from\n"
-"the list of messages shown to users when they join\n"
-"the channel. You can remove a message by specifying its number\n"
-"which you can get by listing the messages as explained below."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG LIST command displays a listing of messages\n"
-"shown to users when they join the channel."
-msgstr ""
-
-msgid "The IMMED option is not available on this network."
-msgstr "The IMMED option is not available on this network."
-
-#, fuzzy, c-format
-msgid ""
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-" \n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it). Use LEVELS SET founder to make a level\n"
-"founder only.\n"
-" \n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel.\n"
-" \n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
-msgstr ""
-"Sintàxi: LEVELS canal SET tipo [nivell|FOUNDER]\n"
-" LEVELS canal {DIS | DISABLE} tipo\n"
-" LEVELS canal LIST\n"
-" LEVELS canal RESET\n"
-"\n"
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-"\n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it).\n"
-"\n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel (see\n"
-"HELP ACCESS LEVELS).\n"
-"\n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
-
-msgid ""
-"The LIST command allows you to list existing entries on the channel access "
-"list.\n"
-"If a mask is given, the mask is wildcard matched against all existing "
-"entries on the\n"
-"access list, and only those entries are returned. If a set of flags is "
-"given, only those\n"
-"on the access list with the specified flags are returned."
-msgstr ""
-
-msgid ""
-"The MODIFY command allows you to modify the access list. If the mask is\n"
-"not already on the access list it is added, then the changes are applied.\n"
-"If the mask has no more flags, then the mask is removed from the access "
-"list.\n"
-"Additionally, you may use +* or -* to add or remove all flags, respectively. "
-"You are\n"
-"only able to modify the access list if you have the proper permission on the "
-"channel,\n"
-"and even then you can only give other people access to the equivalent of "
-"what your access is."
-msgstr ""
-
-msgid ""
-"The STATS command prints out statistics about stored nicks and memory usage."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
-"after registering if it isn't the default setting already."
-msgstr ""
-"Escriu /msg %s SET EMAIL e-mail per provar el teu e-mail.\n"
-"Respectems la teva privacitat; Aquest e-mail no sera entregat\n"
-"a cap persona."
-
-#, c-format
-msgid ""
-"The %s command allows users to configure logging settings\n"
-"for their channel. If no parameters are given this command\n"
-"lists the current logging methods in place for this channel.\n"
-" \n"
-"Otherwise, command must be a command name, and method\n"
-"is one of the following logging methods:\n"
-" \n"
-" MESSAGE [status], NOTICE [status], MEMO\n"
-" \n"
-"Which are used to message, notice, and memo the channel respectively.\n"
-"With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
-"to your channel. Status may be a channel status such as @ or +.\n"
-" \n"
-"To remove a logging method use the same syntax as you would to add it.\n"
-" \n"
-"Example:\n"
-" %s #anope chanserv/access MESSAGE @\n"
-" Would message any channel operators whenever someone used the\n"
-" ACCESS command on ChanServ on the channel."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The %s list for %s is full."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid "The %s list has been cleared."
-msgstr "La llista de AKILLs ha estat netegada."
-
-msgid "The AKILL list has been cleared."
-msgstr "La llista de AKILLs ha estat netegada."
-
-#, fuzzy, c-format
-msgid "The Defcon level is now at: %d"
-msgstr "The Defcon Level is now at Level: %d"
-
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr "The E-mail address of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr "The E-mail address of %s will now be shown in %s INFO displays."
-
-msgid "The available flags are:"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The defcon system can be used to implement a pre-defined\n"
-"set of restrictions to services useful during an attempted\n"
-"attack on the network."
-msgstr ""
-"Syntax: DEFCON [1|2|3|4|5]\n"
-"The defcon system can be used to implement a pre-defined\n"
-"set of restrictions to services useful during an attempted\n"
-"attack on the network."
-
-#, c-format
-msgid "The email address %s has reached its usage limit of %d users."
-msgstr ""
-
-#, c-format
-msgid "The email address %s has reached its usage limit of 1 user."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The entry message list for %s is full."
-msgstr "Greet message for %s unset."
-
-msgid "The following feature/function names are available:"
-msgstr ""
-
-msgid ""
-"The given mask may also be a channel, which will use the\n"
-"access list from the other channel up to the given level."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"The host %s currently has %d sessions with a limit of %d because it matches "
-"entry: %s."
-msgstr "El host %s actualment te %d sessions amb un límit de %d."
-
-#, c-format
-msgid "The last memo you sent to %s (sent on %s) has been read."
-msgstr "The last memo you sent to %s (sent on %s) has been read."
-
-#, c-format
-msgid "The last memo you sent to %s (sent on %s) has not yet been read."
-msgstr "The last memo you sent to %s (sent on %s) has not yet been read."
-
-#, c-format
-msgid "The last quit message of %s will now be hidden from %s INFO displays."
-msgstr "The last quit message of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The last quit message of %s will now be shown in %s INFO displays."
-msgstr "The last quit message of %s will now be shown in %s INFO displays."
-
-#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
-msgstr ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
-msgstr ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
-
-#, fuzzy, c-format
-msgid "The limit on %s is not valid."
-msgstr "El límit de memos per a %s no pot ser canviat."
-
-msgid "The mask must contain at least one non wildcard character."
-msgstr ""
-
-#, c-format
-msgid "The memo limit for %s may not be changed."
-msgstr "El límit de memos per a %s no pot ser canviat."
-
-#, fuzzy, c-format
-msgid "The mode lock list of %s is full."
-msgstr "Greet message for %s unset."
-
-#, c-format
-msgid "The new display MUST be a nickname of the nickname group %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The new display is now %s."
-msgstr "The Defcon Level is now at Level: %d"
-
-#, c-format
-msgid "The nick %s is now being changed to %s."
-msgstr "The nick %s is now being changed to %s."
-
-msgid "The old information is the same as the new information specified."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The oper info already exists on %s."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy, c-format
-msgid "The oper info list for %s is full."
-msgstr "Greet message for %s unset."
-
-#, c-format
-msgid ""
-"The services access status of %s will now be hidden from %s INFO displays."
-msgstr ""
-"The services access status of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The services access status of %s will now be shown in %s INFO displays."
-msgstr ""
-"The services access status of %s will now be shown in %s INFO displays."
-
-#, fuzzy
-msgid "The session exception list is empty."
-msgstr " EXCEPTION Modifica la llista de límit de sessió"
-
-msgid ""
-"The user with your nick has been removed. Use this command again\n"
-"to release services's hold on your nick."
-msgstr ""
-
-#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "There are %d memos on channel %s."
-
-msgid ""
-"There are no bots available at this time.\n"
-"Ask a Services Operator to create one!"
-msgstr ""
-"No hi ha bots disponibles en aquest moment.\n"
-"Demana-li a un administrador de serveis que en fagi un!"
-
-msgid "There are no configured servers."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "There are no forbids of type %s."
-msgstr "There are %d memos on channel %s."
-
-#, fuzzy
-msgid "There are too many nicks in your group."
-msgstr " DELALL Delete the vhost for all nicks in a group"
-
-#, fuzzy, c-format
-msgid "There currently are no logging configurations for %s."
-msgstr " RELOAD Recarrega la configuració dels serveis"
-
-#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "There is %d memo on channel %s."
-
-#, fuzzy, c-format
-msgid ""
-"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
-msgstr "Escriu /msg %s READ %d per a llegir-lo."
-
-#, c-format
-msgid "There is no bot assigned to %s anymore."
-msgstr "Ja no hi ha un bot assignat a %s."
-
-msgid "There is no logon news."
-msgstr "No hi ha notícies de entrada."
-
-msgid "There is no oper news."
-msgstr "No hay notícies de oper."
-
-msgid "There is no random news."
-msgstr "No hi ha notícies al azar."
-
-#, fuzzy, c-format
-msgid "There is no such configuration block %s."
-msgstr " RELOAD Recarrega la configuració dels serveis"
-
-#, fuzzy, c-format
-msgid "There is no such mode %s."
-msgstr "No hay notícies de oper."
-
-msgid "There's no email address set for your nick."
-msgstr "There's no email address set for your nick."
-
-#, fuzzy, c-format
-msgid "This channel has been forbidden: %s"
-msgstr "Aquest canal ha estat registrat amb %s."
-
-#, fuzzy
-msgid "This channel has been suspended."
-msgstr "Aquest canal esta prohibit."
-
-#, fuzzy
-msgid "This channel is suspended."
-msgstr "Aquest canal esta prohibit."
-
-msgid "This channel may not be used."
-msgstr "Aquest canal esta prohibit."
-
-msgid ""
-"This command allows managing DNS zones used for controlling what servers "
-"users\n"
-"are directed to when connecting. Omitting all parameters prints out the "
-"status of\n"
-"the DNS zone.\n"
-" \n"
-"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to "
-"this\n"
-"zone with the ADDSERVER command.\n"
-" \n"
-"The ADDSERVER command adds a server to the given zone. When a query is done, "
-"the\n"
-"zone in question is served if it exists, else all servers in all zones are "
-"served.\n"
-"A server may be in more than one zone.\n"
-" \n"
-"The ADDIP command associates an IP with a server.\n"
-" \n"
-"The POOL and DEPOOL commands actually add and remove servers to their given "
-"zones."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command allows users to set the vhost of their\n"
-"CURRENT nick to be the vhost for all nicks in the same\n"
-"group."
-msgstr ""
-"Syntax: GROUP\n"
-"\n"
-"This command allows users to set the vhost of thier\n"
-"CURRENT nick to be the vhost for all nicks in the same\n"
-"group."
-
-msgid ""
-"This command also creates a new group for your nickname,\n"
-"that will allow you to register other nicks later sharing\n"
-"the same configuration, the same set of memos and the\n"
-"same channel privileges."
-msgstr ""
-
-#, c-format
-msgid "This command is an alias to the command %s."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command is used by several commands as a way to confirm\n"
-"changes made to your account.\n"
-" \n"
-"This is most commonly used to confirm your email address once\n"
-"you register or change it.\n"
-" \n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-msgstr ""
-"Syntax: CONFIRM passcode\n"
-"\n"
-"This is the second step of nickname registration process.\n"
-"You must perform this command in order to get your nickname\n"
-"registered with %s. The passcode (or called auth code also)\n"
-"is sent to your e-mail address in the first step of the\n"
-"registration process. For more information about the first\n"
-"stage of the registration process, type: /msg %s HELP REGISTER\n"
-"\n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-
-#, fuzzy
-msgid "This command lists information about the specified loaded module."
-msgstr ""
-"Syntax: MODINFO FileName\n"
-"This command lists information about the specified loaded module"
-
-#, fuzzy
-msgid ""
-"This command lists registered vhosts to the operator.\n"
-"If a key is specified, only entries whose nick or vhost match\n"
-"the pattern given in key are displayed e.g. Rob* for all\n"
-"entries beginning with \"Rob\"\n"
-"If a #X-Y style is used, only entries between the range of X\n"
-"and Y will be displayed, e.g. #1-3 will display the first 3\n"
-"nick/vhost entries."
-msgstr ""
-"Syntax: LIST [<key>|<#X-Y>]\n"
-"This command lists registered vhosts to the operator\n"
-"if a Key is specified, only entries whos nick or vhost match\n"
-"the pattern given in <key> are displayed e.g. Rob* for all\n"
-"entries beginning with \"Rob\"\n"
-"If a #X-Y style is used, only entries between the range of X\n"
-"and Y will be displayed, e.g. #1-3 will display the first 3\n"
-"nick/vhost entries.\n"
-"The list uses the value of NSListMax as a hard limit for the\n"
-"number of items to display to a operator at any 1 time.\n"
-"Limited to Services operators."
-
-#, fuzzy
-msgid ""
-"This command loads the module named modname from the modules\n"
-"directory."
-msgstr ""
-"Syntax: MODLOAD FileName\n"
-"This command loads the module named FileName from the modules\n"
-"directory."
-
-#, fuzzy
-msgid ""
-"This command makes your nickname join the target nickname's\n"
-"group. password is the password of the target nickname.\n"
-" \n"
-"Joining a group will allow you to share your configuration,\n"
-"memos, and channel privileges with all the nicknames in the\n"
-"group, and much more!\n"
-" \n"
-"A group exists as long as it is useful. This means that even\n"
-"if a nick of the group is dropped, you won't lose the\n"
-"shared things described above, as long as there is at\n"
-"least one nick remaining in the group.\n"
-" \n"
-"You may be able to use this command even if you have not registered\n"
-"your nick yet. If your nick is already registered, you'll\n"
-"need to identify yourself before using this command.\n"
-" \n"
-"It is recommended to use this command with a non-registered\n"
-"nick because it will be registered automatically when\n"
-"using this command. You may use it with a registered nick (to\n"
-"change your group) only if your network administrators allowed\n"
-"it.\n"
-" \n"
-"You can only be in one group at a time. Group merging is\n"
-"not possible.\n"
-" \n"
-"Note: all the nicknames of a group have the same password."
-msgstr ""
-"Sintaxis: GROUP grupo clau\n"
-"\n"
-"Aquesta comanda fa que el teu nickname s'adhereixi al grup de nicknames\n"
-"grup. clau es la de teu nickname.\n"
-"\n"
-"L'unió a un grup et permetra compartir configuracions,\n"
-"memos, i privilegis en canals amb tots els nicknames en un\n"
-"grup, i molt més!\n"
-" \n"
-"Un grup existeix sempre i quant sigui servible. Això\n"
-"significa que si un nick del grup es eliminat, no perdràs\n"
-"les caracteristiques compartides descrites anteriorment, sempre i\n"
-"quant al menys un nick quedi al grup.\n"
-"\n"
-"Pots utilitzar aquesta comanda encara que no estigui registrar el teu\n"
-"nick. Si el teu nick ja esta registrat hauras d'identificar-te\n"
-"abans d'utilitzar aquesta comanda. Escriu /msg %s HELP\n"
-"IDENTIFY per més informació. Potser que no sigui possible\n"
-"a la teva xarxa.\n"
-"\n"
-"Es recomenable utilitzar aquesta comanda amb un nick no registrat ja\n"
-"que sera registrat automaticament quant l'utilitzis.\n"
-"Pots utilitzar-la amb un nick ja registrat (per canviar de grup) \n"
-"sols si els administradors de la teva xarxa ho permeten.\n"
-"\n"
-"Pots estar en un sol grup a la vegada. L'unió de\n"
-"grups no es possible.\n"
-"\n"
-"Tingues en compte: tots els nicks en un grup comparteixen la\n"
-"mateixa clau."
-
-msgid ""
-"This command manages your auto join list. When you identify\n"
-"you will automatically join the channels on your auto join list.\n"
-"Services Operators may provide a nick to modify other users'\n"
-"auto join lists."
-msgstr ""
-
-msgid ""
-"This command may not be used on this network because nickname ownership is "
-"disabled."
-msgstr ""
-
-#, fuzzy
-msgid "This command reloads the module named modname."
-msgstr ""
-"Syntax: MODLOAD FileName\n"
-"This command loads the module named FileName from the modules\n"
-"directory."
-
-msgid "This command retrieves the vhost requests."
-msgstr ""
-
-msgid ""
-"This command searches the Services logfiles for messages\n"
-"that match the given pattern. The day and limit argument\n"
-"may be used to specify how many days of logs to search\n"
-"and the number of replies to limit to. By default this\n"
-"command searches one week of logs, and limits replies\n"
-"to 50.\n"
-" \n"
-"For example:\n"
-" LOGSEARCH +21d +500l Anope\n"
-" Searches the last 21 days worth of logs for messages\n"
-" containing Anope and lists the most recent 500 of them."
-msgstr ""
-
-msgid ""
-"This command tells you what a users access is on a channel\n"
-"and what access entries, if any, they match. Additionally it\n"
-"will tell you of any auto kick entries they match. Usage of\n"
-"this command is limited to users who have the ability to modify\n"
-"access entries on the channel."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, and url. Everything else\n"
-"is reset. You may not ungroup yourself if there is only one nick in\n"
-"your group."
-msgstr ""
-"Syntax: UNGROUP [nick]\n"
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, url, and icq. Everything\n"
-"else is reset. You may not ungroup yourself if there is only one\n"
-"nick in your group."
-
-#, fuzzy
-msgid "This command unloads the module named modname."
-msgstr ""
-"Syntax: MODLOAD FileName\n"
-"This command loads the module named FileName from the modules\n"
-"directory."
-
-msgid "This command will resend you the registration confirmation email."
-msgstr ""
-
-#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "This nickname has been forbidden: %s"
-msgstr "This nickname is currently suspended, reason: %s"
-
-#, fuzzy, c-format
-msgid "This nickname has been recovered by %s."
-msgstr "This nickname is currently suspended, reason: %s"
-
-#, c-format
-msgid ""
-"This nickname has been recovered by %s. If you did not do\n"
-"this then %s may have your password, and you should change it."
-msgstr ""
-
-#, fuzzy
-msgid "This nickname has been registered; you may not use it."
-msgstr "Aquest canal ha estat registrat amb %s."
-
-#, fuzzy
-msgid "This nickname is suspended."
-msgstr "Aquest canal esta prohibit."
-
-#, c-format
-msgid ""
-"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
-"please choose a different nick."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr "Memo %d de %s (%s). per a esborrar-lo escriu: /msg %s DEL %s %d"
-
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr "Memo %d de %s (%s). per a esborrar-lo escriu: /msg %s DEL %s %d"
-
-msgid "To protect ops against bot kicks"
-msgstr ""
-
-msgid "To protect voices against bot kicks"
-msgstr ""
-
-msgid ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
-msgstr ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
-
-#, fuzzy, c-format
-msgid "Too many results for %s."
-msgstr "Lllista d'accés per %s:"
-
-#, c-format
-msgid "Top %i of %s"
-msgstr ""
-
-#, fuzzy
-msgid "Topic"
-msgstr "Lock de tòpic"
-
-#, fuzzy
-msgid "Topic lock"
-msgstr "Lock de tòpic"
-
-#, fuzzy, c-format
-msgid "Topic lock option for %s is now off."
-msgstr "Topic lock option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Topic lock option for %s is now on."
-msgstr "Topic lock option for %s is now ON."
-
-#, fuzzy
-msgid "Topic retention"
-msgstr "Retenció de tòpic"
-
-#, fuzzy, c-format
-msgid "Topic retention option for %s is now off."
-msgstr "Topic retention option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Topic retention option for %s is now on."
-msgstr "Topic retention option for %s is now ON."
-
-msgid "Topic set by"
-msgstr ""
-
-msgid "Turn caps lock OFF!"
-msgstr "Desactiva les majuscules!"
-
-#, fuzzy
-msgid "Turn chanstats statistics on or off"
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-#, fuzzy
-msgid "Turn nickname security on or off"
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-#, fuzzy
-msgid "Turn protection on or off"
-msgstr " KILL Activa o desactiva la protecció"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
-msgstr ""
-"Syntax: SASET nickname PRIVATE {ON | OFF}\n"
-"\n"
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's privacy option on or off for your nick.\n"
-"With PRIVATE set, your nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows your nickname can still get\n"
-"information on it using the INFO command.)"
-msgstr ""
-"Sintaxis: SET PRIVATE {ON | OFF}\n"
-"\n"
-"Fa que %s activi o desactivi l'opció de privacitat del teu\n"
-"nick. Amb PRIVATE establert,el teu nickname no apareixera en les\n"
-"llistes de nicknames generades amb la comanda LIST de %s.\n"
-"(D'altra banda, qualsevol persona que sapigue el teu nick podra comprobar\n"
-"la teva informació utilitzant la comanda INFO.)"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Sintaxis: SET SECURE {ON | OFF}\n"
-"\n"
-"Canvia les caracteristiques de seguretat de %s pel teu nick a on\n"
-"u off. Amb SECURE establert, has d'especificar la teva clau \n"
-"per ser reconegut com propietari del nick, a pesar de que la teva adreça\n"
-"estigui a la llista d'accéss. D'altra banda, si estas a la llista \n"
-"d'accés, %s no te auto-kickejara no important l'establiment de l'opció\n"
-"KILL."
-
-#, fuzzy
-msgid "Turns chanstats channel statistics ON or OFF for this user."
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-#, fuzzy
-msgid "Turns chanstats statistics ON or OFF."
-msgstr " SECURE Activa o desactiva la seguretat de nickname"
-
-#, fuzzy, c-format
-msgid ""
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-msgstr ""
-"Syntax: SASET nickname KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-"\n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-
-#, fuzzy, c-format
-msgid ""
-"Turns the automatic protection option for your nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take your nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-msgstr ""
-"Sintaxis: SET KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Canvia la protecció automàtica del teu nick a on o off.\n"
-"Amb protecció on, si un altre usuari intenta utilitzar el teu nick,\n"
-"tindra un minut per canviar de nick, desprès del qual\n"
-"%s canviara el seu nick automaticament.\n"
-"\n"
-"Si estableixes QUICK, l'usuari tibdrà nomès 20 segons\n"
-"per canviar el nick en comptes dels 60 habituals. Si selecciones\n"
-"IMMED, el nick del usuari sera canviat automaticament\n"
-"sense ser avisat ni donar-li oportunitat de canviar-lo abans;\n"
-"per favor no utilitzis aquesta opció excepte que ho consideris\n"
-"necessari. A mes, els administradors de la xarxa poden haber\n"
-"deshabilitat aquesta opció."
-
-msgid "Type"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
-msgstr ""
-"Escriu /msg %s HELP opció per més informació\n"
-"sobre una opció en particular."
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option.\n"
-" \n"
-"Note: access to this command is controlled by the\n"
-"level SET."
-msgstr ""
-"Type /msg %s HELP SASET option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname. "
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname."
-msgstr ""
-"Type /msg %s HELP SASET option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname. "
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information on a\n"
-"particular option."
-msgstr ""
-"Escriu /msg %s HELP opció per més informació\n"
-"sobre una opció en particular."
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
-msgstr ""
-"Escriu /msg %s SET EMAIL e-mail per provar el teu e-mail.\n"
-"Respectems la teva privacitat; Aquest e-mail no sera entregat\n"
-"a cap persona."
-
-#, fuzzy
-msgid "Un-Load a module"
-msgstr " MODUNLOAD Un-Load a module"
-
-#, fuzzy, c-format
-msgid "Unable to find regex engine %s."
-msgstr "Unable to remove module %s"
-
-#, fuzzy, c-format
-msgid "Unable to load module %s."
-msgstr "Unable to load module %s"
-
-#, fuzzy, c-format
-msgid "Unable to remove module %s."
-msgstr "Unable to remove module %s"
-
-#, fuzzy
-msgid "Unassigns a bot from a channel"
-msgstr "UNASSIGN Unassigns a bot from a channel"
-
-#, fuzzy
-msgid ""
-"Unassigns a bot from a channel. When you use this command,\n"
-"the bot won't join the channel anymore. However, bot\n"
-"configuration for the channel is kept, so you will always\n"
-"be able to reassign a bot later without having to reconfigure\n"
-"it entirely."
-msgstr ""
-"Sintàxi: UNASSIGN canal\n"
-"\n"
-"Desassigna un bot d'un canal. A l'utilitzar aquesta comanda\n"
-"el bot ja no entrara al canal. De totes maneres, la configuració\n"
-"del bot pel canal es enmagatzemada, així et sera possible\n"
-"reassignar un bot sense haver de configurar-lo de nou."
-
-#, fuzzy
-msgid "Underlines kicker"
-msgstr " Kicker per subrallats : %s"
-
-#, fuzzy
-msgid "Unknown SET option."
-msgstr "Unknown SASET option %s."
-
-#, fuzzy, c-format
-msgid "Unknown STATS option: %s"
-msgstr "Opció STATS %s desconeguda."
-
-#, fuzzy, c-format
-msgid "Unknown command %s."
-msgstr "Opció %s desconeguda."
-
-#, fuzzy, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Comanda no coneguda %s. \"%s%s HELP\" per ajuda."
-
-#, fuzzy, c-format
-msgid "Unknown mode character %c ignored."
-msgstr "Caràcter de Mode %c desconegut i ignorat."
-
-#, fuzzy, c-format
-msgid "Unknown parameter: %s"
-msgstr "SET Opció estabilment"
-
-msgid "Unpooled"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Unregisters the named channel. Can only be used by\n"
-"the channel founder."
-msgstr ""
-"Sintaxis: DROP canal\n"
-"\n"
-"Desenregistra el canal especificat. Nomès pot ser utilitzat pel\n"
-"fundador del canal."
-
-#, fuzzy
-msgid ""
-"Unregisters the specified channel. Only Services Operators\n"
-"can drop a channel of which they are not the founder of."
-msgstr ""
-"Sintàxi: DROP canal\n"
-"\n"
-"Desregistra el canal donat. Només\n"
-"administradors de serveis poden eliminar un\n"
-"canal per el qual no s'haguin identificado."
-
-#, fuzzy
-msgid "Unsuspend a given nick"
-msgstr " UNSUSPEND Unsuspend a given nick"
-
-msgid "Unsuspends a nickname which allows it to be used again."
-msgstr ""
-
-msgid ""
-"Updates a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is updated. If channel is omitted then\n"
-"your channel status is updated on every channel you are in."
-msgstr ""
-
-#, fuzzy
-msgid "Updates a selected nicks status on a channel"
-msgstr " BAN Bans a selected nick on a channel"
-
-#, fuzzy
-msgid "Updates your current status, i.e. it checks for new memos"
-msgstr ""
-" UPDATE Updates your current status, i.e. it checks for new memos"
-
-#, fuzzy
-msgid ""
-"Updates your current status, i.e. it checks for new memos,\n"
-"sets needed channel modes and updates your vhost and\n"
-"your userflags (lastseentime, etc)."
-msgstr ""
-"Syntax: UPDATE\n"
-"Updates your current status, i.e. it checks for new memos,\n"
-"sets needed chanmodes (ModeonID) and updates your vhost and\n"
-"your userflags (lastseentime, etc)."
-
-msgid "Updating databases."
-msgstr "Actualitzant les bases de dades."
-
-#, c-format
-msgid "Uplink capab: %s"
-msgstr "Uplink capab: %s"
-
-#, c-format
-msgid "Uplink server: %s"
-msgstr "Uplink server: %s"
-
-#, c-format
-msgid "Use the %s ALL command to list all commands and their descriptions."
-msgstr ""
-
-msgid "Used on"
-msgstr ""
-
-#, fuzzy
-msgid "Used to manage channels"
-msgstr "%s changed your usermodes."
-
-#, fuzzy
-msgid "Used to manage the list of privileged users"
-msgstr " ACCESS Modifica la llista d'usuaris privilegiats"
-
-msgid "Used to modify the channel status of you or other users"
-msgstr ""
-
-#, fuzzy
-msgid "User has been banned from the channel"
-msgstr "Has estat desbanegat de %s."
-
-#, fuzzy, c-format
-msgid "User limit for %s removed."
-msgstr "vhost for %s removed."
-
-#, fuzzy, c-format
-msgid "User limit for %s set to %d."
-msgstr "Límite de memos per a %s establert a %d."
-
-#, fuzzy
-msgid "Users"
-msgstr "Llista de bots:"
-
-#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, fuzzy
-msgid "Users list:"
-msgstr "Llista de bots:"
-
-msgid "VHost"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "VHost for %s set to %s."
-msgstr "vhost for %s set to %s."
-
-#, fuzzy, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "vhost for %s set to %s@%s."
-
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s."
-msgstr "vhost for group %s set to %s."
-
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "vhost for group %s set to %s@%s."
-
-msgid "VIEW host"
-msgstr ""
-
-#, fuzzy
-msgid "VIEW [mask | list | id]"
-msgstr "LIST [canal] [llista | NEW]"
-
-msgid "VIEW [mask | list]"
-msgstr ""
-
-msgid "Value"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Value of %s:%s changed to %s"
-msgstr "El Fundador de %s cambiat a %s."
-
-msgid "Vhost"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Vhost for %s removed."
-msgstr "vhost for %s removed."
-
-#, fuzzy
-msgid "View and change Services Operators"
-msgstr "%s is a services operator of type %s."
-
-msgid "View and change configuration file settings"
-msgstr ""
-
-#, fuzzy
-msgid "View the list of host sessions"
-msgstr " SESSION Mostra la llista de sessions de host"
-
-msgid "Voices protection"
-msgstr "Protecció de Voices"
-
-msgid "Watch your language!"
-msgstr "Cuida el teu llenguatge!"
-
-#, c-format
-msgid ""
-"When private is set, the channel will not appear in\n"
-"%s's %s command."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Without a parameter, displays information on the number of\n"
-"memos you have, how many of them are unread, and how many\n"
-"total memos you can receive.\n"
-" \n"
-"With a channel parameter, displays the same information for\n"
-"the given channel.\n"
-" \n"
-"With a nickname parameter, displays the same information\n"
-"for the given nickname. This is limited to Services\n"
-"Operators."
-msgstr ""
-"Sintàxi: INFO [nick | canal]\n"
-"\n"
-"Sense un paràmetro, mostra informació del nombre\n"
-"de memos que tens, quants d' ells encara no s'han\n"
-"llegit, i el nombre total de memos que pots rebre.\n"
-"\n"
-"amb un canal de paràmetre, mostra la mateixa informació\n"
-"pel canal donat.\n"
-"\n"
-"amb un nickname de paràmetr, mostra la misma\n"
-"informació pel nickname donat. Aquest us està\n"
-"limitat a administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Without a parameter, reverses the effect of the IDENTIFY\n"
-"command, i.e. make you not recognized as the real owner of the nick\n"
-"anymore. Note, however, that you won't be asked to reidentify\n"
-"yourself.\n"
-" \n"
-"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
-"to re-identify. This is limited to Services Operators."
-msgstr ""
-"Sintaxis: LOGOUT [nickname [REVALIDATE]]\n"
-"\n"
-"Sense un parametre, desfà l'efecte de la comanda IDENTIFY, \n"
-"és a dir, fa que no siguis reconegut com l'autentic propietari del nick\n"
-"Tingues en compte, que no seras necessari tornar-te a identificar.\n"
-"\n"
-"Amb un parametre, fa lo mateix pel nick donat. Si\n"
-"a més a més especifiques REVALIDATE, els serveis requeriran\n"
-"a l'esmentat nick a reidentificar-se. Aquest ús esta limitat a\n"
-"administradors de serveis."
-
-#, fuzzy
-msgid ""
-"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
-" \n"
-"With the AKILL option, displays the current size of the\n"
-"AKILL list and the current default expiry time.\n"
-" \n"
-"The RESET option currently resets the maximum user count\n"
-"to the number of users currently present on the network.\n"
-" \n"
-"The UPLINK option displays information about the current\n"
-"server Anope uses as an uplink to the network.\n"
-" \n"
-"The HASH option displays information about the hash maps.\n"
-" \n"
-"The ALL option displays all of the above statistics."
-msgstr ""
-"Sintàxi: STATS [AKILL | ALL | RESET]\n"
-"\n"
-"Sense una opció, mostra el nom actual d'usuaris i\n"
-"IRCops en linea (excluient els serveis), el màxim\n"
-"nombre d'usuaris desde que els serveis s'han iniciat, i\n"
-"el temps que els serveis han estat funcionant.\n"
-"\n"
-"Amb L'opció AKILL, mostra la mida actual de la\n"
-"llista AKILL i l'actual temps d'expiració per defecte.\n"
-"\n"
-"L'opció ALL esta sols disponible per administradors de\n"
-"serveis, i mostra informació en el us de memòria dels\n"
-"serveis. Utilitzar aquesta opció pot congelar els\n"
-"serveis per un curt periode de temps en xarxes grans,\n"
-"aixi que no es recomana utilitzar sovint.\n"
-"\n"
-"L'opció RESET estableix el nombre màxim d'usuaris\n"
-"al nombre d'usuaris actualment presents en la xarxa."
-
-msgid "Word"
-msgstr ""
-
-#, c-format
-msgid "You are already a member of the group of %s."
-msgstr "Ja ets membre del grup de %s."
-
-msgid "You are already identified."
-msgstr "You are already identified."
-
-#, fuzzy, c-format
-msgid "You are already in %s!"
-msgstr "You are already in %s! "
-
-#, fuzzy
-msgid "You are no longer a super admin."
-msgstr "You are no longer a SuperAdmin"
-
-#, fuzzy
-msgid "You are not identified."
-msgstr "You are already identified."
-
-#, fuzzy
-msgid "You are not permitted to be on this channel."
-msgstr "No estas autoritzat a canviar el teu límit de memos."
-
-msgid "You are not permitted to change your memo limit."
-msgstr "No estas autoritzat a canviar el teu límit de memos."
-
-#, fuzzy
-msgid "You are not using a client certificate."
-msgstr "You are already identified."
-
-#, fuzzy
-msgid "You are now a super admin."
-msgstr "You are now a SuperAdmin"
-
-msgid "You are now an IRC Operator."
-msgstr "You are now an IRC Operator."
-
-#, fuzzy
-msgid "You are now identified for your nick. Change your password now."
-msgstr "You are now identified for your nick. Change your password now."
-
-#, c-format
-msgid "You are now in the group of %s."
-msgstr "Ara ets membre en el grup de %s."
-
-#, fuzzy, c-format
-msgid ""
-"You are over your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
-msgstr ""
-"Advertència: Has sobrepassat el màximo numero de memos (%d). Et resultara "
-"impossible rebre més memos fins que esborris alguns dels existents."
-
-msgid "You can not NOOP Services."
-msgstr ""
-
-msgid ""
-"You can not disable the founder privilege because it would be impossible to "
-"reenable it at a later time."
-msgstr ""
-
-#, fuzzy
-msgid "You can not jupe an already juped server."
-msgstr "You can not jupe your services server or your uplink server."
-
-#, fuzzy
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "You can not jupe your services server or your uplink server."
-
-#, c-format
-msgid "You can not reload this module directly, instead reload %s."
-msgstr ""
-
-msgid "You can not request a receipt when sending a memo to yourself."
-msgstr "You can not request a receipt when sending a memo to yourself."
-
-#, fuzzy, c-format
-msgid "You can't %s yourself!"
-msgstr "No pots fer GHOST a tu mateix!"
-
-#, fuzzy
-msgid "You can't add a channel to its own access list."
-msgstr "No hi ha instàncies que concordin a la llista d'accés de %s ."
-
-#, fuzzy, c-format
-msgid "You can't logout %s, they are a Services Operator."
-msgstr "Can't logout %s because he's a services operator."
-
-#, fuzzy, c-format
-msgid "You cannot %s on this network."
-msgstr "No pots establir la teva adreça e-mail en aquesta xarxa."
-
-#, fuzzy, c-format
-msgid "You cannot set the %c flag."
-msgstr "You cannot use this command."
-
-#, c-format
-msgid "You cannot set the memo limit for %s higher than %d."
-msgstr "No pots establir el límite de memos per %s mes de %d."
-
-#, c-format
-msgid "You cannot set your memo limit higher than %d."
-msgstr "No pots establir el teu límit de memos a mes de %d."
-
-#, fuzzy
-msgid "You cannot unassign bots while persist is set on the channel."
-msgstr "You can not unassign bots while persist is set on the channel."
-
-msgid "You cannot unset the e-mail on this network."
-msgstr "No pots establir la teva adreça e-mail en aquesta xarxa."
-
-msgid "You cannot use this command."
-msgstr "You cannot use this command."
-
-#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Tens %d memos, dels quals %d encara no han estat llegits."
-
-#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Tens %d memos, dels quals 1 encara no ha estat llegit."
-
-#, c-format
-msgid "You currently have %d memos."
-msgstr "Tens %d memos."
-
-#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Tens %d memos, cap d'ells llegit."
-
-msgid "You currently have 1 memo, and it has not yet been read."
-msgstr "Tens 1 memo i encara no ha estat llegit."
-
-msgid "You currently have 1 memo."
-msgstr "Tens 1 memo."
-
-msgid "You currently have no memos."
-msgstr "No tens memos."
-
-#, c-format
-msgid "You do not have access to set mode %c."
-msgstr ""
-
-#, c-format
-msgid "You do not have the access to change %s's modes."
-msgstr ""
-
-#, c-format
-msgid "You found me, %s!"
-msgstr ""
-
-#, c-format
-msgid "You have %d new memos."
-msgstr "Tens %d memos nous."
-
-msgid "You have 1 new memo."
-msgstr "Tens 1 memo nou."
-
-#, fuzzy, c-format
-msgid ""
-"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
-msgstr "Escriu /msg %s READ %d per a llegir-lo."
-
-#, fuzzy, c-format
-msgid "You have been invited to %s by %s."
-msgstr "You have been invited to %s."
-
-#, c-format
-msgid "You have been invited to %s."
-msgstr "You have been invited to %s."
-
-#, fuzzy, c-format
-msgid "You have been logged in as %s."
-msgstr "El teu nick ha estat desconnectat."
-
-#, fuzzy
-msgid "You have been logged out."
-msgstr "El teu nick ha estat desconnectat."
-
-#, c-format
-msgid "You have been unbanned from %s."
-msgstr "Has estat desbanegat de %s."
-
-#, fuzzy, c-format
-msgid "You have been unbanned from %d channels."
-msgstr "Has estat desbanegat de %s."
-
-msgid "You have no limit on the number of memos you may keep."
-msgstr "No tens límit en el numero de memos que pots mantenir."
-
-#, fuzzy
-msgid "You have no memos."
-msgstr "Tens %d memos nous."
-
-#, fuzzy
-msgid "You have no new memos."
-msgstr "Tens %d memos nous."
-
-#, fuzzy, c-format
-msgid ""
-"You have reached your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
-msgstr ""
-"Advertència: Has assolit el màxim numero de memos (%d). No podras rebre mes "
-"memos fins que esborris alguns dels existents."
-
-#, fuzzy, c-format
-msgid "You have regained control of %s."
-msgstr "You have been invited to %s."
-
-#, fuzzy
-msgid "You may drop any nick within your group."
-msgstr " DELALL Delete the vhost for all nicks in a group"
-
-#, c-format
-msgid "You may not (un)lock mode %c."
-msgstr ""
-
-#, fuzzy
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "No pots establir la teva adreça e-mail en aquesta xarxa."
-
-#, fuzzy
-msgid "You may not change the email of an unconfirmed account."
-msgstr "No pots establir la teva adreça e-mail en aquesta xarxa."
-
-#, fuzzy
-msgid "You may not change the password of other Services Operators."
-msgstr "Can't logout %s because he's a services operator."
-
-#, fuzzy
-msgid "You may not drop other Services Operators' nicknames."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "You may not get the password of other Services Operators."
-msgstr "Can't logout %s because he's a services operator."
-
-#, fuzzy
-msgid "You may not suspend other Services Operators' nicknames."
-msgstr "Can't logout %s because he's a services operator."
-
-#, fuzzy
-msgid ""
-"You may view but not modify the access list of other Services Operators."
-msgstr "Can't logout %s because he's a services operator."
-
-#, fuzzy
-msgid ""
-"You may view but not modify the certificate list of other Services Operators."
-msgstr "Can't logout %s because he's a services operator."
-
-#, c-format
-msgid "You might see yourself in the mirror, %s."
-msgstr ""
-
-msgid "You must assign a bot to the channel before using this command."
-msgstr ""
-
-msgid "You must be a channel operator to register the channel."
-msgstr "Has de ser un operador de canal per registrar el canal."
-
-#, fuzzy, c-format
-msgid "You must be in %s to use this command."
-msgstr "You need to be identified to use this command."
-
-#, fuzzy
-msgid "You must confirm your account before you can register a channel."
-msgstr "Has de ser un operador de canal per registrar el canal."
-
-#, fuzzy
-msgid "You must confirm your account before you may request a vhost."
-msgstr "Has de ser un operador de canal per registrar el canal."
-
-#, fuzzy
-msgid "You must confirm your account before you may send a memo."
-msgstr "Has de ser un operador de canal per registrar el canal."
-
-#, c-format
-msgid ""
-"You must enter the channel name twice as a confirmation that you wish to drop"
-" %s."
-msgstr ""
-
-#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr "You have to be connected longer than %d seconds to register your nick."
-
-#, fuzzy, c-format
-msgid "You must have the %s(ME) privilege on the channel to use this command."
-msgstr "You need to be identified to use this command."
-
-msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
-"case you forget it."
-msgstr ""
-"Ara has de proveir un e-mail pel teu nick.\n"
-"Aquest e-mail et permetra recuperar la teva clau en\n"
-"cas de que la olvidis."
-
-msgid "You need to be identified to use this command."
-msgstr "You need to be identified to use this command."
-
-#, fuzzy
-msgid "You will be notified by message and by mail when new memos arrive."
-msgstr "Seràs notificat quan els memos nous se t'enviin."
-
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon and when they arrive, and by mail "
-"when they arrive."
-msgstr "Seràs notificat per nous memos quant et conectis i quant se t'enviin."
-
-msgid "You will be notified of new memos at logon and when they arrive."
-msgstr "Seràs notificat per nous memos quant et conectis i quant se t'enviin."
-
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon, and by mail when they arrive."
-msgstr "Seràs notificat per nous memos quant et conectis i quant se t'enviin."
-
-msgid "You will be notified of new memos at logon."
-msgstr "Seràs notificat per memos nous quant et conectis."
-
-msgid "You will be notified when new memos arrive."
-msgstr "Seràs notificat quan els memos nous se t'enviin."
-
-msgid "You will no longer be able to receive memos."
-msgstr "No et sera possible rebre més memos."
-
-msgid "You will no longer be informed via email."
-msgstr "You will no longer be informed via email."
-
-msgid "You will not be notified of new memos."
-msgstr "No seràs notificat per memos nous."
-
-msgid "You will now be informed about new memos via email."
-msgstr "You will now be informed about new memos via email."
-
-msgid "Your IRCd does not support SVSJOIN."
-msgstr ""
-
-msgid "Your IRCd does not support SVSNICK."
-msgstr ""
-
-msgid "Your IRCd does not support SVSPART."
-msgstr ""
-
-msgid ""
-"Your IRCd does not support vIdent's, if this is incorrect, please report "
-"this as a possible bug"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Your account %s has been successfully created."
-msgstr "El bot %s ha estat esborrat."
-
-#, fuzzy
-msgid "Your account is already confirmed."
-msgstr "You are already identified."
-
-#, fuzzy, c-format
-msgid "Your account will expire, if not confirmed, in %s."
-msgstr "You are already identified."
-
-#, fuzzy, c-format
-msgid "Your email address has been changed to %s."
-msgstr "E-mail address for %s changed to %s."
-
-#, fuzzy
-msgid "Your email address is not allowed, choose a different one."
-msgstr "Totes les linees O de %s han estat esborrades."
-
-msgid ""
-"Your email address is not confirmed. To confirm it, follow the instructions "
-"that were emailed to you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Your email address of %s has been confirmed."
-msgstr "Totes les linees O de %s han estat esborrades."
-
-#, fuzzy, c-format
-msgid "Your email has been updated to %s"
-msgstr "E-mail address for %s changed to %s."
-
-#, fuzzy, c-format
-msgid "Your email has been updated to %s."
-msgstr "E-mail address for %s changed to %s."
-
-msgid "Your memo limit has been disabled."
-msgstr "El teu límit de memos ha estat deshabilitat."
-
-#, c-format
-msgid "Your memo limit has been set to %d."
-msgstr "El teu límite de memos ha estat establert a %d."
-
-#, c-format
-msgid "Your memo limit is %d, and may not be changed."
-msgstr "El teu límit de memos es %d i no pot ser canviat."
-
-#, c-format
-msgid "Your memo limit is %d."
-msgstr "El teu límit de memos es %d."
-
-msgid "Your memo limit is 0; you will not receive any new memos."
-msgstr "El teu límit de memos es 0; no rebràs nous memos."
-
-#, fuzzy
-msgid ""
-"Your memo limit is 0; you will not receive any new memos. You cannot change "
-"this limit."
-msgstr ""
-"El teu límit de memos es 0; no rebràs nous memos. No pots cambiar aquest "
-"límit."
-
-msgid "Your nick has been logged out."
-msgstr "El teu nick ha estat desconnectat."
-
-#, fuzzy
-msgid "Your nick is already registered."
-msgstr "El teu nick ja esta registrat; escriu /msg %s DROP primer."
-
-msgid "Your nick is not grouped to anything, you can't ungroup it."
-msgstr "Your nick is not grouped to anything, you can't ungroup it."
-
-#, fuzzy
-msgid "Your nick isn't registered."
-msgstr "Nickname %s registered."
-
-#, c-format
-msgid "Your nickname is now being changed to %s"
-msgstr "El teu nickname s'esta canviant a %s"
-
-msgid "Your oper block doesn't require logging in."
-msgstr ""
-
-#, c-format
-msgid "Your passcode has been re-sent to %s."
-msgstr "Your passcode has been re-sent to %s."
-
-#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "La teva clau es %s - Recordala per un us futur."
-
-#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr ""
-
-msgid "Your password reset request has expired."
-msgstr "Your password reset request has expired."
-
-#, fuzzy
-msgid "Your vHost has been requested."
-msgstr "El bot %s ha estat esborrat."
-
-#, c-format
-msgid "Your vhost of %s is now activated."
-msgstr "Your vhost of %s is now activated."
-
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "Your vhost of %s@%s is now activated."
-
-msgid "Your vhost was removed and the normal cloaking restored."
-msgstr "Your vhost was removed and the normal cloaking restored."
-
-#, fuzzy
-msgid "Zone"
-msgstr "Cap"
-
-#, fuzzy, c-format
-msgid "Zone %s already exists."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy, c-format
-msgid "Zone %s does not exist."
-msgstr "El bot %s ja existeix."
-
-#, fuzzy, c-format
-msgid "Zone %s removed."
-msgstr "vhost for %s removed."
-
-#, fuzzy
-msgid "[1|2|3|4|5]"
-msgstr "DEFCON [1|2|3|4|5]"
-
-#, c-format
-msgid "[Logon News - %s] %s"
-msgstr "[Notícies de Logon - %s] %s"
-
-#, c-format
-msgid "[Oper News - %s] %s"
-msgstr "[Notícies de Oper - %s] %s"
-
-#, c-format
-msgid "[Random News - %s] %s"
-msgstr "[Notícies al Atzar - %s] %s"
-
-#, fuzzy
-msgid "[account] password"
-msgstr "IDENTIFY clau"
-
-#, fuzzy
-msgid "[channel [nick]]"
-msgstr "OP #channel [nick]"
-
-#, fuzzy
-msgid "[channel] ADD entry"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | instància]"
-
-#, fuzzy
-msgid "[channel] DEL entry"
-msgstr "MODE canal Modes"
-
-#, fuzzy
-msgid "[channel] LIST"
-msgstr "DROP canal"
-
-#, fuzzy
-msgid "[channel] [list | NEW]"
-msgstr "LIST [canal] [llista | NEW]"
-
-#, fuzzy
-msgid "[channel] [nick]"
-msgstr "OP #channel [nick]"
-
-#, fuzzy
-msgid "[channel] {num | list | LAST | ALL}"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-#, fuzzy
-msgid "[channel] {num | list | LAST | NEW | ALL}"
-msgstr "DEL [canal] {numero | llista | ALL}"
-
-msgid "[key|#X-Y]"
-msgstr ""
-
-#, fuzzy
-msgid "[nick | channel]"
-msgstr "CANCEL {nick | canal}"
-
-#, fuzzy
-msgid "[nick]"
-msgstr "INFO nick"
-
-msgid "[nickname [REVALIDATE]]"
-msgstr ""
-
-#, fuzzy
-msgid "[nickname]"
-msgstr "CHECK nickname"
-
-msgid "[parameter]"
-msgstr ""
-
-msgid "[+daysd] [+limitl] pattern"
-msgstr ""
-
-#, fuzzy
-msgid "[+expiry] channel reason"
-msgstr "CHANKILL [+expiry] {#channel} [reason]"
-
-msgid "[Hostname hidden]"
-msgstr ""
-
-msgid "[Suspended]"
-msgstr ""
-
-msgid "[Unconfirmed]"
-msgstr ""
-
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been approved."
-msgstr "[auto-memo] The memo you sent to %s has been viewed."
-
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been rejected."
-msgstr "[auto-memo] The memo you sent to %s has been viewed."
-
-#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "Ultim memo enviat a %s va ser cancel.lat."
-
-msgid "[{pattern | channel} [INVISIBLE]]"
-msgstr ""
-
-msgid "[{pattern | nick} [SECRET]]"
-msgstr ""
-
-msgid "day"
-msgstr ""
-
-msgid "days"
-msgstr ""
-
-#, fuzzy
-msgid "does not expire"
-msgstr " %s (does not expire)"
-
-#, c-format
-msgid "expires in %d day"
-msgstr "expira en %d dia"
-
-#, c-format
-msgid "expires in %d days"
-msgstr "expira en %d dies"
-
-#, c-format
-msgid "expires in %d hour, %d minute"
-msgstr "expira en %d hora, %d minut"
-
-#, c-format
-msgid "expires in %d hour, %d minutes"
-msgstr "expira en %d hora, %d minuts"
-
-#, c-format
-msgid "expires in %d hours, %d minute"
-msgstr "expira en %d hores, %d minut"
-
-#, c-format
-msgid "expires in %d hours, %d minutes"
-msgstr "expira en %d hores, %d minuts"
-
-#, c-format
-msgid "expires in %d minute"
-msgstr "expira en %d minuts"
-
-#, c-format
-msgid "expires in %d minutes"
-msgstr "expira en %d minuts"
-
-#, fuzzy
-msgid "expires momentarily"
-msgstr "expira en %d dia"
-
-msgid "hour"
-msgstr ""
-
-msgid "hours"
-msgstr ""
-
-#, c-format
-msgid "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
-
-msgid "minute"
-msgstr ""
-
-msgid "minutes"
-msgstr ""
-
-msgid "not assigned yet"
-msgstr ""
-
-msgid "second"
-msgstr ""
-
-#, fuzzy
-msgid "seconds"
-msgstr "%s commands:"
-
-#, fuzzy, c-format
-msgid "vHost for %s has been activated."
-msgstr "Your vhost of %s is now activated."
-
-#, fuzzy, c-format
-msgid "vHost for %s has been rejected."
-msgstr "El bot %s ha estat esborrat."
-
-msgid "vhost"
-msgstr ""
-
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "vhosts for group %s have been removed."
-
-msgid "year"
-msgstr ""
-
-msgid "years"
-msgstr ""
-
-msgid "{MODIFY|VIEW} [block name item name item value]"
-msgstr ""
-
-#, fuzzy
-msgid "{channel | nickname}"
-msgstr "UNBAN canal [nick]"
-
-#, fuzzy
-msgid "{nick | channel}"
-msgstr "CANCEL {nick | canal}"
-
-#, fuzzy
-msgid "{nick | channel} memo-text"
-msgstr "SEND {nick | canal} text"
diff --git a/language/anope.de_DE.po b/language/anope.de_DE.po
index e814a2bbf..b43789f12 100644
--- a/language/anope.de_DE.po
+++ b/language/anope.de_DE.po
@@ -3778,7 +3778,7 @@ msgstr ""
"angezeigt. (Es werden jedoch nur max. %d angezeigt, um ein\n"
"Flooding des Users zu verhindern. Wenn mehr News\n"
"existieren, werden nur die neuesten angezeigt.)\n"
-"NewsCount kann in der services.conf eingestellt werden.\n"
+"NewsCount kann in der anope.conf eingestellt werden.\n"
"\n"
"Diese Funktion ist beschränkt auf Services Operatoren."
@@ -3796,7 +3796,7 @@ msgstr ""
"(Es werden jedoch nur max. %d Nachrichten angezeigt, um ein\n"
"Flooding des Users zu verhindern. Wenn mehr News\n"
"existieren, werden nur die neüsten angezeigt.)\n"
-"NewsCount can be configured in services.conf.\n"
+"NewsCount can be configured in anope.conf.\n"
"\n"
"Diese Funktion ist beschränkt auf Services Operatoren."
@@ -7365,7 +7365,7 @@ msgstr "Der Eintrag des Vertreters für %s wurde entfernt."
#, fuzzy
msgid "Super admin can not be set because it is not enabled in the configuration."
-msgstr "SuperAdmin muss in der services.conf eingeschaltet werden."
+msgstr "SuperAdmin muss in der anope.conf eingeschaltet werden."
#, fuzzy
msgid "Suspend a given nick"
diff --git a/language/anope.el_GR.po b/language/anope.el_GR.po
index f6f1338bd..d207cfa35 100644
--- a/language/anope.el_GR.po
+++ b/language/anope.el_GR.po
@@ -4012,7 +4012,7 @@ msgstr ""
"(Παρόλα αυτά, δεν θα του στέλνονται παραπάνω από #%d# μηνύματα\n"
"για να αποφευχθεί το flood του χρήστη. Αν υπάρχουν\n"
"περισσότερα μηνύματα, θα φαίνονται τα πιο πρόσφατα.)\n"
-"Το NewsCount μπορεί να ρυθμιστεί στο services.conf.\n"
+"Το NewsCount μπορεί να ρυθμιστεί στο anope.conf.\n"
"\n"
"Η εντολή LOGONNEWS μπορεί να χρησιμοποιηθεί μόνο από IRC Operators."
@@ -4034,7 +4034,7 @@ msgstr ""
"μηνύματα\n"
"για να αποφευχθεί flood στον χρήστη. Αν υπάρχουν \n"
"περισσότερα μηνύματα, θα φαίνονται τα πιο πρόσφατα.)\n"
-"Το NewsCount μπορεί να ρυθμιστεί στο services.conf.\n"
+"Το NewsCount μπορεί να ρυθμιστεί στο anope.conf.\n"
" \n"
"Το OPERNEWS μπορεί να χρησιμοποιηθεί μόνο από Services Operators."
@@ -7580,7 +7580,7 @@ msgstr "Ο Successor του #%s# δεν έχει οριστεί."
#, fuzzy
msgid ""
"Super admin can not be set because it is not enabled in the configuration."
-msgstr "H ρύθμιση SuperAdmin δεν έχει ενεργοποιηθεί στο services.conf"
+msgstr "H ρύθμιση SuperAdmin δεν έχει ενεργοποιηθεί στο anope.conf"
#
msgid "Suspend a given nick"
diff --git a/language/anope.en_US.po b/language/anope.en_US.po
index 739ce2c37..6141bd51c 100644
--- a/language/anope.en_US.po
+++ b/language/anope.en_US.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-12-17 19:24+0000\n"
-"PO-Revision-Date: 2023-12-17 19:27+0000\n"
+"POT-Creation-Date: 2025-02-14 14:57+0000\n"
+"PO-Revision-Date: 2024-11-25 01:32+0000\n"
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
"Language-Team: English\n"
"Language: en_US\n"
@@ -16,55 +16,53 @@ msgstr ""
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 3.4\n"
+"X-Generator: Poedit 3.4.2\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
-msgstr "%d channel(s) cleared, and %d channel(s) dropped."
+msgstr ""
#, c-format
-msgid "%d nickname(s) dropped."
-msgstr "%d nickname(s) dropped."
+msgid "%d nickname dropped."
+msgid_plural "%d nicknames dropped."
+msgstr[0] ""
+msgstr[1] ""
#, c-format
msgid "%s added to %s %s list."
-msgstr "%s added to %s %s list."
+msgstr ""
#, c-format
msgid "%s added to %s access list at level %d."
-msgstr "%s added to %s access list at level %d."
+msgstr ""
#, c-format
msgid "%s added to %s access list at privilege %s (level %d)"
-msgstr "%s added to %s access list at privilege %s (level %d)"
+msgstr ""
#, c-format
msgid "%s added to %s autokick list."
-msgstr "%s added to %s autokick list."
+msgstr ""
#, c-format
msgid "%s added to %s bad words list."
-msgstr "%s added to %s bad words list."
-
-#, c-format
-msgid "%s added to %s's access list."
-msgstr "%s added to %s's access list."
+msgstr ""
#, c-format
msgid "%s added to %s's certificate list."
-msgstr "%s added to %s's certificate list."
+msgstr ""
#, c-format
msgid "%s added to ignore list."
-msgstr "%s added to ignore list."
+msgstr ""
#, c-format
msgid "%s added to the %s list."
-msgstr "%s added to the %s list."
+msgstr ""
#, c-format
msgid "%s added to the AKILL list."
-msgstr "%s added to the AKILL list."
+msgstr ""
#, c-format
msgid ""
@@ -74,11 +72,6 @@ msgid ""
"require a channel as a parameter will automatically have that parameter\n"
"given.\n"
msgstr ""
-"%s allows you to execute \"fantasy\" commands in the channel.\n"
-"Fantasy commands are commands that can be executed from messaging a\n"
-"channel, and provide a more convenient way to execute commands. Commands that\n"
-"require a channel as a parameter will automatically have that parameter\n"
-"given.\n"
#, c-format
msgid ""
@@ -86,47 +79,29 @@ msgid ""
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
+"below; to use them, type %s command. For\n"
"more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
-"%s allows you to have a bot on your own channel.\n"
-"It has been created for users that can't host or\n"
-"configure a bot, or for use on networks that don't\n"
-"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
-"more information on a specific command, type\n"
-"%s%s %s command.\n"
#, c-format
msgid ""
"%s allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
+"nicknames; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
-"%s allows you to register a nickname and\n"
-"prevent others from using it. The following\n"
-"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
#, c-format
msgid ""
"%s allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
+"accounts; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
-"%s allows you to register an account.\n"
-"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
#, c-format
msgid ""
@@ -135,112 +110,105 @@ msgid ""
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
+"%s command. For more information on a\n"
+"specific command, type %s HELP command.\n"
msgstr ""
-"%s allows you to register and control various\n"
-"aspects of channels. %s can often prevent\n"
-"malicious users from \"taking over\" channels by limiting\n"
-"who is allowed channel operator privileges. Available\n"
-"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
#, c-format
msgid "%s already exists in %s bad words list."
-msgstr "%s already exists in %s bad words list."
+msgstr ""
#, c-format
msgid "%s already exists on %s autokick list."
-msgstr "%s already exists on %s autokick list."
+msgstr ""
#, c-format
msgid "%s already exists on the EXCEPTION list."
-msgstr "%s already exists on the EXCEPTION list."
+msgstr ""
#, c-format
msgid "%s cannot be taken as times to ban."
-msgstr "%s cannot be taken as times to ban."
+msgstr ""
#, c-format
msgid "%s changed your usermodes to %s."
-msgstr "%s changed your usermodes to %s."
+msgstr ""
#, c-format
msgid "%s channel list:"
-msgstr "%s channel list:"
+msgstr ""
#, c-format
msgid "%s deleted from %s %s list."
-msgstr "%s deleted from %s %s list."
+msgstr ""
#, c-format
msgid "%s deleted from %s access list."
-msgstr "%s deleted from %s access list."
+msgstr ""
#, c-format
msgid "%s deleted from %s autokick list."
-msgstr "%s deleted from %s autokick list."
+msgstr ""
#, c-format
msgid "%s deleted from %s bad words list."
-msgstr "%s deleted from %s bad words list."
-
-#, c-format
-msgid "%s deleted from %s's access list."
-msgstr "%s deleted from %s's access list."
+msgstr ""
#, c-format
msgid "%s deleted from %s's certificate list."
-msgstr "%s deleted from %s's certificate list."
+msgstr ""
#, c-format
msgid "%s deleted from session-limit exception list."
-msgstr "%s deleted from session-limit exception list."
+msgstr ""
#, c-format
msgid "%s deleted from the %s list."
-msgstr "%s deleted from the %s list."
+msgstr ""
#, c-format
msgid "%s deleted from the AKILL list."
-msgstr "%s deleted from the AKILL list."
+msgstr ""
#, c-format
msgid "%s disabled on channel %s."
-msgstr "%s disabled on channel %s."
+msgstr ""
+
+#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr ""
#, c-format
msgid "%s has been invited to %s."
-msgstr "%s has been invited to %s."
+msgstr ""
#, c-format
msgid "%s has been joined to %s."
-msgstr "%s has been joined to %s."
+msgstr ""
#, c-format
msgid "%s has been parted from %s."
-msgstr "%s has been parted from %s."
+msgstr ""
#, c-format
msgid "%s has been unbanned from %s."
-msgstr "%s has been unbanned from %s."
+msgstr ""
#, c-format
msgid "%s has no access in any channels."
-msgstr "%s has no access in any channels."
+msgstr ""
#, c-format
msgid "%s has no access on %s."
-msgstr "%s has no access on %s."
+msgstr ""
#, c-format
msgid "%s has too many channels registered."
-msgstr "%s has too many channels registered."
+msgstr ""
#, c-format
msgid "%s is a super administrator."
-msgstr "%s is a super administrator."
+msgstr ""
#, c-format
msgid ""
@@ -251,161 +219,151 @@ msgid ""
"registered in order to send a memo.\n"
"%s's commands include:"
msgstr ""
-"%s is a utility allowing IRC users to send short\n"
-"messages to other IRC users, whether they are online at\n"
-"the time or not, or to channels(*). Both the sender's\n"
-"nickname and the target nickname or channel must be\n"
-"registered in order to send a memo.\n"
-"%s's commands include:"
#, c-format
msgid "%s is already in %s!"
-msgstr "%s is already in %s!"
+msgstr ""
#, c-format
msgid "%s is already in %s."
-msgstr "%s is already in %s."
+msgstr ""
#, c-format
msgid "%s is already on the ignore list."
-msgstr "%s is already on the ignore list."
+msgstr ""
#, c-format
msgid "%s is already suspended."
-msgstr "%s is already suspended."
+msgstr ""
#, c-format
msgid "%s is not a registered unforbidden nick or channel."
-msgstr "%s is not a registered unforbidden nick or channel."
+msgstr ""
#, c-format
msgid "%s is not a valid ban type."
-msgstr "%s is not a valid ban type."
+msgstr ""
#, c-format
msgid "%s is not a valid bot or registered channel."
-msgstr "%s is not a valid bot or registered channel."
+msgstr ""
#, c-format
-msgid "%s is not a valid e-mail address."
-msgstr "%s is not a valid e-mail address."
+msgid "%s is not a valid email address."
+msgstr ""
#, c-format
msgid "%s is not currently on channel %s."
-msgstr "%s is not currently on channel %s."
+msgstr ""
#, c-format
msgid "%s is not in %s."
-msgstr "%s is not in %s."
+msgstr ""
#, c-format
msgid "%s is not on the ignore list."
-msgstr "%s is not on the ignore list."
+msgstr ""
#, c-format
msgid "%s is on the auto kick list of %s (%s)."
-msgstr "%s is on the auto kick list of %s (%s)."
+msgstr ""
#, c-format
msgid "%s is the founder of %s."
-msgstr "%s is the founder of %s."
+msgstr ""
#, c-format
msgid "%s matches access entry %s (from entry %s), which has privilege %s."
-msgstr "%s matches access entry %s (from entry %s), which has privilege %s."
+msgstr ""
#, c-format
msgid "%s matches access entry %s, which has privilege %s."
-msgstr "%s matches access entry %s, which has privilege %s."
+msgstr ""
#, c-format
msgid "%s matches an except on %s and cannot be banned until the except has been removed."
-msgstr "%s matches an except on %s and cannot be banned until the except has been removed."
+msgstr ""
#, c-format
msgid "%s matches auto kick entry %s on %s (%s)."
-msgstr "%s matches auto kick entry %s on %s (%s)."
+msgstr ""
#, c-format
msgid "%s not found on %s %s list."
-msgstr "%s not found on %s %s list."
+msgstr ""
#, c-format
msgid "%s not found on %s access list."
-msgstr "%s not found on %s access list."
+msgstr ""
#, c-format
msgid "%s not found on %s autokick list."
-msgstr "%s not found on %s autokick list."
+msgstr ""
#, c-format
msgid "%s not found on %s bad words list."
-msgstr "%s not found on %s bad words list."
-
-#, c-format
-msgid "%s not found on %s's access list."
-msgstr "%s not found on %s's access list."
+msgstr ""
#, c-format
msgid "%s not found on %s's certificate list."
-msgstr "%s not found on %s's certificate list."
+msgstr ""
#, c-format
msgid "%s not found on ignore list."
-msgstr "%s not found on ignore list."
+msgstr ""
#, c-format
msgid "%s not found on session list, but has a limit of %d because it matches entry: %s."
-msgstr "%s not found on session list, but has a limit of %d because it matches entry: %s."
+msgstr ""
#, c-format
msgid "%s not found on session-limit exception list."
-msgstr "%s not found on session-limit exception list."
+msgstr ""
#, c-format
msgid "%s not found on the %s list."
-msgstr "%s not found on the %s list."
+msgstr ""
#, c-format
msgid "%s not found on the AKILL list."
-msgstr "%s not found on the AKILL list."
+msgstr ""
#, c-format
msgid "%s removed from the %s access list."
-msgstr "%s removed from the %s access list."
+msgstr ""
#, c-format
msgid "%s removed from the ignore list."
-msgstr "%s removed from the ignore list."
+msgstr ""
#, c-format
msgid "%s users list:"
-msgstr "%s users list:"
+msgstr ""
#, c-format
msgid "%s will no longer be ignored."
-msgstr "%s will no longer be ignored."
+msgstr ""
#, c-format
msgid "%s will now be ignored for %s."
-msgstr "%s will now be ignored for %s."
+msgstr ""
#, c-format
msgid "%s will now permanently be ignored."
-msgstr "%s will now permanently be ignored."
+msgstr ""
#, c-format
-msgid "%s%s HELP %s for more information."
-msgstr "%s%s HELP %s for more information."
+msgid "%s HELP %s for more information."
+msgstr ""
msgid "ADD nick user host real"
-msgstr "ADD nick user host real"
+msgstr ""
msgid "CHANGE oldnick newnick [user [host [real]]]"
-msgstr "CHANGE oldnick newnick [user [host [real]]]"
+msgstr ""
msgid "DEL nick"
-msgstr "DEL nick"
+msgstr ""
msgid ""
"EXCEPTION ADD adds the given host mask to the exception list.\n"
@@ -430,27 +388,6 @@ msgid ""
"Note that a connecting client will \"use\" the first exception\n"
"their host matches."
msgstr ""
-"EXCEPTION ADD adds the given host mask to the exception list.\n"
-"Note that nick!user@host and user@host masks are invalid!\n"
-"Only real host masks, such as box.host.dom and *.host.dom,\n"
-"are allowed because sessions limiting does not take nick or\n"
-"user names into account. limit must be a number greater than\n"
-"or equal to zero. This determines how many sessions this host\n"
-"may carry at a time. A value of zero means the host has an\n"
-"unlimited session limit. See the AKILL help for details about\n"
-"the format of the optional expiry parameter.\n"
-" \n"
-"EXCEPTION DEL removes the given mask from the exception list.\n"
-" \n"
-"EXCEPTION LIST and EXCEPTION VIEW show all current\n"
-"sessions if the optional mask is given, the list is limited\n"
-"to those sessions matching the mask. The difference is that\n"
-"EXCEPTION VIEW is more verbose, displaying the name of the\n"
-"person who added the exception, its session limit, reason,\n"
-"host mask and the expiry date and time.\n"
-" \n"
-"Note that a connecting client will \"use\" the first exception\n"
-"their host matches."
msgid ""
"SET kills all operators from the given\n"
@@ -458,321 +395,323 @@ msgid ""
"up on the given server. REVOKE removes this\n"
"restriction."
msgstr ""
-"SET kills all operators from the given\n"
-"server and prevents operators from opering\n"
-"up on the given server. REVOKE removes this\n"
-"restriction."
#, c-format
msgid ""
"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
+"%s command; type %s HELP LEVELS for\n"
"information."
msgstr ""
-"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
-"information."
#, c-format
msgid "[auto-memo] The memo you sent to %s has been viewed."
-msgstr "[auto-memo] The memo you sent to %s has been viewed."
+msgstr ""
msgid "[target] [password]"
-msgstr "[target] [password]"
+msgstr ""
msgid "address"
-msgstr "address"
+msgstr ""
msgid "botname {ON|OFF}"
-msgstr "botname {ON|OFF}"
+msgstr ""
msgid "channel"
-msgstr "channel"
+msgstr ""
msgid "channel bantype"
-msgstr "channel bantype"
-
-msgid "channel channel"
-msgstr "channel channel"
+msgstr ""
msgid "channel command method [status]"
-msgstr "channel command method [status]"
+msgstr ""
msgid "channel mask [reason]"
-msgstr "channel mask [reason]"
+msgstr ""
msgid "channel modes"
-msgstr "channel modes"
+msgstr ""
msgid "channel nick"
-msgstr "channel nick"
+msgstr ""
msgid "channel nick [reason]"
-msgstr "channel nick [reason]"
+msgstr ""
msgid "channel target [what]"
-msgstr "channel target [what]"
+msgstr ""
msgid "channel text"
-msgstr "channel text"
+msgstr ""
msgid "channel time"
-msgstr "channel time"
+msgstr ""
msgid "channel user reason"
-msgstr "channel user reason"
+msgstr ""
msgid "channel what"
-msgstr "channel what"
+msgstr ""
-msgid "channel ADD mask"
-msgstr "channel ADD mask"
+msgid "channel ADD mask level [description]"
+msgstr ""
-msgid "channel ADD mask level"
-msgstr "channel ADD mask level"
+msgid "channel ADD mask [description]"
+msgstr ""
msgid "channel ADD message"
-msgstr "channel ADD message"
+msgstr ""
msgid "channel ADD word [SINGLE | START | END]"
-msgstr "channel ADD word [SINGLE | START | END]"
+msgstr ""
msgid "channel ADD {nick | mask} [reason]"
-msgstr "channel ADD {nick | mask} [reason]"
+msgstr ""
msgid "channel APPEND topic"
-msgstr "channel APPEND topic"
+msgstr ""
msgid "channel CLEAR"
-msgstr "channel CLEAR"
+msgstr ""
msgid "channel CLEAR [what]"
-msgstr "channel CLEAR [what]"
+msgstr ""
msgid "channel CLEAR [ALL]"
-msgstr "channel CLEAR [ALL]"
+msgstr ""
msgid "channel DEL num"
-msgstr "channel DEL num"
+msgstr ""
msgid "channel DEL {mask | entry-num | list}"
-msgstr "channel DEL {mask | entry-num | list}"
+msgstr ""
msgid "channel DEL {nick | mask | entry-num | list}"
-msgstr "channel DEL {nick | mask | entry-num | list}"
+msgstr ""
msgid "channel DEL {word | entry-num | list}"
-msgstr "channel DEL {word | entry-num | list}"
+msgstr ""
msgid "channel ENFORCE"
-msgstr "channel ENFORCE"
+msgstr ""
msgid "channel LIST"
-msgstr "channel LIST"
+msgstr ""
msgid "channel LIST [mask | entry-num | list]"
-msgstr "channel LIST [mask | entry-num | list]"
+msgstr ""
msgid "channel LIST [mask | list]"
-msgstr "channel LIST [mask | list]"
+msgstr ""
msgid "channel LIST [mask | +flags]"
-msgstr "channel LIST [mask | +flags]"
+msgstr ""
msgid "channel LOCK {ADD|DEL|SET|LIST} [what]"
-msgstr "channel LOCK {ADD|DEL|SET|LIST} [what]"
+msgstr ""
msgid "channel RESET"
-msgstr "channel RESET"
+msgstr ""
msgid "channel SET modes"
-msgstr "channel SET modes"
+msgstr ""
msgid "channel SET type level"
-msgstr "channel SET type level"
+msgstr ""
msgid "channel VIEW [mask | entry-num | list]"
-msgstr "channel VIEW [mask | entry-num | list]"
+msgstr ""
msgid "channel VIEW [mask | list]"
-msgstr "channel VIEW [mask | list]"
+msgstr ""
+
+msgid "channel [code]"
+msgstr ""
msgid "channel [description]"
-msgstr "channel [description]"
+msgstr ""
msgid "channel [nick]"
-msgstr "channel [nick]"
+msgstr ""
msgid "channel [parameters]"
-msgstr "channel [parameters]"
+msgstr ""
msgid "channel [user]"
-msgstr "channel [user]"
+msgstr ""
+
+msgid "channel [user]+"
+msgstr ""
msgid "channel [+expiry] [reason]"
-msgstr "channel [+expiry] [reason]"
+msgstr ""
msgid "channel [+expiry] {nick | mask} [reason]"
-msgstr "channel [+expiry] {nick | mask} [reason]"
+msgstr ""
-msgid "channel [MODIFY] mask changes"
-msgstr "channel [MODIFY] mask changes"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr ""
msgid "channel [SET] [topic]"
-msgstr "channel [SET] [topic]"
+msgstr ""
msgid "channel [UNLOCK|LOCK]"
-msgstr "channel [UNLOCK|LOCK]"
+msgstr ""
msgid "channel {ON|OFF}"
-msgstr "channel {ON|OFF}"
+msgstr ""
msgid "channel {ON|OFF} [ttb [ln [secs]]]"
-msgstr "channel {ON|OFF} [ttb [ln [secs]]]"
+msgstr ""
msgid "channel {ON|OFF} [ttb [min [percent]]]"
-msgstr "channel {ON|OFF} [ttb [min [percent]]]"
+msgstr ""
msgid "channel {ON|OFF} [ttb [num]]"
-msgstr "channel {ON|OFF} [ttb [num]]"
+msgstr ""
msgid "channel {ON|OFF} [ttb]"
-msgstr "channel {ON|OFF} [ttb]"
+msgstr ""
msgid "channel {DIS | DISABLE} type"
-msgstr "channel {DIS | DISABLE} type"
+msgstr ""
msgid "channel {ON | LEVEL | OFF}"
-msgstr "channel {ON | LEVEL | OFF}"
+msgstr ""
msgid "channel {ON | OFF}"
-msgstr "channel {ON | OFF}"
+msgstr ""
msgid "email"
-msgstr "email"
+msgstr ""
msgid "language"
-msgstr "language"
+msgstr ""
msgid "memo-text"
-msgstr "memo-text"
+msgstr ""
msgid "message"
-msgstr "message"
+msgstr ""
msgid "modname"
-msgstr "modname"
+msgstr ""
+
+msgid "network-name"
+msgstr ""
msgid "new-display"
-msgstr "new-display"
+msgstr ""
msgid "new-password"
-msgstr "new-password"
+msgstr ""
msgid "nick"
-msgstr "nick"
+msgstr ""
msgid "nick channel"
-msgstr "nick channel"
+msgstr ""
msgid "nick channel [reason]"
-msgstr "nick channel [reason]"
-
-msgid "nick flags"
-msgstr "nick flags"
+msgstr ""
msgid "nick hostmask"
-msgstr "nick hostmask"
+msgstr ""
msgid "nick newnick"
-msgstr "nick newnick"
+msgstr ""
msgid "nick [reason]"
-msgstr "nick [reason]"
+msgstr ""
msgid "nickname"
-msgstr "nickname"
+msgstr ""
msgid "nickname address"
-msgstr "nickname address"
+msgstr ""
msgid "nickname email"
-msgstr "nickname email"
+msgstr ""
msgid "nickname language"
-msgstr "nickname language"
+msgstr ""
msgid "nickname message"
-msgstr "nickname message"
+msgstr ""
msgid "nickname new-display"
-msgstr "nickname new-display"
+msgstr ""
msgid "nickname new-password"
-msgstr "nickname new-password"
+msgstr ""
+
+msgid "nickname [code]"
+msgstr ""
msgid "nickname [parameter]"
-msgstr "nickname [parameter]"
+msgstr ""
msgid "nickname [password]"
-msgstr "nickname [password]"
+msgstr ""
msgid "nickname [+expiry] [reason]"
-msgstr "nickname [+expiry] [reason]"
+msgstr ""
msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-msgstr "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
+msgstr ""
msgid "nickname {ON | OFF}"
-msgstr "nickname {ON | OFF}"
+msgstr ""
msgid "nickname {ON | QUICK | IMMED | OFF}"
-msgstr "nickname {ON | QUICK | IMMED | OFF}"
+msgstr ""
msgid "option (channel | bot) settings"
-msgstr "option (channel | bot) settings"
+msgstr ""
msgid "option channel parameters"
-msgstr "option channel parameters"
+msgstr ""
msgid "option channel {ON|OFF} [settings]"
-msgstr "option channel {ON|OFF} [settings]"
+msgstr ""
msgid "option nickname parameters"
-msgstr "option nickname parameters"
+msgstr ""
msgid "option parameters"
-msgstr "option parameters"
+msgstr ""
msgid "option setting"
-msgstr "option setting"
+msgstr ""
msgid "passcode"
-msgstr "passcode"
+msgstr ""
msgid "password"
-msgstr "password"
+msgstr ""
msgid "password [email]"
-msgstr "password [email]"
+msgstr ""
msgid "password email"
-msgstr "password email"
+msgstr ""
msgid "pattern [SUSPENDED] [NOEXPIRE]"
-msgstr "pattern [SUSPENDED] [NOEXPIRE]"
+msgstr ""
msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-msgstr "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
+msgstr ""
+
+msgid "server [message]"
+msgstr ""
msgid "server [reason]"
-msgstr "server [reason]"
+msgstr ""
msgid "user modes"
-msgstr "user modes"
+msgstr ""
msgid "user [reason]"
-msgstr "user [reason]"
+msgstr ""
msgid ""
" \n"
@@ -791,21 +730,6 @@ msgid ""
"Note: because the realname mask may contain spaces, the\n"
"separator between it and the reason is a colon."
msgstr ""
-" \n"
-"SNLINE ADD adds the given realname mask to the SNLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SNLINE which does not expire, use +0. If the\n"
-"realname mask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current SNLINE default expiry time can be found with the\n"
-"STATS AKILL command.\n"
-" \n"
-"Note: because the realname mask may contain spaces, the\n"
-"separator between it and the reason is a colon."
msgid ""
" \n"
@@ -821,37 +745,19 @@ msgid ""
"current SQLINE default expiry time can be found with the\n"
"STATS AKILL command."
msgstr ""
-" \n"
-"SQLINE ADD adds the given (nick/channel) mask to the SQLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SQLINE which does not expire, use +0.\n"
-"If the mask to be added starts with a +, an expiry time\n"
-"must be given, even if it is the same as the default. The\n"
-"current SQLINE default expiry time can be found with the\n"
-"STATS AKILL command."
#, c-format
msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
-" \n"
-"Accounts that are not used anymore are subject to\n"
-"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
msgid ""
" \n"
"Available commands are:"
msgstr ""
-" \n"
-"Available commands are:"
#, c-format
msgid ""
@@ -859,9 +765,6 @@ msgid ""
"Bot will join a channel whenever there is at least\n"
"%d user(s) on it."
msgstr ""
-" \n"
-"Bot will join a channel whenever there is at least\n"
-"%d user(s) on it."
#, c-format
msgid ""
@@ -871,19 +774,10 @@ msgid ""
"fantasy commands on a channel when prefixed\n"
"with one of the following fantasy characters: %s\n"
" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
+"Note that users wanting to use fantasy commands\n"
+"MUST have enough access for both the FANTASY\n"
+"privilege and the command they are executing."
msgstr ""
-" \n"
-"Enables or disables fantasy mode on a channel.\n"
-"When it is enabled, users will be able to use\n"
-"fantasy commands on a channel when prefixed\n"
-"with one of the following fantasy characters: %s\n"
-" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
msgid ""
" \n"
@@ -892,11 +786,6 @@ msgid ""
"messages of users joining the channel, provided\n"
"they have enough access to the channel."
msgstr ""
-" \n"
-"Enables or disables greet mode on a channel.\n"
-"When it is enabled, the bot will display greet\n"
-"messages of users joining the channel, provided\n"
-"they have enough access to the channel."
msgid ""
" \n"
@@ -904,10 +793,6 @@ msgid ""
"When it is enabled, ops won't be kicked by the bot\n"
"even if they don't match the NOKICK level."
msgstr ""
-" \n"
-"Enables or disables ops protection mode on a channel.\n"
-"When it is enabled, ops won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
msgid ""
" \n"
@@ -915,51 +800,34 @@ msgid ""
"When it is enabled, voices won't be kicked by the bot\n"
"even if they don't match the NOKICK level."
msgstr ""
-" \n"
-"Enables or disables voices protection mode on a channel.\n"
-"When it is enabled, voices won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
#, c-format
msgid ""
" \n"
"Fantasy commands may be prefixed with one of the following characters: %s\n"
msgstr ""
-" \n"
-"Fantasy commands may be prefixed with one of the following characters: %s\n"
msgid ""
" \n"
"NOTICE: In order to register a channel, you must have\n"
"first registered your nickname."
msgstr ""
-" \n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname."
#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
-" \n"
-"Note that any channel which is not used for %d days\n"
-"(i.e. which no user on the channel's access list enters\n"
-"for that period of time) will be automatically dropped."
#, c-format
msgid ""
" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
+"See the %s command (%s HELP ACCESS) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"
msgstr ""
-" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
msgid ""
" \n"
@@ -967,10 +835,6 @@ msgid ""
"to identify for the nick, and may view the access list for\n"
"any nickname."
msgstr ""
-" \n"
-"Services Operators can also drop any nickname without needing\n"
-"to identify for the nick, and may view the access list for\n"
-"any nickname."
msgid ""
" \n"
@@ -978,10 +842,6 @@ msgid ""
"any channel, view (and modify) the access, levels and akick\n"
"lists and settings for any channel."
msgstr ""
-" \n"
-"Services Operators can also, depending on their access drop\n"
-"any channel, view (and modify) the access, levels and akick\n"
-"lists and settings for any channel."
msgid ""
" \n"
@@ -990,11 +850,6 @@ msgid ""
"be removed after the given time. Set to 0 to disable bans from\n"
"automatically expiring."
msgstr ""
-" \n"
-"Sets the time bot bans expire in. If enabled, any bans placed by\n"
-"bots, such as flood kicker, badwords kicker, etc. will automatically\n"
-"be removed after the given time. Set to 0 to disable bans from\n"
-"automatically expiring."
#, c-format
msgid ""
@@ -1017,24 +872,6 @@ msgid ""
"The %s CLEAR command clears all entries of the\n"
"%s list."
msgstr ""
-" \n"
-"The %s ADD command adds the given nickname to the\n"
-"%s list.\n"
-" \n"
-"The %s DEL command removes the given nick from the\n"
-"%s list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The %s LIST command displays the %s list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" %s #channel LIST 2-5,7-9\n"
-" Lists %s entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The %s CLEAR command clears all entries of the\n"
-"%s list."
#, c-format
msgid ""
@@ -1058,25 +895,6 @@ msgid ""
"The AKICK CLEAR command clears all entries of the\n"
"akick list."
msgstr ""
-" \n"
-"The AKICK DEL command removes the given nick or mask\n"
-"from the AutoKick list. It does not, however, remove any\n"
-"bans placed by an AutoKick; those must be removed\n"
-"manually.\n"
-" \n"
-"The AKICK LIST command displays the AutoKick list, or\n"
-"optionally only those AutoKick entries which match the\n"
-"given mask.\n"
-" \n"
-"The AKICK VIEW command is a more verbose version of the\n"
-"AKICK LIST command.\n"
-" \n"
-"The AKICK ENFORCE command causes %s to enforce the\n"
-"current AKICK list by removing those users who match an\n"
-"AKICK mask.\n"
-" \n"
-"The AKICK CLEAR command clears all entries of the\n"
-"akick list."
msgid ""
" \n"
@@ -1099,25 +917,6 @@ msgid ""
" \n"
"AKILL CLEAR clears all entries of the AKILL list."
msgstr ""
-" \n"
-"The AKILL DEL command removes the given mask from the\n"
-"AKILL list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The AKILL LIST command displays the AKILL list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" AKILL LIST 2-5,7-9\n"
-" Lists AKILL entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"AKILL VIEW is a more verbose version of AKILL LIST, and\n"
-"will show who added an AKILL, the date it was added, and when\n"
-"it expires, as well as the user@host/ip mask and reason.\n"
-" \n"
-"AKILL CLEAR clears all entries of the AKILL list."
msgid ""
" \n"
@@ -1140,25 +939,6 @@ msgid ""
" \n"
"SNLINE CLEAR clears all entries of the SNLINE list."
msgstr ""
-" \n"
-"The SNLINE DEL command removes the given mask from the\n"
-"SNLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SNLINE LIST command displays the SNLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SNLINE LIST 2-5,7-9\n"
-" Lists SNLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SNLINE VIEW is a more verbose version of SNLINE LIST, and\n"
-"will show who added an SNLINE, the date it was added, and when\n"
-"it expires, as well as the realname mask and reason.\n"
-" \n"
-"SNLINE CLEAR clears all entries of the SNLINE list."
msgid ""
" \n"
@@ -1181,25 +961,6 @@ msgid ""
" \n"
"SQLINE CLEAR clears all entries of the SQLINE list."
msgstr ""
-" \n"
-"The SQLINE DEL command removes the given mask from the\n"
-"SQLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SQLINE LIST command displays the SQLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SQLINE LIST 2-5,7-9\n"
-" Lists SQLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SQLINE VIEW is a more verbose version of SQLINE LIST, and\n"
-"will show who added an SQLINE, the date it was added, and when\n"
-"it expires, as well as the mask and reason.\n"
-" \n"
-"SQLINE CLEAR clears all entries of the SQLINE list."
msgid ""
" \n"
@@ -1207,681 +968,711 @@ msgid ""
"is already assigned to the channel, it is unassigned\n"
"automatically when you enable it."
msgstr ""
-" \n"
-"This option makes a channel unassignable. If a bot\n"
-"is already assigned to the channel, it is unassigned\n"
-"automatically when you enable it."
msgid ""
" \n"
"This option prevents a bot from being assigned to a\n"
"channel by users that aren't IRC Operators."
msgstr ""
-" \n"
-"This option prevents a bot from being assigned to a\n"
-"channel by users that aren't IRC Operators."
#, c-format
msgid ""
" \n"
-"Type %s%s HELP command for help on any of the\n"
+"Type %s HELP command for help on any of the\n"
"above commands."
msgstr ""
-" \n"
-"Type %s%s HELP command for help on any of the\n"
-"above commands."
#, c-format
msgid " %s is online using this oper block."
-msgstr " %s is online using this oper block."
+msgstr ""
#, c-format
msgid " Command %s on %s is linked to %s"
-msgstr " Command %s on %s is linked to %s"
+msgstr ""
#, c-format
msgid " Providing service: %s"
-msgstr " Providing service: %s"
+msgstr ""
msgid " This oper is configured in the configuration file."
-msgstr " This oper is configured in the configuration file."
+msgstr ""
#, c-format
msgid " Loaded at: %p"
-msgstr " Loaded at: %p"
+msgstr ""
#, c-format
msgid " but %s mysteriously dematerialized."
-msgstr " but %s mysteriously dematerialized."
-
-#, c-format
-msgid "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
+msgstr ""
msgid "\"Jupiter\" a server"
-msgstr "\"Jupiter\" a server"
+msgstr ""
#, c-format
msgid "%-8s %s"
-msgstr "%-8s %s"
+msgstr ""
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr ""
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr "%b %d %H:%M:%S %Y %Z"
+msgid "%b %d %Y %H:%M:%S %Z"
+msgstr ""
#, c-format
msgid "%c is an unknown status mode."
-msgstr "%c is an unknown status mode."
+msgstr ""
#, c-format
msgid "%c%c is not locked on %s."
-msgstr "%c%c is not locked on %s."
+msgstr ""
#, c-format
msgid "%c%c%s has been unlocked from %s."
-msgstr "%c%c%s has been unlocked from %s."
+msgstr ""
#, c-format
msgid "%d access entries from %s have been cloned to %s."
-msgstr "%d access entries from %s have been cloned to %s."
+msgstr ""
#, c-format
msgid "%d bots available."
-msgstr "%d bots available."
+msgstr ""
#, c-format
msgid "%d modules loaded."
-msgstr "%d modules loaded."
+msgstr ""
#, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nickname(s) in the group."
+msgid "%lld day"
+msgid_plural "%lld days"
+msgstr[0] ""
+msgstr[1] ""
+
+#, c-format
+msgid "%lld hour"
+msgid_plural "%lld hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#, c-format
+msgid "%lld minute"
+msgid_plural "%lld minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#, c-format
+msgid "%lld second"
+msgid_plural "%lld seconds"
+msgstr[0] ""
+msgstr[1] ""
+
+#, c-format
+msgid "%lld year"
+msgid_plural "%lld years"
+msgstr[0] ""
+msgstr[1] ""
#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
-msgstr "%lu nicks are stored in the database, using %.2Lf kB of memory."
+msgstr ""
#, c-format
msgid "%s %s list is empty."
-msgstr "%s %s list is empty."
+msgstr ""
#, c-format
msgid "%s (%d kick(s) to ban)"
-msgstr "%s (%d kick(s) to ban)"
+msgstr ""
#, c-format
msgid "%s (%d kick(s) to ban; %d lines in %ds)"
-msgstr "%s (%d kick(s) to ban; %d lines in %ds)"
+msgstr ""
#, c-format
msgid "%s (%d kick(s) to ban; %d times)"
-msgstr "%s (%d kick(s) to ban; %d times)"
+msgstr ""
#, c-format
msgid "%s (%d kick(s) to ban; minimum %d/%d%%)"
-msgstr "%s (%d kick(s) to ban; minimum %d/%d%%)"
+msgstr ""
#, c-format
msgid "%s (%d lines in %ds)"
-msgstr "%s (%d lines in %ds)"
+msgstr ""
#, c-format
msgid "%s (%d times)"
-msgstr "%s (%d times)"
+msgstr ""
#, c-format
msgid "%s (%s) was kicked from %s (\"%s\") %s ago%s"
-msgstr "%s (%s) was kicked from %s (\"%s\") %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was kicked from a secret channel %s ago%s"
-msgstr "%s (%s) was kicked from a secret channel %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen changing nick from %s to %s %s ago%s"
-msgstr "%s (%s) was last seen changing nick from %s to %s %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen changing nick to %s %s ago%s"
-msgstr "%s (%s) was last seen changing nick to %s %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen connecting %s ago (%s)%s"
-msgstr "%s (%s) was last seen connecting %s ago (%s)%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen joining %s %s ago%s"
-msgstr "%s (%s) was last seen joining %s %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen joining a secret channel %s ago%s"
-msgstr "%s (%s) was last seen joining a secret channel %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen parting %s %s ago%s"
-msgstr "%s (%s) was last seen parting %s %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen parting a secret channel %s ago%s"
-msgstr "%s (%s) was last seen parting a secret channel %s ago%s"
+msgstr ""
#, c-format
msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
-msgstr "%s (%s) was last seen quitting (%s) %s ago (%s)."
+msgstr ""
#, c-format
msgid "%s (minimum %d/%d%%)"
-msgstr "%s (minimum %d/%d%%)"
+msgstr ""
#, c-format
msgid "%s access list is empty."
-msgstr "%s access list is empty."
+msgstr ""
#, c-format
msgid "%s added to %s's auto join list."
-msgstr "%s added to %s's auto join list."
+msgstr ""
#, c-format
msgid "%s already exists."
-msgstr "%s already exists."
+msgstr ""
#, c-format
msgid "%s autokick list is empty."
-msgstr "%s autokick list is empty."
+msgstr ""
#, c-format
msgid "%s bad words list is empty."
-msgstr "%s bad words list is empty."
+msgstr ""
+
+#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr ""
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr ""
#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
-msgstr "%s cannot be the successor on channel %s as they are the founder."
+msgstr ""
#, c-format
msgid "%s commands:"
-msgstr "%s commands:"
+msgstr ""
#, c-format
msgid "%s coverage is too wide; Please use a more specific mask."
-msgstr "%s coverage is too wide; Please use a more specific mask."
+msgstr ""
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s currently has %d memos, of which %d are unread."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr ""
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s currently has %d memos, of which 1 is unread."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr ""
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s currently has %d memos."
+msgid "%s currently has %zu memos."
+msgstr ""
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s currently has %d memos; all of them are unread."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr ""
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
-msgstr "%s currently has 1 memo, and it has not yet been read."
+msgstr ""
#, c-format
msgid "%s currently has 1 memo."
-msgstr "%s currently has 1 memo."
+msgstr ""
#, c-format
msgid "%s currently has no memos."
-msgstr "%s currently has no memos."
+msgstr ""
#, c-format
msgid "%s deleted from the %s forbid list."
-msgstr "%s deleted from the %s forbid list."
+msgstr ""
#, c-format
msgid "%s for %s set to %s."
-msgstr "%s for %s set to %s."
+msgstr ""
#, c-format
msgid "%s for %s unset."
-msgstr "%s for %s unset."
+msgstr ""
#, c-format
msgid "%s had an invalid key specified, and was thus ignored."
-msgstr "%s had an invalid key specified, and was thus ignored."
+msgstr ""
#, c-format
msgid "%s has no memo limit."
-msgstr "%s has no memo limit."
+msgstr ""
#, c-format
msgid "%s has no memos."
-msgstr "%s has no memos."
+msgstr ""
#, c-format
msgid "%s has no new memos."
-msgstr "%s has no new memos."
+msgstr ""
#, c-format
msgid "%s is %s"
-msgstr "%s is %s"
+msgstr ""
#, c-format
msgid "%s is a Services Operator of type %s."
-msgstr "%s is a Services Operator of type %s."
+msgstr ""
#, c-format
msgid "%s is a client on services."
-msgstr "%s is a client on services."
+msgstr ""
#, c-format
msgid "%s is a network service."
-msgstr "%s is a network service."
+msgstr ""
#, c-format
msgid "%s is already covered by %s."
-msgstr "%s is already covered by %s."
+msgstr ""
#, c-format
msgid "%s is already on %s's auto join list."
-msgstr "%s is already on %s's auto join list."
+msgstr ""
#, c-format
msgid "%s is an unconfirmed nickname."
-msgstr "%s is an unconfirmed nickname."
+msgstr ""
#, c-format
msgid ""
"%s is another way to modify the channel access list, similar to\n"
"the XOP and ACCESS methods."
msgstr ""
-"%s is another way to modify the channel access list, similar to\n"
-"the XOP and ACCESS methods."
#, c-format
msgid "%s is currently online."
-msgstr "%s is currently online."
+msgstr ""
#, c-format
msgid "%s is disabled"
-msgstr "%s is disabled"
+msgstr ""
#, c-format
msgid "%s is enabled"
-msgstr "%s is enabled"
+msgstr ""
#, c-format
msgid "%s is not a valid IP address."
-msgstr "%s is not a valid IP address."
+msgstr ""
#, c-format
msgid "%s is not a valid command."
-msgstr "%s is not a valid command."
+msgstr ""
#, c-format
msgid "%s is not a valid logging method."
-msgstr "%s is not a valid logging method."
+msgstr ""
#, c-format
msgid "%s is not notified of new memos."
-msgstr "%s is not notified of new memos."
+msgstr ""
#, c-format
msgid "%s is notified of new memos at logon and when they arrive."
-msgstr "%s is notified of new memos at logon and when they arrive."
+msgstr ""
#, c-format
msgid "%s is notified of new memos at logon."
-msgstr "%s is notified of new memos at logon."
+msgstr ""
#, c-format
msgid "%s is notified when new memos arrive."
-msgstr "%s is notified when new memos arrive."
+msgstr ""
#, c-format
msgid "%s is on the channel right now (as %s)!"
-msgstr "%s is on the channel right now (as %s)!"
+msgstr ""
#, c-format
msgid "%s is on the channel right now!"
-msgstr "%s is on the channel right now!"
+msgstr ""
#, c-format
msgid "%s list for %s"
-msgstr "%s list for %s"
+msgstr ""
#, c-format
msgid "%s list is empty."
-msgstr "%s list is empty."
+msgstr ""
#, c-format
msgid "%s locked on %s."
-msgstr "%s locked on %s."
+msgstr ""
#, c-format
msgid "%s not found."
-msgstr "%s not found."
+msgstr ""
#, c-format
msgid "%s settings:"
-msgstr "%s settings:"
+msgstr ""
#, c-format
msgid "%s was last seen here %s ago."
-msgstr "%s was last seen here %s ago."
+msgstr ""
#, c-format
msgid "%s was not found on %s's auto join list."
-msgstr "%s was not found on %s's auto join list."
+msgstr ""
#, c-format
msgid "%s was removed from %s's auto join list."
-msgstr "%s was removed from %s's auto join list."
+msgstr ""
#, c-format
msgid "%s will not send you any notification of memos."
-msgstr "%s will not send you any notification of memos."
+msgstr ""
#, c-format
msgid "%s will now notify you of memos when they are sent to you."
-msgstr "%s will now notify you of memos when they are sent to you."
+msgstr ""
#, c-format
msgid "%s will now notify you of memos when you log on and when they are sent to you."
-msgstr "%s will now notify you of memos when you log on and when they are sent to you."
+msgstr ""
#, c-format
msgid "%s will now notify you of memos when you log on or unset /AWAY."
-msgstr "%s will now notify you of memos when you log on or unset /AWAY."
+msgstr ""
#, c-format
msgid "%s!%s@%s (%s) added to the bot list."
-msgstr "%s!%s@%s (%s) added to the bot list."
-
-#, c-format
-msgid "%s's access list is empty."
-msgstr "%s's access list is empty."
+msgstr ""
#, c-format
msgid "%s's auto join list is empty."
-msgstr "%s's auto join list is empty."
+msgstr ""
#, c-format
msgid "%s's auto join list:"
-msgstr "%s's auto join list:"
+msgstr ""
#, c-format
msgid "%s's certificate list is empty."
-msgstr "%s's certificate list is empty."
+msgstr ""
#, c-format
msgid "%s's memo limit is %d, and may not be changed."
-msgstr "%s's memo limit is %d, and may not be changed."
+msgstr ""
#, c-format
msgid "%s's memo limit is %d."
-msgstr "%s's memo limit is %d."
+msgstr ""
+
+#, c-format
+msgid "%u channel"
+msgid_plural "%u channels"
+msgstr[0] ""
+msgstr[1] ""
+
+#, c-format
+msgid "%zu nickname in the group."
+msgid_plural "%zu nicknames in the group."
+msgstr[0] ""
+msgstr[1] ""
#, c-format
msgid "(%s ago)"
-msgstr "(%s ago)"
+msgstr ""
#, c-format
msgid "(%s from now)"
-msgstr "(%s from now)"
+msgstr ""
msgid "(Split)"
-msgstr "(Split)"
+msgstr ""
#, c-format
msgid "(by %s on %s) %s"
-msgstr "(by %s on %s) %s"
+msgstr ""
msgid "(disabled)"
-msgstr "(disabled)"
+msgstr ""
msgid "(founder only)"
-msgstr "(founder only)"
+msgstr ""
msgid "(now)"
-msgstr "(now)"
+msgstr ""
msgid "* AKILL any new clients connecting"
-msgstr "* AKILL any new clients connecting"
+msgstr ""
#, c-format
msgid "* Force channel modes (%s) to be set on all channels"
-msgstr "* Force channel modes (%s) to be set on all channels"
+msgstr ""
msgid "* Ignore non-opers with a message"
-msgstr "* Ignore non-opers with a message"
+msgstr ""
msgid "* Kill any new clients connecting"
-msgstr "* Kill any new clients connecting"
+msgstr ""
msgid "* No mode lock changes"
-msgstr "* No mode lock changes"
+msgstr ""
msgid "* No new channel registrations"
-msgstr "* No new channel registrations"
+msgstr ""
msgid "* No new memos sent"
-msgstr "* No new memos sent"
+msgstr ""
msgid "* No new nick registrations"
-msgstr "* No new nick registrations"
+msgstr ""
msgid "* Silently ignore non-opers"
-msgstr "* Silently ignore non-opers"
+msgstr ""
#, c-format
msgid "* Use the reduced session limit of %d"
-msgstr "* Use the reduced session limit of %d"
+msgstr ""
#, c-format
msgid ", but %s mysteriously dematerialized."
-msgstr ", but %s mysteriously dematerialized."
+msgstr ""
#, c-format
msgid ". %s is still online."
-msgstr ". %s is still online."
+msgstr ""
msgid "<unknown>"
-msgstr "<unknown>"
+msgstr ""
#, c-format
-msgid "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
-msgstr "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
+msgid "A confirmation email has been sent to %s. Follow the instructions in it to change your email address."
+msgstr ""
msgid "A massmemo has been sent to all registered users."
-msgstr "A massmemo has been sent to all registered users."
+msgstr ""
msgid "A memo informing the user will also be sent, which includes the reason for the rejection if supplied."
-msgstr "A memo informing the user will also be sent, which includes the reason for the rejection if supplied."
+msgstr ""
msgid "A memo informing the user will also be sent."
-msgstr "A memo informing the user will also be sent."
+msgstr ""
#, c-format
msgid ""
"A notification memo has been sent to %s informing them you have\n"
"read their memo."
msgstr ""
-"A notification memo has been sent to %s informing them you have\n"
-"read their memo."
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr "A vHost ident must be in the format of a valid ident."
+msgid "A vhost must be in the format of a valid hostname."
+msgstr ""
-msgid "A vHost must be in the format of a valid hostname."
-msgstr "A vHost must be in the format of a valid hostname."
+msgid "A vident must be in the format of a valid ident."
+msgstr ""
msgid "ADD expiry {nick|mask} [reason]"
-msgstr "ADD expiry {nick|mask} [reason]"
+msgstr ""
+
+msgid "ADD message"
+msgstr ""
msgid "ADD oper type"
-msgstr "ADD oper type"
+msgstr ""
msgid "ADD target info"
-msgstr "ADD target info"
+msgstr ""
msgid "ADD text"
-msgstr "ADD text"
+msgstr ""
msgid "ADD [+expiry] mask limit reason"
-msgstr "ADD [+expiry] mask limit reason"
+msgstr ""
msgid "ADD [nickname] channel [key]"
-msgstr "ADD [nickname] channel [key]"
-
-msgid "ADD [nickname] mask"
-msgstr "ADD [nickname] mask"
+msgstr ""
msgid "ADD [nickname] [fingerprint]"
-msgstr "ADD [nickname] [fingerprint]"
+msgstr ""
msgid "ADD [+expiry] mask reason"
-msgstr "ADD [+expiry] mask reason"
+msgstr ""
msgid "ADD [+expiry] mask:reason"
-msgstr "ADD [+expiry] mask:reason"
+msgstr ""
msgid "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiry] entry reason"
-msgstr "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiry] entry reason"
+msgstr ""
msgid "ADDIP server.name ip"
-msgstr "ADDIP server.name ip"
+msgstr ""
msgid "ADDSERVER server.name [zone.name]"
-msgstr "ADDSERVER server.name [zone.name]"
+msgstr ""
msgid "ADDZONE zone.name"
-msgstr "ADDZONE zone.name"
+msgstr ""
#, c-format
msgid "AKICK ENFORCE for %s complete; %d users were affected."
-msgstr "AKICK ENFORCE for %s complete; %d users were affected."
+msgstr ""
msgid "AKILL all users on a specific channel"
-msgstr "AKILL all users on a specific channel"
+msgstr ""
msgid "AKILL list is empty."
-msgstr "AKILL list is empty."
+msgstr ""
msgid "AMSG kicker"
-msgstr "AMSG kicker"
+msgstr ""
msgid "Access"
-msgstr "Access"
+msgstr ""
msgid "Access denied."
-msgstr "Access denied."
+msgstr ""
#, c-format
msgid "Access for %s on %s:"
-msgstr "Access for %s on %s:"
+msgstr ""
#, c-format
msgid "Access level must be between %d and %d inclusive."
-msgstr "Access level must be between %d and %d inclusive."
+msgstr ""
msgid "Access level must be non-zero."
-msgstr "Access level must be non-zero."
+msgstr ""
#, c-format
msgid "Access level settings for channel %s:"
-msgstr "Access level settings for channel %s:"
+msgstr ""
#, c-format
msgid "Access levels for %s reset to defaults."
-msgstr "Access levels for %s reset to defaults."
+msgstr ""
#, c-format
msgid "Access list for %s:"
-msgstr "Access list for %s:"
+msgstr ""
#, c-format
msgid "Access to this command requires the permission %s to be present in your opertype."
-msgstr "Access to this command requires the permission %s to be present in your opertype."
+msgstr ""
msgid "Account"
-msgstr "Account"
+msgstr ""
#, c-format
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
-msgstr "Account %s has already reached the maximum number of simultaneous logins (%u)."
+msgstr ""
+
+msgid "Account id"
+msgstr ""
-msgid "Activate security features"
-msgstr "Activate security features"
+msgid "Account registered"
+msgstr ""
+
+msgid "Accounts can not be registered right now. Please try again later."
+msgstr ""
-msgid "Activate the requested vHost for the given nick."
-msgstr "Activate the requested vHost for the given nick."
+msgid "Activate the requested vhost for the given nick."
+msgstr ""
msgid ""
"Activates the vhost currently assigned to the nick in use.\n"
"When you use this command any user who performs a /whois\n"
"on you will see the vhost instead of your real host/IP address."
msgstr ""
-"Activates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see the vhost instead of your real host/IP address."
msgid "Activates your assigned vhost"
-msgstr "Activates your assigned vhost"
+msgstr ""
msgid ""
"Add or delete oper information for a given nick or channel.\n"
"This will show to opers in the respective info command for\n"
"the nick or channel."
msgstr ""
-"Add or delete oper information for a given nick or channel.\n"
-"This will show to opers in the respective info command for\n"
-"the nick or channel."
#, c-format
msgid "Added IP %s to %s."
-msgstr "Added IP %s to %s."
+msgstr ""
#, c-format
msgid "Added a forbid on %s of type %s to expire on %s."
-msgstr "Added a forbid on %s of type %s to expire on %s."
+msgstr ""
#, c-format
msgid "Added info to %s."
-msgstr "Added info to %s."
+msgstr ""
msgid "Added new logon news item."
-msgstr "Added new logon news item."
+msgstr ""
msgid "Added new oper news item."
-msgstr "Added new oper news item."
+msgstr ""
msgid "Added new random news item."
-msgstr "Added new random news item."
+msgstr ""
#, c-format
msgid "Added server %s."
-msgstr "Added server %s."
+msgstr ""
#, c-format
msgid "Added zone %s."
-msgstr "Added zone %s."
+msgstr ""
msgid ""
"Adding, deleting, or clearing entry messages requires the\n"
"SET permission."
msgstr ""
-"Adding, deleting, or clearing entry messages requires the\n"
-"SET permission."
msgid ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
+"Additionally, Services Operators with the chanserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
msgstr ""
+
+msgid ""
"Additionally, Services Operators with the nickserv/confirm permission can\n"
"replace passcode with a users nick to force validate them."
+msgstr ""
+
+msgid ""
+"Additionally, Services Operators with the nickserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
+msgstr ""
#, c-format
msgid ""
@@ -1889,164 +1680,152 @@ msgid ""
"can be executed by prefixing the command name with\n"
"one of the following characters: %s"
msgstr ""
-"Additionally, if fantasy is enabled fantasy commands\n"
-"can be executed by prefixing the command name with\n"
-"one of the following characters: %s"
#, c-format
msgid "All O:lines of %s have been reset."
-msgstr "All O:lines of %s have been reset."
+msgstr ""
#, c-format
msgid "All akick entries from %s have been cloned to %s."
-msgstr "All akick entries from %s have been cloned to %s."
+msgstr ""
#, c-format
msgid "All available commands for %s:"
-msgstr "All available commands for %s:"
+msgstr ""
#, c-format
msgid "All badword entries from %s have been cloned to %s."
-msgstr "All badword entries from %s have been cloned to %s."
+msgstr ""
#, c-format
msgid "All level entries from %s have been cloned into %s."
-msgstr "All level entries from %s have been cloned into %s."
+msgstr ""
msgid "All logon news items deleted."
-msgstr "All logon news items deleted."
+msgstr ""
#, c-format
msgid "All memos for channel %s have been deleted."
-msgstr "All memos for channel %s have been deleted."
+msgstr ""
#, c-format
msgid "All modes cleared on %s."
-msgstr "All modes cleared on %s."
+msgstr ""
msgid "All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."
-msgstr "All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."
+msgstr ""
msgid "All of your memos have been deleted."
-msgstr "All of your memos have been deleted."
+msgstr ""
msgid "All oper news items deleted."
-msgstr "All oper news items deleted."
+msgstr ""
#, c-format
msgid "All operators from %s have been removed."
-msgstr "All operators from %s have been removed."
+msgstr ""
msgid "All random news items deleted."
-msgstr "All random news items deleted."
+msgstr ""
#, c-format
msgid "All settings from %s have been cloned to %s."
-msgstr "All settings from %s have been cloned to %s."
+msgstr ""
#, c-format
msgid "All user modes on %s have been synced."
-msgstr "All user modes on %s have been synced."
+msgstr ""
#, c-format
msgid "All vhosts in the group %s have been set to %s."
-msgstr "All vhosts in the group %s have been set to %s."
-
-#, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "All vhosts in the group %s have been set to %s@%s."
+msgstr ""
-msgid "Allowed to (de)halfop him/herself"
-msgstr "Allowed to (de)halfop him/herself"
+msgid "Allowed to (de)halfop themself"
+msgstr ""
msgid "Allowed to (de)halfop users"
-msgstr "Allowed to (de)halfop users"
+msgstr ""
-msgid "Allowed to (de)op him/herself"
-msgstr "Allowed to (de)op him/herself"
+msgid "Allowed to (de)op themself"
+msgstr ""
msgid "Allowed to (de)op users"
-msgstr "Allowed to (de)op users"
+msgstr ""
-msgid "Allowed to (de)owner him/herself"
-msgstr "Allowed to (de)owner him/herself"
+msgid "Allowed to (de)owner themself"
+msgstr ""
msgid "Allowed to (de)owner users"
-msgstr "Allowed to (de)owner users"
+msgstr ""
-msgid "Allowed to (de)protect him/herself"
-msgstr "Allowed to (de)protect him/herself"
+msgid "Allowed to (de)protect themself"
+msgstr ""
msgid "Allowed to (de)protect users"
-msgstr "Allowed to (de)protect users"
+msgstr ""
-msgid "Allowed to (de)voice him/herself"
-msgstr "Allowed to (de)voice him/herself"
+msgid "Allowed to (de)voice themself"
+msgstr ""
msgid "Allowed to (de)voice users"
-msgstr "Allowed to (de)voice users"
+msgstr ""
msgid "Allowed to assign/unassign a bot"
-msgstr "Allowed to assign/unassign a bot"
+msgstr ""
msgid "Allowed to ban users"
-msgstr "Allowed to ban users"
+msgstr ""
msgid "Allowed to change channel topics"
-msgstr "Allowed to change channel topics"
+msgstr ""
msgid "Allowed to get full INFO output"
-msgstr "Allowed to get full INFO output"
+msgstr ""
msgid "Allowed to issue commands restricted to channel founders"
-msgstr "Allowed to issue commands restricted to channel founders"
+msgstr ""
msgid "Allowed to modify channel badwords list"
-msgstr "Allowed to modify channel badwords list"
+msgstr ""
+
+msgid "Allowed to modify channel settings"
+msgstr ""
msgid "Allowed to modify the access list"
-msgstr "Allowed to modify the access list"
+msgstr ""
msgid "Allowed to read channel memos"
-msgstr "Allowed to read channel memos"
+msgstr ""
-msgid "Allowed to set channel settings"
-msgstr "Allowed to set channel settings"
+msgid "Allowed to unban themself"
+msgstr ""
msgid "Allowed to unban users"
-msgstr "Allowed to unban users"
+msgstr ""
msgid "Allowed to use GETKEY command"
-msgstr "Allowed to use GETKEY command"
+msgstr ""
msgid "Allowed to use SAY and ACT commands"
-msgstr "Allowed to use SAY and ACT commands"
+msgstr ""
msgid "Allowed to use fantasy commands"
-msgstr "Allowed to use fantasy commands"
+msgstr ""
msgid "Allowed to use the AKICK command"
-msgstr "Allowed to use the AKICK command"
+msgstr ""
msgid "Allowed to use the INVITE command"
-msgstr "Allowed to use the INVITE command"
+msgstr ""
msgid "Allowed to use the KICK command"
-msgstr "Allowed to use the KICK command"
+msgstr ""
msgid "Allowed to use the MODE command"
-msgstr "Allowed to use the MODE command"
+msgstr ""
msgid "Allowed to view the access list"
-msgstr "Allowed to view the access list"
-
-#, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
msgstr ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
msgid ""
"Allows Services Operators to change modes for any channel.\n"
@@ -2054,17 +1833,11 @@ msgid ""
"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
"If CLEAR ALL is given then all modes, including user status, is removed."
msgstr ""
-"Allows Services Operators to change modes for any channel.\n"
-"Parameters are the same as for the standard /MODE command.\n"
-"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
-"If CLEAR ALL is given then all modes, including user status, is removed."
msgid ""
"Allows Services Operators to change modes for any user.\n"
"Parameters are the same as for the standard /MODE command."
msgstr ""
-"Allows Services Operators to change modes for any user.\n"
-"Parameters are the same as for the standard /MODE command."
msgid ""
"Allows Services Operators to create, modify, and delete\n"
@@ -2085,61 +1858,24 @@ msgid ""
"currently registered. If an unregistered user is currently\n"
"using the nick, they will be killed."
msgstr ""
-"Allows Services Operators to create, modify, and delete\n"
-"bots that users will be able to use on their own\n"
-"channels.\n"
-" \n"
-"BOT ADD adds a bot with the given nickname, username,\n"
-"hostname and realname. Since no integrity checks are done\n"
-"for these settings, be really careful.\n"
-" \n"
-"BOT CHANGE allows you to change the nickname, username, hostname\n"
-"or realname of a bot without deleting it (and\n"
-"all the data associated with it).\n"
-" \n"
-"BOT DEL removes the given bot from the bot list.\n"
-" \n"
-"Note: You cannot create a bot with a nick that is\n"
-"currently registered. If an unregistered user is currently\n"
-"using the nick, they will be killed."
-
-msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
"Ignores will not be enforced on IRC Operators."
msgstr ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes,\n"
-"h for hours and d for days.\n"
-"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format nick!user@host,\n"
-"everything else will be considered a nick. Wildcards are permitted.\n"
-" \n"
-"Ignores will not be enforced on IRC Operators."
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2159,56 +1895,24 @@ msgid ""
"current AKILL default expiry time can be found with the\n"
"STATS AKILL command."
msgstr ""
-"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
-"will issue a KILL for that user and, on supported server\n"
-"types, will instruct all servers to add a ban for the mask\n"
-"which the user matched.\n"
-" \n"
-"AKILL ADD adds the given mask to the AKILL\n"
-"list for the given reason, which must be given.\n"
-"Mask should be in the format of nick!user@host#real name,\n"
-"though all that is required is user@host. If a real name is specified,\n"
-"the reason must be prepended with a :.\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an AKILL which does not expire, use +0. If the\n"
-"usermask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current AKILL default expiry time can be found with the\n"
-"STATS AKILL command."
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
-"Allows Services Operators to manipulate the SNLINE list. If\n"
-"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
-"session."
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
"regular expression, the expression will be matched against\n"
"channels too."
msgstr ""
-"Allows Services Operators to manipulate the SQLINE list. If\n"
-"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
-"session.\n"
-"If the first character of the mask is #, services will\n"
-"prevent the use of matching channels. If the mask is a\n"
-"regular expression, the expression will be matched against\n"
-"channels too."
msgid ""
"Allows Services Operators to manipulate the list of hosts that\n"
@@ -2220,14 +1924,6 @@ msgid ""
"source of help regarding session limiting. The content of\n"
"this notice is a config setting."
msgstr ""
-"Allows Services Operators to manipulate the list of hosts that\n"
-"have specific session limits - allowing certain machines,\n"
-"such as shell servers, to carry more than the default number\n"
-"of clients at a time. Once a host reaches its session limit,\n"
-"all clients attempting to connect from that host will be\n"
-"killed. Before the user is killed, they are notified, of a\n"
-"source of help regarding session limiting. The content of\n"
-"this notice is a config setting."
msgid ""
"Allows Services Operators to view the session list.\n"
@@ -2245,20 +1941,6 @@ msgid ""
"limiting and how to set session limits specific to certain\n"
"hosts and groups thereof."
msgstr ""
-"Allows Services Operators to view the session list.\n"
-" \n"
-"SESSION LIST lists hosts with at least threshold sessions.\n"
-"The threshold must be a number greater than 1. This is to\n"
-"prevent accidental listing of the large number of single\n"
-"session hosts.\n"
-" \n"
-"SESSION VIEW displays detailed information about a specific\n"
-"host - including the current session count and session limit.\n"
-"The host value may not include wildcards.\n"
-" \n"
-"See the EXCEPTION help for more information about session\n"
-"limiting and how to set session limits specific to certain\n"
-"hosts and groups thereof."
msgid ""
"Allows manipulating the topic of the specified channel.\n"
@@ -2270,30 +1952,44 @@ msgid ""
"topic lock is set, the channel topic will be unchangeable by users who do not have\n"
"the TOPIC privilege."
msgstr ""
-"Allows manipulating the topic of the specified channel.\n"
-"The SET command changes the topic of the channel to the given topic\n"
-"or unsets the topic if no topic is given. The APPEND command appends\n"
-"the given topic to the existing topic.\n"
-" \n"
-"LOCK and UNLOCK may be used to enable and disable topic lock. When\n"
-"topic lock is set, the channel topic will be unchangeable by users who do not have\n"
-"the TOPIC privilege."
+
+msgid ""
+"Allows queueing messages to send to users on the network.\n"
+"\n"
+"The QUEUE ADD command adds the given message to the message queue.\n"
+"The QUEUE CLEAR command clears the message queue.\n"
+"The QUEUE DEL command removes the specified message from the message queue. The\n"
+"message number can be obtained from the output of the QUEUE LIST command.\n"
+"The QUEUE LIST command lists all messages that are currently in the message queue."
+msgstr ""
#, c-format
msgid ""
-"Allows staff to kick a user from any channel.\n"
-"Parameters are the same as for the standard /KICK\n"
-"command. The kick message will have the nickname of the\n"
-"IRCop sending the KICK command prepended; for example:\n"
-" \n"
-"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
+"Allows sending messages to all users on a server. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on the network. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
msgstr ""
+
+#, c-format
+msgid ""
"Allows staff to kick a user from any channel.\n"
"Parameters are the same as for the standard /KICK\n"
"command. The kick message will have the nickname of the\n"
"IRCop sending the KICK command prepended; for example:\n"
" \n"
"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
+msgstr ""
msgid ""
"Allows the channel founder to set various channel options\n"
@@ -2301,19 +1997,12 @@ msgid ""
" \n"
"Available options:"
msgstr ""
-"Allows the channel founder to set various channel options\n"
-"and other information.\n"
-" \n"
-"Available options:"
msgid ""
"Allows you to change and view Services Operators.\n"
"Note that operators removed by this command but are still set in\n"
"the configuration file are not permanently affected by this."
msgstr ""
-"Allows you to change and view Services Operators.\n"
-"Note that operators removed by this command but are still set in\n"
-"the configuration file are not permanently affected by this."
msgid ""
"Allows you to change and view configuration settings.\n"
@@ -2322,34 +2011,21 @@ msgid ""
"restarted, or the configuration is reloaded.\n"
" \n"
"Example:\n"
-" MODIFY nickserv forcemail no"
+" MODIFY nickserv regdelay 15m"
msgstr ""
-"Allows you to change and view configuration settings.\n"
-"Settings changed by this command are temporary and will not be reflected\n"
-"back into the configuration file, and will be lost if Anope is shut down,\n"
-"restarted, or the configuration is reloaded.\n"
-" \n"
-"Example:\n"
-" MODIFY nickserv forcemail no"
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
-"use notices."
msgid ""
"Allows you to ignore users by nick or host from memoing\n"
@@ -2357,59 +2033,38 @@ msgid ""
"to memo you or a channel, they will not be told that you have\n"
"them ignored."
msgstr ""
-"Allows you to ignore users by nick or host from memoing\n"
-"you or a channel. If someone on the memo ignore list tries\n"
-"to memo you or a channel, they will not be told that you have\n"
-"them ignored."
msgid ""
"Allows you to kill a user from the network.\n"
"Parameters are the same as for the standard /KILL\n"
"command."
msgstr ""
-"Allows you to kill a user from the network.\n"
-"Parameters are the same as for the standard /KILL\n"
-"command."
#, c-format
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
+"nick. You can hide the email address (EMAIL), last seen\n"
"user@host mask (USERMASK), the services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
"be displayed (OFF) or hidden (ON)."
msgstr ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
#, c-format
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
+"nick. You can hide your email address (EMAIL), last seen\n"
"user@host mask (USERMASK), your services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
"be displayed (OFF) or hidden (ON)."
msgstr ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), your services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
#, c-format
msgid "Allows you to see %s information about a channel or a bot"
-msgstr "Allows you to see %s information about a channel or a bot"
+msgstr ""
#, c-format
msgid ""
@@ -2419,132 +2074,119 @@ msgid ""
"you'll get information about a bot, such as creation\n"
"time or number of channels it is on."
msgstr ""
-"Allows you to see %s information about a channel or a bot.\n"
-"If the parameter is a channel, then you'll get information\n"
-"such as enabled kickers. If the parameter is a nick,\n"
-"you'll get information about a bot, such as creation\n"
-"time or number of channels it is on."
msgid ""
"Alternative methods of modifying channel access lists are\n"
"available."
msgstr ""
-"Alternative methods of modifying channel access lists are\n"
-"available."
-msgid "Approve the requested vHost of a user"
-msgstr "Approve the requested vHost of a user"
+msgid "Approve the requested vhost of a user"
+msgstr ""
msgid "As a Services Operator, you may drop any nick."
-msgstr "As a Services Operator, you may drop any nick."
+msgstr ""
msgid "Assigns a bot to a channel"
-msgstr "Assigns a bot to a channel"
+msgstr ""
msgid ""
"Assigns the specified bot to a channel. You\n"
"can then configure the bot for the channel so it fits\n"
"your needs."
msgstr ""
-"Assigns the specified bot to a channel. You\n"
-"can then configure the bot for the channel so it fits\n"
-"your needs."
msgid "Associate a URL with the channel"
-msgstr "Associate a URL with the channel"
+msgstr ""
msgid "Associate a URL with this account"
-msgstr "Associate a URL with this account"
+msgstr ""
msgid "Associate a URL with your account"
-msgstr "Associate a URL with your account"
+msgstr ""
msgid "Associate a greet message with your nickname"
-msgstr "Associate a greet message with your nickname"
+msgstr ""
-msgid "Associate an E-mail address with the channel"
-msgstr "Associate an E-mail address with the channel"
+msgid "Associate an email address with the channel"
+msgstr ""
-msgid "Associate an E-mail address with your nickname"
-msgstr "Associate an E-mail address with your nickname"
+msgid "Associate an email address with your nickname"
+msgstr ""
msgid "Associate oper info with a nick or channel"
-msgstr "Associate oper info with a nick or channel"
+msgstr ""
-msgid "Associates the given E-mail address with the nickname."
-msgstr "Associates the given E-mail address with the nickname."
+msgid "Associates the given email address with the nickname."
+msgstr ""
msgid ""
-"Associates the given E-mail address with your nickname.\n"
+"Associates the given email address with your nickname.\n"
"This address will be displayed whenever someone requests\n"
"information on the nickname with the INFO command."
msgstr ""
-"Associates the given E-mail address with your nickname.\n"
-"This address will be displayed whenever someone requests\n"
-"information on the nickname with the INFO command."
msgid "Auto-op"
-msgstr "Auto-op"
+msgstr ""
#, c-format
msgid "Autokick list for %s:"
-msgstr "Autokick list for %s:"
+msgstr ""
msgid "Automatic channel operator status upon join"
-msgstr "Automatic channel operator status upon join"
+msgstr ""
msgid "Automatic halfop upon join"
-msgstr "Automatic halfop upon join"
+msgstr ""
msgid "Automatic owner upon join"
-msgstr "Automatic owner upon join"
+msgstr ""
msgid "Automatic protect upon join"
-msgstr "Automatic protect upon join"
+msgstr ""
msgid "Automatic voice on join"
-msgstr "Automatic voice on join"
+msgstr ""
#, c-format
msgid "Available commands for %s:"
-msgstr "Available commands for %s:"
+msgstr ""
msgid "Available opertypes:"
-msgstr "Available opertypes:"
+msgstr ""
#, c-format
msgid "Available privileges for %s:"
-msgstr "Available privileges for %s:"
+msgstr ""
msgid "BANS enforced by "
-msgstr "BANS enforced by "
+msgstr ""
msgid "Bad words kicker"
-msgstr "Bad words kicker"
+msgstr ""
#, c-format
msgid "Bad words list for %s:"
-msgstr "Bad words list for %s:"
+msgstr ""
msgid "Bad words list is now empty."
-msgstr "Bad words list is now empty."
+msgstr ""
msgid "Ban expiry may not be longer than 1 day."
-msgstr "Ban expiry may not be longer than 1 day."
+msgstr ""
#, c-format
msgid "Ban on %s expires in %s."
-msgstr "Ban on %s expires in %s."
+msgstr ""
msgid "Ban type"
-msgstr "Ban type"
+msgstr ""
#, c-format
msgid "Ban type for channel %s is now #%d."
-msgstr "Ban type for channel %s is now #%d."
+msgstr ""
msgid "Bans a given nick or mask on a channel"
-msgstr "Bans a given nick or mask on a channel"
+msgstr ""
msgid ""
"Bans a given nick or mask on a channel. An optional expiry may\n"
@@ -2554,117 +2196,109 @@ msgid ""
"By default, limited to AOPs or those with level 5 access\n"
"and above on the channel. Channel founders may ban masks."
msgstr ""
-"Bans a given nick or mask on a channel. An optional expiry may\n"
-"be given to cause services to remove the ban after a set amount\n"
-"of time.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders may ban masks."
#, c-format
msgid "Bans enforced on %s."
-msgstr "Bans enforced on %s."
+msgstr ""
msgid "Bolds kicker"
-msgstr "Bolds kicker"
+msgstr ""
#, c-format
msgid "Bot %s already exists."
-msgstr "Bot %s already exists."
+msgstr ""
#, c-format
msgid "Bot %s does not exist."
-msgstr "Bot %s does not exist."
+msgstr ""
#, c-format
msgid "Bot %s has been assigned to %s."
-msgstr "Bot %s has been assigned to %s."
+msgstr ""
#, c-format
msgid "Bot %s has been changed to %s!%s@%s (%s)."
-msgstr "Bot %s has been changed to %s!%s@%s (%s)."
+msgstr ""
#, c-format
msgid "Bot %s has been deleted."
-msgstr "Bot %s has been deleted."
+msgstr ""
#, c-format
msgid "Bot %s is already assigned to channel %s."
-msgstr "Bot %s is already assigned to channel %s."
+msgstr ""
#, c-format
msgid "Bot will kick ops on channel %s."
-msgstr "Bot will kick ops on channel %s."
+msgstr ""
#, c-format
msgid "Bot will kick voices on channel %s."
-msgstr "Bot will kick voices on channel %s."
+msgstr ""
#, c-format
msgid "Bot won't kick ops on channel %s."
-msgstr "Bot won't kick ops on channel %s."
+msgstr ""
#, c-format
msgid "Bot won't kick voices on channel %s."
-msgstr "Bot won't kick voices on channel %s."
+msgstr ""
#, c-format
msgid "Bot %s is not changeable."
-msgstr "Bot %s is not changeable."
+msgstr ""
#, c-format
msgid "Bot %s is not deletable."
-msgstr "Bot %s is not deletable."
+msgstr ""
#, c-format
msgid "Bot bans will automatically expire after %s."
-msgstr "Bot bans will automatically expire after %s."
+msgstr ""
msgid "Bot bans will no longer automatically expire."
-msgstr "Bot bans will no longer automatically expire."
+msgstr ""
#, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Bot hosts may only be %d characters long."
+msgid "Bot hosts may only be %zu characters long."
+msgstr ""
msgid "Bot hosts may only contain valid host characters."
-msgstr "Bot hosts may only contain valid host characters."
+msgstr ""
#, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Bot idents may only be %d characters long."
+msgid "Bot idents may only be %zu characters long."
+msgstr ""
msgid "Bot idents may only contain valid ident characters."
-msgstr "Bot idents may only contain valid ident characters."
+msgstr ""
#, c-format
msgid "Bot is not on channel %s."
-msgstr "Bot is not on channel %s."
+msgstr ""
msgid "Bot list:"
-msgstr "Bot list:"
+msgstr ""
msgid "Bot nick"
-msgstr "Bot nick"
+msgstr ""
#, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Bot nicks may only be %d characters long."
+msgid "Bot nicks may only be %zu characters long."
+msgstr ""
msgid "Bot nicks may only contain valid nick characters."
-msgstr "Bot nicks may only contain valid nick characters."
+msgstr ""
#, c-format
msgid ""
"Bot will now kick for %s, and will place a ban\n"
"after %d kicks for the same user."
msgstr ""
-"Bot will now kick for %s, and will place a ban\n"
-"after %d kicks for the same user."
#, c-format
msgid "Bot will now kick for %s."
-msgstr "Bot will now kick for %s."
+msgstr ""
#, c-format
msgid ""
@@ -2672,29 +2306,22 @@ msgid ""
"%d characters and %d%% of the entire message), and will\n"
"place a ban after %d kicks for the same user."
msgstr ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message), and will\n"
-"place a ban after %d kicks for the same user."
#, c-format
msgid ""
"Bot will now kick for caps (they must constitute at least\n"
"%d characters and %d%% of the entire message)."
msgstr ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message)."
#, c-format
msgid ""
"Bot will now kick for flood (%d lines in %d seconds\n"
"and will place a ban after %d kicks for the same user."
msgstr ""
-"Bot will now kick for flood (%d lines in %d seconds\n"
-"and will place a ban after %d kicks for the same user."
#, c-format
msgid "Bot will now kick for flood (%d lines in %d seconds)."
-msgstr "Bot will now kick for flood (%d lines in %d seconds)."
+msgstr ""
#, c-format
msgid ""
@@ -2702,17 +2329,12 @@ msgid ""
"same message %d time), and will place a ban after %d\n"
"kicks for the same user."
msgstr ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time), and will place a ban after %d\n"
-"kicks for the same user."
#, c-format
msgid ""
"Bot will now kick for repeats (users that repeat the\n"
"same message %d time)."
msgstr ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time)."
#, c-format
msgid ""
@@ -2720,177 +2342,142 @@ msgid ""
"same message %d times), and will place a ban after %d\n"
"kicks for the same user."
msgstr ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times), and will place a ban after %d\n"
-"kicks for the same user."
#, c-format
msgid ""
"Bot will now kick for repeats (users that repeat the\n"
"same message %d times)."
msgstr ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times)."
#, c-format
msgid "Bot won't kick for %s anymore."
-msgstr "Bot won't kick for %s anymore."
+msgstr ""
msgid "Bot won't kick for caps anymore."
-msgstr "Bot won't kick for caps anymore."
+msgstr ""
msgid "Bot won't kick for flood anymore."
-msgstr "Bot won't kick for flood anymore."
+msgstr ""
msgid "Bot won't kick for repeats anymore."
-msgstr "Bot won't kick for repeats anymore."
+msgstr ""
msgid "By"
-msgstr "By"
+msgstr ""
msgid "CLEAR target"
-msgstr "CLEAR target"
+msgstr ""
msgid "CLEAR time"
-msgstr "CLEAR time"
+msgstr ""
msgid "Cancel the last memo you sent"
-msgstr "Cancel the last memo you sent"
+msgstr ""
msgid "Cancel the registration of a channel"
-msgstr "Cancel the registration of a channel"
+msgstr ""
msgid "Cancel the registration of a nickname"
-msgstr "Cancel the registration of a nickname"
+msgstr ""
msgid ""
"Cancels the last memo you sent to the given nick or channel,\n"
"provided it has not been read at the time you use the command."
msgstr ""
-"Cancels the last memo you sent to the given nick or channel,\n"
-"provided it has not been read at the time you use the command."
#, c-format
msgid "Cannot clone channel %s to itself!"
-msgstr "Cannot clone channel %s to itself!"
+msgstr ""
msgid "Cannot send mail now; please retry a little later."
-msgstr "Cannot send mail now; please retry a little later."
+msgstr ""
msgid "Caps kicker"
-msgstr "Caps kicker"
+msgstr ""
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
msgstr ""
-"Causes Services to do an immediate shutdown; databases are\n"
-"not saved. This command should not be used unless\n"
-"damage to the in-memory copies of the databases is feared\n"
-"and they should not be saved."
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
-"session limitation, etc.)."
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr ""
-"Causes Services to save all databases and then restart\n"
-"(i.e. exit and immediately re-run the executable)."
-msgid "Causes Services to save all databases and then shut down."
-msgstr "Causes Services to save all databases and then shut down."
+msgid "Causes services to save all databases and then shut down."
+msgstr ""
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr ""
-"Causes Services to update all database files as soon as you\n"
-"send the command."
#, c-format
msgid "Certificate list for %s:"
-msgstr "Certificate list for %s:"
+msgstr ""
msgid "ChanServ is required to enable persist on this network."
-msgstr "ChanServ is required to enable persist on this network."
+msgstr ""
msgid "Change channel modes"
-msgstr "Change channel modes"
+msgstr ""
-msgid "Change the communication method of Services"
-msgstr "Change the communication method of Services"
+msgid "Change the communication method of services"
+msgstr ""
msgid "Change user modes"
-msgstr "Change user modes"
+msgstr ""
#, c-format
msgid "Changed usermodes of %s to %s."
-msgstr "Changed usermodes of %s to %s."
+msgstr ""
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
-"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
-"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
msgid ""
"Changes the founder of a channel. The new nickname must\n"
"be a registered one."
msgstr ""
-"Changes the founder of a channel. The new nickname must\n"
-"be a registered one."
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Changes the language Services uses when sending messages to\n"
-"the given user (for example, when responding to a command they send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Changes the language Services uses when sending messages to\n"
-"you (for example, when responding to a command you send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
msgid "Changes the password used to identify as the nick's owner."
-msgstr "Changes the password used to identify as the nick's owner."
+msgstr ""
msgid ""
"Changes the password used to identify you as the nick's\n"
"owner."
msgstr ""
-"Changes the password used to identify you as the nick's\n"
-"owner."
msgid ""
"Changes the successor of a channel. If the founder's\n"
@@ -2902,234 +2489,226 @@ msgid ""
"become the new founder, but if the access list is empty, the\n"
"channel will be dropped."
msgstr ""
-"Changes the successor of a channel. If the founder's\n"
-"nickname expires or is dropped while the channel is still\n"
-"registered, the successor will become the new founder of the\n"
-"channel. The successor's nickname must be a registered one.\n"
-"If there's no successor set, then the first nickname on the\n"
-"access list (with the highest access, if applicable) will\n"
-"become the new founder, but if the access list is empty, the\n"
-"channel will be dropped."
+
+#, c-format
+msgid "Changing your usermodes to %s"
+msgstr ""
+
+#, c-format
+msgid "Changing your vhost to %s"
+msgstr ""
msgid "Channel"
-msgstr "Channel"
+msgstr ""
#, c-format
msgid "Channel %s doesn't exist."
-msgstr "Channel %s doesn't exist."
+msgstr ""
#, c-format
msgid "Channel %s has been dropped."
-msgstr "Channel %s has been dropped."
+msgstr ""
#, c-format
msgid "Channel %s has no key."
-msgstr "Channel %s has no key."
+msgstr ""
#, c-format
msgid "Channel %s is already registered!"
-msgstr "Channel %s is already registered!"
+msgstr ""
#, c-format
msgid "Channel %s is forbidden by %s: %s"
-msgstr "Channel %s is forbidden by %s: %s"
+msgstr ""
#, c-format
msgid "Channel %s is forbidden."
-msgstr "Channel %s is forbidden."
+msgstr ""
#, c-format
msgid "Channel %s is no longer persistent."
-msgstr "Channel %s is no longer persistent."
+msgstr ""
#, c-format
msgid "Channel %s is now persistent."
-msgstr "Channel %s is now persistent."
+msgstr ""
#, c-format
msgid "Channel %s is now released."
-msgstr "Channel %s is now released."
+msgstr ""
#, c-format
msgid "Channel %s is now suspended."
-msgstr "Channel %s is now suspended."
+msgstr ""
#, c-format
msgid "Channel %s isn't registered."
-msgstr "Channel %s isn't registered."
+msgstr ""
#, c-format
msgid "Channel %s isn't suspended."
-msgstr "Channel %s isn't suspended."
+msgstr ""
#, c-format
msgid "Channel %s registered under your account: %s"
-msgstr "Channel %s registered under your account: %s"
+msgstr ""
#, c-format
msgid "Channel %s will expire."
-msgstr "Channel %s will expire."
+msgstr ""
#, c-format
msgid "Channel %s will not expire."
-msgstr "Channel %s will not expire."
+msgstr ""
#, c-format
msgid "Channel %s %s list has been cleared."
-msgstr "Channel %s %s list has been cleared."
+msgstr ""
#, c-format
msgid "Channel %s access list has been cleared."
-msgstr "Channel %s access list has been cleared."
+msgstr ""
#, c-format
msgid "Channel %s akick list has been cleared."
-msgstr "Channel %s akick list has been cleared."
+msgstr ""
#, c-format
msgid "Channel %s has no mode locks."
-msgstr "Channel %s has no mode locks."
+msgstr ""
#, c-format
msgid "Channel %s is currently suspended."
-msgstr "Channel %s is currently suspended."
+msgstr ""
#, c-format
msgid "Channel %s is not a valid channel."
-msgstr "Channel %s is not a valid channel."
+msgstr ""
msgid "Channel list:"
-msgstr "Channel list:"
+msgstr ""
#, c-format
msgid "Channel stats for %s on %s:"
-msgstr "Channel stats for %s on %s:"
+msgstr ""
msgid "Channels may not be on access lists."
-msgstr "Channels may not be on access lists."
+msgstr ""
#, c-format
msgid "Channels that %s has access on:"
-msgstr "Channels that %s has access on:"
+msgstr ""
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Channels: %lu entries, %lu buckets, longest chain is %d"
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr ""
msgid "Chanstats"
-msgstr "Chanstats"
+msgstr ""
#, c-format
msgid "Chanstats statistics are now disabled for %s"
-msgstr "Chanstats statistics are now disabled for %s"
+msgstr ""
msgid "Chanstats statistics are now disabled for this channel."
-msgstr "Chanstats statistics are now disabled for this channel."
+msgstr ""
msgid "Chanstats statistics are now disabled for your nick."
-msgstr "Chanstats statistics are now disabled for your nick."
+msgstr ""
#, c-format
msgid "Chanstats statistics are now enabled for %s"
-msgstr "Chanstats statistics are now enabled for %s"
+msgstr ""
msgid "Chanstats statistics are now enabled for this channel."
-msgstr "Chanstats statistics are now enabled for this channel."
+msgstr ""
msgid "Chanstats statistics are now enabled for your nick."
-msgstr "Chanstats statistics are now enabled for your nick."
+msgstr ""
msgid ""
"Checks for the last time nick was seen joining, leaving,\n"
"or changing nick on the network and tells you when and, depending\n"
"on channel or user settings, where it was."
msgstr ""
-"Checks for the last time nick was seen joining, leaving,\n"
-"or changing nick on the network and tells you when and, depending\n"
-"on channel or user settings, where it was."
msgid "Checks if last memo to a nick was read"
-msgstr "Checks if last memo to a nick was read"
+msgstr ""
msgid ""
"Checks whether the _last_ memo you sent to nick has been read\n"
"or not. Note that this only works with nicks, not with channels."
msgstr ""
-"Checks whether the _last_ memo you sent to nick has been read\n"
-"or not. Note that this only works with nicks, not with channels."
#, c-format
msgid "Cleared info from %s."
-msgstr "Cleared info from %s."
+msgstr ""
msgid "Colors kicker"
-msgstr "Colors kicker"
+msgstr ""
msgid "Command"
-msgstr "Command"
+msgstr ""
msgid "Configures AMSG kicker"
-msgstr "Configures AMSG kicker"
+msgstr ""
msgid "Configures badwords kicker"
-msgstr "Configures badwords kicker"
+msgstr ""
msgid "Configures bolds kicker"
-msgstr "Configures bolds kicker"
+msgstr ""
msgid "Configures bot kickers. option can be one of:"
-msgstr "Configures bot kickers. option can be one of:"
+msgstr ""
msgid "Configures bot options"
-msgstr "Configures bot options"
+msgstr ""
msgid ""
"Configures bot options.\n"
" \n"
"Available options:"
msgstr ""
-"Configures bot options.\n"
-" \n"
-"Available options:"
msgid "Configures caps kicker"
-msgstr "Configures caps kicker"
+msgstr ""
msgid "Configures channel logging settings"
-msgstr "Configures channel logging settings"
+msgstr ""
msgid "Configures color kicker"
-msgstr "Configures color kicker"
+msgstr ""
msgid "Configures flood kicker"
-msgstr "Configures flood kicker"
+msgstr ""
msgid "Configures italics kicker"
-msgstr "Configures italics kicker"
+msgstr ""
msgid "Configures kickers"
-msgstr "Configures kickers"
+msgstr ""
msgid "Configures repeat kicker"
-msgstr "Configures repeat kicker"
+msgstr ""
msgid "Configures reverses kicker"
-msgstr "Configures reverses kicker"
+msgstr ""
msgid "Configures the time bot bans expire in"
-msgstr "Configures the time bot bans expire in"
+msgstr ""
msgid "Configures underlines kicker"
-msgstr "Configures underlines kicker"
+msgstr ""
msgid "Confirm a passcode"
-msgstr "Confirm a passcode"
+msgstr ""
msgid "Control modes and mode locks on a channel"
-msgstr "Control modes and mode locks on a channel"
+msgstr ""
msgid "Controls what messages will be sent to users when they join the channel."
-msgstr "Controls what messages will be sent to users when they join the channel."
+msgstr ""
msgid ""
"Copies all settings, access, akicks, etc from channel to the\n"
@@ -3137,254 +2716,254 @@ msgid ""
"or LEVELS then only the respective settings are cloned.\n"
"You must be the founder of channel and target."
msgstr ""
-"Copies all settings, access, akicks, etc from channel to the\n"
-"target channel. If what is ACCESS, AKICK, BADWORDS,\n"
-"or LEVELS then only the respective settings are cloned.\n"
-"You must be the founder of channel and target."
msgid "Copy all settings from one channel to another"
-msgstr "Copy all settings from one channel to another"
+msgstr ""
msgid "Created"
-msgstr "Created"
+msgstr ""
msgid "Creator"
-msgstr "Creator"
+msgstr ""
#, c-format
msgid "Current %s list:"
-msgstr "Current %s list:"
+msgstr ""
msgid "Current AKILL list:"
-msgstr "Current AKILL list:"
+msgstr ""
msgid "Current Session Limit Exception list:"
-msgstr "Current Session Limit Exception list:"
+msgstr ""
msgid "Current module list:"
-msgstr "Current module list:"
+msgstr ""
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Current number of AKILLs: %d"
+msgid "Current number of AKILLs: %zu"
+msgstr ""
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Current number of SNLINEs: %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr ""
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Current number of SQLINEs: %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr ""
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Current users: %d (%d ops)"
+msgid "Current users: %zu (%d ops)"
+msgstr ""
+
+msgid "DEL entry-num"
+msgstr ""
msgid "DEL oper"
-msgstr "DEL oper"
+msgstr ""
msgid "DEL target info"
-msgstr "DEL target info"
+msgstr ""
msgid "DEL [nickname] channel"
-msgstr "DEL [nickname] channel"
+msgstr ""
msgid "DEL [nickname] fingerprint"
-msgstr "DEL [nickname] fingerprint"
-
-msgid "DEL [nickname] mask"
-msgstr "DEL [nickname] mask"
+msgstr ""
msgid "DEL {mask | entry-num | list | id}"
-msgstr "DEL {mask | entry-num | list | id}"
+msgstr ""
msgid "DEL {mask | entry-num | list}"
-msgstr "DEL {mask | entry-num | list}"
+msgstr ""
msgid "DEL {nick|mask}"
-msgstr "DEL {nick|mask}"
+msgstr ""
msgid "DEL {num | ALL}"
-msgstr "DEL {num | ALL}"
+msgstr ""
msgid "DEL {NICK|CHAN|EMAIL|REGISTER} entry"
-msgstr "DEL {NICK|CHAN|EMAIL|REGISTER} entry"
+msgstr ""
msgid "DELIP server.name ip"
-msgstr "DELIP server.name ip"
+msgstr ""
msgid "DELSERVER server.name [zone.name]"
-msgstr "DELSERVER server.name [zone.name]"
+msgstr ""
msgid "DELZONE zone.name"
-msgstr "DELZONE zone.name"
+msgstr ""
msgid "DEPOOL server.name"
-msgstr "DEPOOL server.name"
+msgstr ""
#, c-format
msgid "Database cleared, removed %lu nicks that were added after %s."
-msgstr "Database cleared, removed %lu nicks that were added after %s."
+msgstr ""
msgid "Date/Time"
-msgstr "Date/Time"
+msgstr ""
msgid ""
"Deactivates the vhost currently assigned to the nick in use.\n"
"When you use this command any user who performs a /whois\n"
"on you will see your real host/IP address."
msgstr ""
-"Deactivates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see your real host/IP address."
msgid "Deactivates your assigned vhost"
-msgstr "Deactivates your assigned vhost"
+msgstr ""
#, c-format
msgid "Default AKILL expiry time: %d days"
-msgstr "Default AKILL expiry time: %d days"
+msgstr ""
#, c-format
msgid "Default AKILL expiry time: %d hours"
-msgstr "Default AKILL expiry time: %d hours"
+msgstr ""
#, c-format
msgid "Default AKILL expiry time: %d minutes"
-msgstr "Default AKILL expiry time: %d minutes"
+msgstr ""
msgid "Default AKILL expiry time: 1 day"
-msgstr "Default AKILL expiry time: 1 day"
+msgstr ""
msgid "Default AKILL expiry time: 1 hour"
-msgstr "Default AKILL expiry time: 1 hour"
+msgstr ""
msgid "Default AKILL expiry time: 1 minute"
-msgstr "Default AKILL expiry time: 1 minute"
+msgstr ""
msgid "Default AKILL expiry time: No expiration"
-msgstr "Default AKILL expiry time: No expiration"
+msgstr ""
#, c-format
msgid "Default SNLINE expiry time: %d days"
-msgstr "Default SNLINE expiry time: %d days"
+msgstr ""
#, c-format
msgid "Default SNLINE expiry time: %d hours"
-msgstr "Default SNLINE expiry time: %d hours"
+msgstr ""
#, c-format
msgid "Default SNLINE expiry time: %d minutes"
-msgstr "Default SNLINE expiry time: %d minutes"
+msgstr ""
msgid "Default SNLINE expiry time: 1 day"
-msgstr "Default SNLINE expiry time: 1 day"
+msgstr ""
msgid "Default SNLINE expiry time: 1 hour"
-msgstr "Default SNLINE expiry time: 1 hour"
+msgstr ""
msgid "Default SNLINE expiry time: 1 minute"
-msgstr "Default SNLINE expiry time: 1 minute"
+msgstr ""
msgid "Default SNLINE expiry time: No expiration"
-msgstr "Default SNLINE expiry time: No expiration"
+msgstr ""
#, c-format
msgid "Default SQLINE expiry time: %d days"
-msgstr "Default SQLINE expiry time: %d days"
+msgstr ""
#, c-format
msgid "Default SQLINE expiry time: %d hours"
-msgstr "Default SQLINE expiry time: %d hours"
+msgstr ""
#, c-format
msgid "Default SQLINE expiry time: %d minutes"
-msgstr "Default SQLINE expiry time: %d minutes"
+msgstr ""
msgid "Default SQLINE expiry time: 1 day"
-msgstr "Default SQLINE expiry time: 1 day"
+msgstr ""
msgid "Default SQLINE expiry time: 1 hour"
-msgstr "Default SQLINE expiry time: 1 hour"
+msgstr ""
msgid "Default SQLINE expiry time: 1 minute"
-msgstr "Default SQLINE expiry time: 1 minute"
+msgstr ""
msgid "Default SQLINE expiry time: No expiration"
-msgstr "Default SQLINE expiry time: No expiration"
+msgstr ""
msgid "Define messages to be randomly shown to users at logon"
-msgstr "Define messages to be randomly shown to users at logon"
+msgstr ""
msgid "Define messages to be shown to users at logon"
-msgstr "Define messages to be shown to users at logon"
+msgstr ""
msgid "Define messages to be shown to users who oper"
-msgstr "Define messages to be shown to users who oper"
+msgstr ""
msgid "Delete a memo or memos"
-msgstr "Delete a memo or memos"
+msgstr ""
msgid "Delete the vhost of another user"
-msgstr "Delete the vhost of another user"
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s %s list."
-msgstr "Deleted %d entries from %s %s list."
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s access list."
-msgstr "Deleted %d entries from %s access list."
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s autokick list."
-msgstr "Deleted %d entries from %s autokick list."
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s bad words list."
-msgstr "Deleted %d entries from %s bad words list."
+msgstr ""
#, c-format
msgid "Deleted %d entries from session-limit exception list."
-msgstr "Deleted %d entries from session-limit exception list."
+msgstr ""
#, c-format
msgid "Deleted %d entries from the %s list."
-msgstr "Deleted %d entries from the %s list."
+msgstr ""
#, c-format
msgid "Deleted %d entries from the AKILL list."
-msgstr "Deleted %d entries from the AKILL list."
+msgstr ""
+
+#, c-format
+msgid "Deleted %u entries from your message queue."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from %s access list."
-msgstr "Deleted 1 entry from %s access list."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from %s autokick list."
-msgstr "Deleted 1 entry from %s autokick list."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from %s bad words list."
-msgstr "Deleted 1 entry from %s bad words list."
+msgstr ""
msgid "Deleted 1 entry from session-limit exception list."
-msgstr "Deleted 1 entry from session-limit exception list."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from the %s list."
-msgstr "Deleted 1 entry from the %s list."
+msgstr ""
msgid "Deleted 1 entry from the AKILL list."
-msgstr "Deleted 1 entry from the AKILL list."
+msgstr ""
#, c-format
msgid "Deleted info from %s."
-msgstr "Deleted info from %s."
+msgstr ""
#, c-format
msgid "Deleted one entry from %s %s list."
-msgstr "Deleted one entry from %s %s list."
+msgstr ""
+
+msgid "Deleted one entry from your message queue."
+msgstr ""
msgid ""
"Deletes the specified memo or memos. You can supply\n"
@@ -3402,55 +2981,37 @@ msgid ""
" DEL 2-5,7-9\n"
" Deletes memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Deletes the specified memo or memos. You can supply\n"
-"multiple memo numbers or ranges of numbers instead of a\n"
-"single number, as in the second example below.\n"
-" \n"
-"If LAST is given, the last memo will be deleted.\n"
-"If ALL is given, deletes all of your memos.\n"
-" \n"
-"Examples:\n"
-" \n"
-" DEL 1\n"
-" Deletes your first memo.\n"
-" \n"
-" DEL 2-5,7-9\n"
-" Deletes memos numbered 2 through 5 and 7 through 9."
msgid ""
"Deletes the vhost assigned to the given nick from the\n"
"database."
msgstr ""
-"Deletes the vhost assigned to the given nick from the\n"
-"database."
msgid "Deletes the vhost for all nicks in a group"
-msgstr "Deletes the vhost for all nicks in a group"
+msgstr ""
msgid ""
"Deletes the vhost for all nicks in the same group as\n"
"that of the given nick."
msgstr ""
-"Deletes the vhost for all nicks in the same group as\n"
-"that of the given nick."
#, c-format
msgid "Depooled %s."
-msgstr "Depooled %s."
+msgstr ""
msgid "Description"
-msgstr "Description"
+msgstr ""
#, c-format
msgid "Description of %s changed to %s."
-msgstr "Description of %s changed to %s."
+msgstr ""
#, c-format
msgid "Description of %s unset."
-msgstr "Description of %s unset."
+msgstr ""
msgid "Disabled"
-msgstr "Disabled"
+msgstr ""
msgid ""
"Disallows anyone from using the given channel.\n"
@@ -3462,33 +3023,25 @@ msgid ""
" \n"
"Reason may be required on certain networks."
msgstr ""
-"Disallows anyone from using the given channel.\n"
-"May be cancelled by using the UNSUSPEND\n"
-"command to preserve all previous channel data/settings.\n"
-"If an expiry is given the channel will be unsuspended after\n"
-"that period of time, else the default expiry from the\n"
-"configuration is used.\n"
-" \n"
-"Reason may be required on certain networks."
#, c-format
msgid "Displayed %d records (%d total)."
-msgstr "Displayed %d records (%d total)."
+msgstr ""
#, c-format
msgid "Displayed all records (count: %d)."
-msgstr "Displayed all records (count: %d)."
+msgstr ""
#, c-format
msgid "Displayed records from %d to %d."
-msgstr "Displayed records from %d to %d."
+msgstr ""
#, c-format
msgid "Displayed records matching key %s (count: %d)."
-msgstr "Displayed records matching key %s (count: %d)."
+msgstr ""
msgid "Displays information about a given nickname"
-msgstr "Displays information about a given nickname"
+msgstr ""
msgid ""
"Displays information about the given nickname, such as\n"
@@ -3497,60 +3050,55 @@ msgid ""
"your account name is used, else your current nickname is\n"
"used."
msgstr ""
-"Displays information about the given nickname, such as\n"
-"the nick's owner, last seen address and time, and nick\n"
-"options. If no nick is given, and you are identified,\n"
-"your account name is used, else your current nickname is\n"
-"used."
msgid "Displays information about your memos"
-msgstr "Displays information about your memos"
+msgstr ""
msgid "Displays one or more vhost entries"
-msgstr "Displays one or more vhost entries"
+msgstr ""
msgid "Displays the top 10 users of a channel"
-msgstr "Displays the top 10 users of a channel"
+msgstr ""
msgid "Displays the top 10 users of the network"
-msgstr "Displays the top 10 users of the network"
+msgstr ""
msgid "Displays the top 3 users of a channel"
-msgstr "Displays the top 3 users of a channel"
+msgstr ""
msgid "Displays the top 3 users of the network"
-msgstr "Displays the top 3 users of the network"
+msgstr ""
msgid "Displays this list and give information about commands"
-msgstr "Displays this list and give information about commands"
+msgstr ""
msgid "Displays your Channel Stats"
-msgstr "Displays your Channel Stats"
+msgstr ""
msgid "Displays your Global Stats"
-msgstr "Displays your Global Stats"
+msgstr ""
msgid "Don't use AMSGs!"
-msgstr "Don't use AMSGs!"
+msgstr ""
msgid "Don't use bolds on this channel!"
-msgstr "Don't use bolds on this channel!"
+msgstr ""
msgid "Don't use colors on this channel!"
-msgstr "Don't use colors on this channel!"
+msgstr ""
msgid "Don't use italics on this channel!"
-msgstr "Don't use italics on this channel!"
+msgstr ""
msgid "Don't use reverses on this channel!"
-msgstr "Don't use reverses on this channel!"
+msgstr ""
#, c-format
msgid "Don't use the word \"%s\" on this channel!"
-msgstr "Don't use the word \"%s\" on this channel!"
+msgstr ""
msgid "Don't use underlines on this channel!"
-msgstr "Don't use underlines on this channel!"
+msgstr ""
msgid ""
"Drops the given nick from the database. Once your nickname\n"
@@ -3558,22 +3106,6 @@ msgid ""
"you may own. Any other user will be able to gain control of\n"
"this nick."
msgstr ""
-"Drops the given nick from the database. Once your nickname\n"
-"is dropped you may lose all of your access and channels that\n"
-"you may own. Any other user will be able to gain control of\n"
-"this nick."
-
-#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "E-mail address for %s changed to %s."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "E-mail address for %s unset."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "E-mail for %s is invalid."
#, c-format
msgid ""
@@ -3583,11 +3115,6 @@ msgid ""
"sent in order to avoid flooding the user. If there are\n"
"more news messages, only the most recent will be sent."
msgstr ""
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. However, no more than %d messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
#, c-format
msgid ""
@@ -3597,39 +3124,43 @@ msgid ""
"be sent in order to avoid flooding the user. If there are\n"
"more news messages, only the most recent will be sent."
msgstr ""
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. However, no more than %d messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
msgid ""
"Edits or displays the list of random news messages. When a\n"
"user connects to the network, one (and only one) of the\n"
"random news will be randomly chosen and sent to them."
msgstr ""
-"Edits or displays the list of random news messages. When a\n"
-"user connects to the network, one (and only one) of the\n"
-"random news will be randomly chosen and sent to them."
msgid "Email address"
-msgstr "Email address"
+msgstr ""
+
+#, c-format
+msgid "Email address for %s changed to %s."
+msgstr ""
+
+#, c-format
+msgid "Email address for %s unset."
+msgstr ""
+
+#, c-format
+msgid "Email for %s is invalid."
+msgstr ""
#, c-format
msgid "Email matched: %s (%s) to %s."
-msgstr "Email matched: %s (%s) to %s."
+msgstr ""
-msgid "Enable fantaisist commands"
-msgstr "Enable fantaisist commands"
+msgid "Enable fantasy commands"
+msgstr ""
msgid "Enable greet messages"
-msgstr "Enable greet messages"
+msgstr ""
msgid "Enable or disable keep modes"
-msgstr "Enable or disable keep modes"
+msgstr ""
msgid "Enabled"
-msgstr "Enabled"
+msgstr ""
#, c-format
msgid ""
@@ -3637,47 +3168,24 @@ msgid ""
"channel. When disabled, users who join the channel will\n"
"not automatically gain any status from %s."
msgstr ""
-"Enables or disables %s's autoop feature for a\n"
-"channel. When disabled, users who join the channel will\n"
-"not automatically gain any status from %s."
msgid ""
"Enables or disables keepmodes for the given channel. If keep\n"
"modes is enabled, services will remember modes set on the channel\n"
"and attempt to re-set them the next time the channel is created."
msgstr ""
-"Enables or disables keepmodes for the given channel. If keep\n"
-"modes is enabled, services will remember modes set on the channel\n"
-"and attempt to re-set them the next time the channel is created."
msgid ""
"Enables or disables keepmodes for the given nick. If keep\n"
"modes is enabled, services will remember users' usermodes\n"
"and attempt to re-set them the next time they authenticate."
msgstr ""
-"Enables or disables keepmodes for the given nick. If keep\n"
-"modes is enabled, services will remember users' usermodes\n"
-"and attempt to re-set them the next time they authenticate."
msgid ""
"Enables or disables keepmodes for your nick. If keep\n"
"modes is enabled, services will remember your usermodes\n"
"and attempt to re-set them the next time you authenticate."
msgstr ""
-"Enables or disables keepmodes for your nick. If keep\n"
-"modes is enabled, services will remember your usermodes\n"
-"and attempt to re-set them the next time you authenticate."
-
-msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
msgid ""
"Enables or disables signed kicks for a\n"
@@ -3689,14 +3197,6 @@ msgid ""
"or equal to the SIGNKICK level on the channel won't have their\n"
"kicks signed."
msgstr ""
-"Enables or disables signed kicks for a\n"
-"channel. When SIGNKICK is set, kicks issued with\n"
-"the KICK command will have the nick that used the\n"
-"command in their reason.\n"
-" \n"
-"If you use LEVEL, those who have a level that is superior\n"
-"or equal to the SIGNKICK level on the channel won't have their\n"
-"kicks signed."
#, c-format
msgid ""
@@ -3705,22 +3205,15 @@ msgid ""
"ban or remove a channel status of a user that has\n"
"a level superior or equal to theirs via %s commands."
msgstr ""
-"Enables or disables the peace option for a channel.\n"
-"When peace is set, a user won't be able to kick,\n"
-"ban or remove a channel status of a user that has\n"
-"a level superior or equal to theirs via %s commands."
msgid "Enables or disables the private option for a channel."
-msgstr "Enables or disables the private option for a channel."
+msgstr ""
msgid ""
"Enables or disables the restricted access option for a\n"
"channel. When restricted access is set, users not on the access list will\n"
"instead be kicked and banned from the channel."
msgstr ""
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
msgid ""
"Enables or disables the secure founder option for a channel.\n"
@@ -3729,20 +3222,12 @@ msgid ""
"and not those who have founder level access through\n"
"the access/qop command."
msgstr ""
-"Enables or disables the secure founder option for a channel.\n"
-"When secure founder is set, only the real founder will be\n"
-"able to drop the channel, change its founder and its successor,\n"
-"and not those who have founder level access through\n"
-"the access/qop command."
msgid ""
"Enables or disables the secure ops option for a channel.\n"
"When secure ops is set, users who are not on the access list\n"
"will not be allowed channel operator status."
msgstr ""
-"Enables or disables the secure ops option for a channel.\n"
-"When secure ops is set, users who are not on the access list\n"
-"will not be allowed channel operator status."
#, c-format
msgid ""
@@ -3752,11 +3237,6 @@ msgid ""
"last user leaves the channel, and will be restored the\n"
"next time the channel is created."
msgstr ""
-"Enables or disables the topic retention option for a\n"
-"channel. When %s is set, the topic for the\n"
-"channel will be remembered by %s even after the\n"
-"last user leaves the channel, and will be restored the\n"
-"next time the channel is created."
#, c-format
msgid ""
@@ -3780,79 +3260,60 @@ msgid ""
"Additionally, services will set or unset this mode when you\n"
"set persist on or off."
msgstr ""
-"Enables or disables the persistent channel setting.\n"
-"When persistent is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-" \n"
-"If your IRCd does not have a permanent (persistent) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-" \n"
-"If this network does not have %s enabled and does\n"
-"not have a permanent channel mode, %s will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-" \n"
-"If your IRCd has a permanent (persistent) channel mode\n"
-"and it is set or unset (for any reason, including MODE LOCK),\n"
-"persist is automatically set and unset for the channel as well.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
msgid "End of AKILL list."
-msgstr "End of AKILL list."
+msgstr ""
msgid "End of access list"
-msgstr "End of access list"
+msgstr ""
#, c-format
msgid "End of access list - %d/%d entries shown."
-msgstr "End of access list - %d/%d entries shown."
+msgstr ""
msgid "End of access list."
-msgstr "End of access list."
+msgstr ""
msgid "End of autokick list"
-msgstr "End of autokick list"
+msgstr ""
msgid "End of bad words list."
-msgstr "End of bad words list."
+msgstr ""
#, c-format
msgid "End of channel list. %u channels shown."
-msgstr "End of channel list. %u channels shown."
+msgstr ""
msgid "End of configuration."
-msgstr "End of configuration."
+msgstr ""
msgid "End of entry message list."
-msgstr "End of entry message list."
+msgstr ""
#, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "End of forbid list - %d/%d entries shown."
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr ""
msgid "End of forbid list."
-msgstr "End of forbid list."
+msgstr ""
#, c-format
msgid "End of list - %d channels shown."
-msgstr "End of list - %d channels shown."
+msgstr ""
#, c-format
msgid "End of list - %d/%d matches shown."
-msgstr "End of list - %d/%d matches shown."
+msgstr ""
msgid "End of news list."
-msgstr "End of news list."
+msgstr ""
#, c-format
msgid "End of users list. %u users shown."
-msgstr "End of users list. %u users shown."
+msgstr ""
msgid "Enforce various channel modes and set options"
-msgstr "Enforce various channel modes and set options"
+msgstr ""
msgid ""
"Enforce various channel modes and set options. The channel\n"
@@ -3869,58 +3330,45 @@ msgid ""
"kicking users affected by them, and LIMIT will kick users until the\n"
"user count drops below the channel limit, if one is set."
msgstr ""
-"Enforce various channel modes and set options. The channel\n"
-"option indicates what channel to enforce the modes and options\n"
-"on. The what option indicates what modes and options to\n"
-"enforce, and can be any of SECUREOPS, RESTRICTED, REGONLY, SSLONLY,\n"
-"BANS, or LIMIT.\n"
-" \n"
-"Use SECUREOPS to enforce the SECUREOPS option, even if it is not\n"
-"enabled. Use RESTRICTED to enforce the RESTRICTED option, also\n"
-"if it's not enabled. Use REGONLY to kick all unregistered users\n"
-"from the channel. Use SSLONLY to kick all users not using a secure\n"
-"connection from the channel. BANS will enforce bans on the channel by\n"
-"kicking users affected by them, and LIMIT will kick users until the\n"
-"user count drops below the channel limit, if one is set."
msgid "English"
-msgstr "English"
+msgstr ""
#, c-format
msgid "Entry message %i for %s deleted."
-msgstr "Entry message %i for %s deleted."
+msgstr ""
#, c-format
msgid "Entry message %s not found on channel %s."
-msgstr "Entry message %s not found on channel %s."
+msgstr ""
#, c-format
msgid "Entry message added to %s"
-msgstr "Entry message added to %s"
+msgstr ""
#, c-format
msgid "Entry message list for %s is empty."
-msgstr "Entry message list for %s is empty."
+msgstr ""
#, c-format
msgid "Entry message list for %s:"
-msgstr "Entry message list for %s:"
+msgstr ""
#, c-format
msgid "Entry messages for %s have been cleared."
-msgstr "Entry messages for %s have been cleared."
+msgstr ""
#, c-format
msgid "Error reloading configuration file: %s"
-msgstr "Error reloading configuration file: %s"
+msgstr ""
#, c-format
-msgid "Error! The vHost ident is too long, please use an ident shorter than %d characters."
-msgstr "Error! The vHost ident is too long, please use an ident shorter than %d characters."
+msgid "Error! The vhost is too long, please use a hostname shorter than %zu characters."
+msgstr ""
#, c-format
-msgid "Error! The vHost is too long, please use a hostname shorter than %d characters."
-msgstr "Error! The vHost is too long, please use a hostname shorter than %d characters."
+msgid "Error! The vident is too long, please use an ident shorter than %zu characters."
+msgstr ""
msgid ""
"Examples:\n"
@@ -3936,304 +3384,282 @@ msgid ""
" CERT LIST\n"
" Displays the current certificate list."
msgstr ""
-"Examples:\n"
-" \n"
-" CERT ADD\n"
-" Adds your current fingerprint to the certificate list and\n"
-" automatically identifies you when you connect to IRC\n"
-" using this fingerprint.\n"
-" \n"
-" CERT DEL <fingerprint>\n"
-" Removes the fingerprint <fingerprint> from your certificate list.\n"
-" \n"
-" CERT LIST\n"
-" Displays the current certificate list."
#, c-format
msgid "Exception for %s has been updated to %d."
-msgstr "Exception for %s has been updated to %d."
+msgstr ""
msgid "Expires"
-msgstr "Expires"
+msgstr ""
#, c-format
msgid "Expiry and reason updated for %s."
-msgstr "Expiry and reason updated for %s."
+msgstr ""
#, c-format
msgid "Expiry for %s updated."
-msgstr "Expiry for %s updated."
+msgstr ""
msgid "Fantasy"
-msgstr "Fantasy"
+msgstr ""
#, c-format
msgid "Fantasy mode is now off on channel %s."
-msgstr "Fantasy mode is now off on channel %s."
+msgstr ""
#, c-format
msgid "Fantasy mode is now on on channel %s."
-msgstr "Fantasy mode is now on on channel %s."
+msgstr ""
msgid "Find a user's status on a channel"
-msgstr "Find a user's status on a channel"
+msgstr ""
#, c-format
msgid "Fingerprint %s already present on %s's certificate list."
-msgstr "Fingerprint %s already present on %s's certificate list."
+msgstr ""
#, c-format
msgid "Fingerprint %s is already in use."
-msgstr "Fingerprint %s is already in use."
+msgstr ""
msgid "Flags"
-msgstr "Flags"
+msgstr ""
#, c-format
msgid "Flags for %s on %s set to +%s"
-msgstr "Flags for %s on %s set to +%s"
+msgstr ""
#, c-format
msgid "Flags list for %s"
-msgstr "Flags list for %s"
+msgstr ""
msgid "Flood kicker"
-msgstr "Flood kicker"
+msgstr ""
msgid ""
"Forbid allows you to forbid usage of certain nicknames, channels,\n"
"and email addresses. Wildcards are accepted for all entries."
msgstr ""
-"Forbid allows you to forbid usage of certain nicknames, channels,\n"
-"and email addresses. Wildcards are accepted for all entries."
msgid "Forbid list is empty."
-msgstr "Forbid list is empty."
+msgstr ""
msgid "Forbid list:"
-msgstr "Forbid list:"
+msgstr ""
#, c-format
msgid "Forbid on %s was not found."
-msgstr "Forbid on %s was not found."
+msgstr ""
msgid "Forbid usage of nicknames, channels, and emails"
-msgstr "Forbid usage of nicknames, channels, and emails"
+msgstr ""
-msgid "Force the Services databases to be updated immediately"
-msgstr "Force the Services databases to be updated immediately"
+msgid "Force the services databases to be updated immediately"
+msgstr ""
msgid "Forcefully change a user's nickname"
-msgstr "Forcefully change a user's nickname"
+msgstr ""
msgid "Forcefully changes a user's nickname from nick to newnick."
-msgstr "Forcefully changes a user's nickname from nick to newnick."
+msgstr ""
msgid "Forcefully join a user to a channel"
-msgstr "Forcefully join a user to a channel"
+msgstr ""
msgid "Forcefully join a user to a channel."
-msgstr "Forcefully join a user to a channel."
+msgstr ""
msgid "Forcefully part a user from a channel"
-msgstr "Forcefully part a user from a channel"
+msgstr ""
msgid "Forcefully part a user from a channel."
-msgstr "Forcefully part a user from a channel."
+msgstr ""
msgid "Founder"
-msgstr "Founder"
+msgstr ""
#, c-format
msgid "Founder of %s changed to %s."
-msgstr "Founder of %s changed to %s."
-
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "GETPASS command unavailable because encryption is in use."
+msgstr ""
msgid "Ghost with your nick has been killed."
-msgstr "Ghost with your nick has been killed."
-
-msgid "Give Operflags to a certain user"
-msgstr "Give Operflags to a certain user"
+msgstr ""
#, c-format
msgid ""
-"Gives %s status to the selected nick on a channel. If nick is\n"
+"Gives %s status to the selected nicks on a channel. If nick is\n"
"not given, it will %s you."
msgstr ""
-"Gives %s status to the selected nick on a channel. If nick is\n"
-"not given, it will %s you."
#, c-format
msgid "Gives you or the specified nick %s status on a channel"
-msgstr "Gives you or the specified nick %s status on a channel"
+msgstr ""
msgid "Greet"
-msgstr "Greet"
+msgstr ""
msgid "Greet message displayed on join"
-msgstr "Greet message displayed on join"
+msgstr ""
#, c-format
msgid "Greet message for %s changed to %s."
-msgstr "Greet message for %s changed to %s."
+msgstr ""
#, c-format
msgid "Greet message for %s unset."
-msgstr "Greet message for %s unset."
+msgstr ""
#, c-format
msgid "Greet mode is now off on channel %s."
-msgstr "Greet mode is now off on channel %s."
+msgstr ""
#, c-format
msgid "Greet mode is now on on channel %s."
-msgstr "Greet mode is now on on channel %s."
+msgstr ""
msgid "Helps you reset lost passwords"
-msgstr "Helps you reset lost passwords"
+msgstr ""
msgid "Hide certain pieces of nickname information"
-msgstr "Hide certain pieces of nickname information"
+msgstr ""
msgid "Hide channel from the LIST command"
-msgstr "Hide channel from the LIST command"
+msgstr ""
msgid "Host"
-msgstr "Host"
+msgstr ""
#, c-format
msgid "Hosts with at least %d sessions:"
-msgstr "Hosts with at least %d sessions:"
+msgstr ""
#, c-format
msgid "I don't know who %s is."
-msgstr "I don't know who %s is."
+msgstr ""
#, c-format
msgid "I've never seen %s on this channel."
-msgstr "I've never seen %s on this channel."
+msgstr ""
msgid "ID"
-msgstr "ID"
+msgstr ""
msgid "INFO [type]"
-msgstr "INFO [type]"
+msgstr ""
msgid "IP"
-msgstr "IP"
+msgstr ""
#, c-format
msgid "IP %s already exists for %s."
-msgstr "IP %s already exists for %s."
+msgstr ""
#, c-format
msgid "IP %s does not exist for %s."
-msgstr "IP %s does not exist for %s."
+msgstr ""
msgid "Identify yourself with your password"
-msgstr "Identify yourself with your password"
+msgstr ""
#, c-format
msgid "If you do not change within %s, I will change your nick."
-msgstr "If you do not change within %s, I will change your nick."
+msgstr ""
msgid "Ignore list has been cleared."
-msgstr "Ignore list has been cleared."
+msgstr ""
msgid "Ignore list is empty."
-msgstr "Ignore list is empty."
+msgstr ""
msgid "Ignore list:"
-msgstr "Ignore list:"
+msgstr ""
msgid "Immediate protection"
-msgstr "Immediate protection"
+msgstr ""
msgid "Incorrect email address."
-msgstr "Incorrect email address."
+msgstr ""
msgid "Incorrect range specified. The correct syntax is #from-to."
-msgstr "Incorrect range specified. The correct syntax is #from-to."
+msgstr ""
msgid "Info about a loaded module"
-msgstr "Info about a loaded module"
+msgstr ""
#, c-format
-msgid "Information for bot %s:"
-msgstr "Information for bot %s:"
+msgid "Information about bot %s:"
+msgstr ""
#, c-format
-msgid "Information for channel %s:"
-msgstr "Information for channel %s:"
+msgid "Information about channel %s:"
+msgstr ""
#, c-format
msgid "Invalid duration %s, using %d days."
-msgstr "Invalid duration %s, using %d days."
+msgstr ""
msgid "Invalid expiry time."
-msgstr "Invalid expiry time."
+msgstr ""
msgid "Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames."
-msgstr "Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames."
+msgstr ""
#, c-format
msgid "Invalid limit %s, using %d."
-msgstr "Invalid limit %s, using %d."
+msgstr ""
-msgid "Invalid passcode has been entered, please check the e-mail again, and retry."
-msgstr "Invalid passcode has been entered, please check the e-mail again, and retry."
+msgid "Invalid passcode has been entered, please check the email again, and retry."
+msgstr ""
msgid "Invalid passcode."
-msgstr "Invalid passcode."
+msgstr ""
#, c-format
msgid "Invalid session limit. It must be a valid integer greater than or equal to zero and less than %d."
-msgstr "Invalid session limit. It must be a valid integer greater than or equal to zero and less than %d."
+msgstr ""
msgid "Invalid threshold value. It must be a valid integer greater than 1."
-msgstr "Invalid threshold value. It must be a valid integer greater than 1."
+msgstr ""
msgid "Invalid value for LIMIT. Must be numerical."
-msgstr "Invalid value for LIMIT. Must be numerical."
+msgstr ""
msgid "Invites you or an optionally specified nick into a channel"
-msgstr "Invites you or an optionally specified nick into a channel"
+msgstr ""
msgid "Italics kicker"
-msgstr "Italics kicker"
+msgstr ""
msgid "Join a group"
-msgstr "Join a group"
+msgstr ""
msgid "Keep modes"
-msgstr "Keep modes"
+msgstr ""
#, c-format
msgid "Keep modes for %s is now off."
-msgstr "Keep modes for %s is now off."
+msgstr ""
#, c-format
msgid "Keep modes for %s is now on."
-msgstr "Keep modes for %s is now on."
+msgstr ""
msgid "Key"
-msgstr "Key"
+msgstr ""
#, c-format
msgid "Key for channel %s is %s."
-msgstr "Key for channel %s is %s."
+msgstr ""
msgid "Kick a user from a channel"
-msgstr "Kick a user from a channel"
+msgstr ""
#, c-format
msgid "Kicked %d/%d users matching %s from %s."
-msgstr "Kicked %d/%d users matching %s from %s."
+msgstr ""
msgid "Kicks a specified nick from a channel"
-msgstr "Kicks a specified nick from a channel"
+msgstr ""
msgid ""
"Kicks a specified nick from a channel.\n"
@@ -4241,119 +3667,121 @@ msgid ""
"By default, limited to AOPs or those with level 5 access\n"
"and above on the channel. Channel founders can also specify masks."
msgstr ""
-"Kicks a specified nick from a channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders can also specify masks."
msgid "Kill a user"
-msgstr "Kill a user"
+msgstr ""
msgid "LIMIT enforced by "
-msgstr "LIMIT enforced by "
+msgstr ""
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr "LIMIT enforced on %s, %d users removed."
+msgid "LIMIT enforced on %s, %zu users removed."
+msgstr ""
msgid "LIST threshold"
-msgstr "LIST threshold"
+msgstr ""
msgid "LIST [mask | list | id]"
-msgstr "LIST [mask | list | id]"
+msgstr ""
msgid "LIST [mask | list]"
-msgstr "LIST [mask | list]"
+msgstr ""
msgid "LIST [nickname]"
-msgstr "LIST [nickname]"
+msgstr ""
msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "LOGONNEWS {ADD|DEL|LIST} [text|num]"
+msgstr ""
-msgid "Language changed to English."
-msgstr "Language changed to English."
+#, c-format
+msgid "Language changed to %s."
+msgstr ""
#, c-format
msgid "Language for %s changed to %s."
-msgstr "Language for %s changed to %s."
+msgstr ""
#, c-format
msgid "Last memo to %s has been cancelled."
-msgstr "Last memo to %s has been cancelled."
+msgstr ""
msgid "Last quit message"
-msgstr "Last quit message"
+msgstr ""
msgid "Last seen"
-msgstr "Last seen"
+msgstr ""
msgid "Last seen address"
-msgstr "Last seen address"
+msgstr ""
msgid "Last topic"
-msgstr "Last topic"
+msgstr ""
msgid "Last used"
-msgstr "Last used"
+msgstr ""
msgid "Last usermask"
-msgstr "Last usermask"
+msgstr ""
msgid "Level"
-msgstr "Level"
+msgstr ""
#, c-format
msgid "Level for %s on channel %s changed to %d."
-msgstr "Level for %s on channel %s changed to %d."
+msgstr ""
#, c-format
msgid "Level for %s on channel %s changed to founder only."
-msgstr "Level for %s on channel %s changed to founder only."
+msgstr ""
#, c-format
msgid "Level must be between %d and %d inclusive."
-msgstr "Level must be between %d and %d inclusive."
+msgstr ""
msgid "Limit"
-msgstr "Limit"
+msgstr ""
msgid "List all registered nicknames that match a given pattern"
-msgstr "List all registered nicknames that match a given pattern"
+msgstr ""
msgid "List channels you have access on"
-msgstr "List channels you have access on"
+msgstr ""
#, c-format
msgid "List for mode %c is full."
-msgstr "List for mode %c is full."
+msgstr ""
msgid "List loaded modules"
-msgstr "List loaded modules"
+msgstr ""
#, c-format
msgid "List of entries matching %s:"
-msgstr "List of entries matching %s:"
+msgstr ""
#, c-format
msgid "List of nicknames in the group of %s:"
-msgstr "List of nicknames in the group of %s:"
+msgstr ""
msgid "List of nicknames in your group:"
-msgstr "List of nicknames in your group:"
+msgstr ""
msgid "List your memos"
-msgstr "List your memos"
+msgstr ""
msgid ""
"Lists all available bots on this network.\n"
-"Bots prefixed by a * are reserved for IRC Operators."
+"\n"
+"If the OPERONLY, UNUSED or VANITY options are given only\n"
+"bots which, respectively, are oper-only, unused or were\n"
+"added at runtime will be displayed. If multiple options are\n"
+"given, all nicks matching at least one option will be\n"
+"displayed.\n"
+"\n"
+"Note that these options are limited to Services Operators."
msgstr ""
-"Lists all available bots on this network.\n"
-"Bots prefixed by a * are reserved for IRC Operators."
msgid "Lists all channel records"
-msgstr "Lists all channel records"
+msgstr ""
msgid ""
"Lists all channels currently in use on the IRC network, whether they\n"
@@ -4364,13 +3792,6 @@ msgid ""
"specified, lists only channels matching pattern that have the +s or\n"
"+p mode."
msgstr ""
-"Lists all channels currently in use on the IRC network, whether they\n"
-"are registered or not.\n"
-" \n"
-"If pattern is given, lists only channels that match it. If a nickname\n"
-"is given, lists only the channels the user using it is on. If SECRET is\n"
-"specified, lists only channels matching pattern that have the +s or\n"
-"+p mode."
msgid ""
"Lists all channels you have access on.\n"
@@ -4379,17 +3800,12 @@ msgid ""
"prefixed by an exclamation mark. The nickname parameter is\n"
"limited to Services Operators"
msgstr ""
-"Lists all channels you have access on.\n"
-" \n"
-"Channels that have the NOEXPIRE option set will be\n"
-"prefixed by an exclamation mark. The nickname parameter is\n"
-"limited to Services Operators"
msgid "Lists all nicknames in your group"
-msgstr "Lists all nicknames in your group"
+msgstr ""
msgid "Lists all registered channels matching the given pattern"
-msgstr "Lists all registered channels matching the given pattern"
+msgstr ""
msgid ""
"Lists all registered channels matching the given pattern.\n"
@@ -4419,32 +3835,6 @@ msgid ""
" LIST #51-100\n"
" Lists all registered channels within the given range (51-100)."
msgstr ""
-"Lists all registered channels matching the given pattern.\n"
-"Channels with the PRIVATE option set will only be\n"
-"displayed to Services Operators with the proper access.\n"
-"Channels with the NOEXPIRE option set will have\n"
-"a ! prefixed to the channel for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range, channel names\n"
-"are to be written without '#'.\n"
-" \n"
-"If the SUSPENDED or NOEXPIRE options are given, only channels\n"
-"which, respectively, are SUSPENDED or have the NOEXPIRE\n"
-"flag set will be displayed. If multiple options are given,\n"
-"all channels matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *anope*\n"
-" Lists all registered channels with anope in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered channels which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered channels within the given range (51-100)."
msgid ""
"Lists all registered nicknames which match the given\n"
@@ -4476,37 +3866,9 @@ msgid ""
" LIST #51-100\n"
" Lists all registered nicks within the given range (51-100)."
msgstr ""
-"Lists all registered nicknames which match the given\n"
-"pattern, in nick!user@host format. Nicks with the PRIVATE\n"
-"option set will only be displayed to Services Operators with the\n"
-"proper access. Nicks with the NOEXPIRE option set will have\n"
-"a ! prefixed to the nickname for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range.\n"
-" \n"
-"If the SUSPENDED, UNCONFIRMED or NOEXPIRE options are given, only\n"
-"nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n"
-"NOEXPIRE flag set will be displayed. If multiple options are\n"
-"given, all nicks matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *!joeuser@foo.com\n"
-" Lists all registered nicks owned by joeuser@foo.com.\n"
-" \n"
-" LIST *Bot*!*@*\n"
-" Lists all registered nicks with Bot in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered nicks which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered nicks within the given range (51-100)."
msgid "Lists all user records"
-msgstr "Lists all user records"
+msgstr ""
msgid ""
"Lists all users currently online on the IRC network, whether their\n"
@@ -4517,13 +3879,6 @@ msgid ""
"only users that are on the given channel. If INVISIBLE is specified, only users\n"
"with the +i flag will be listed."
msgstr ""
-"Lists all users currently online on the IRC network, whether their\n"
-"nick is registered or not.\n"
-" \n"
-"If pattern is given, lists only users that match it (it must be in\n"
-"the format nick!user@host[#realname]). If channel is given, lists\n"
-"only users that are on the given channel. If INVISIBLE is specified, only users\n"
-"with the +i flag will be listed."
msgid ""
"Lists any memos you currently have. With NEW, lists only\n"
@@ -4533,21 +3888,15 @@ msgid ""
" LIST 2-5,7-9\n"
" Lists memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Lists any memos you currently have. With NEW, lists only\n"
-"new (unread) memos. Unread memos are marked with a \"*\"\n"
-"to the left of the memo number. You can also specify a list\n"
-"of numbers, as in the example below:\n"
-" LIST 2-5,7-9\n"
-" Lists memos numbered 2 through 5 and 7 through 9."
msgid "Lists available bots"
-msgstr "Lists available bots"
+msgstr ""
msgid "Lists currently loaded modules."
-msgstr "Lists currently loaded modules."
+msgstr ""
msgid "Lists information about the specified registered channel"
-msgstr "Lists information about the specified registered channel"
+msgstr ""
msgid ""
"Lists information about the specified registered channel,\n"
@@ -4557,53 +3906,47 @@ msgid ""
"successor, last topic set, settings and expiration\n"
"time will also be displayed when applicable."
msgstr ""
-"Lists information about the specified registered channel,\n"
-"including its founder, time of registration, last\n"
-"time used, and description. If the user issuing the\n"
-"command has the appropriate access for it, then the\n"
-"successor, last topic set, settings and expiration\n"
-"time will also be displayed when applicable."
msgid "Load a module"
-msgstr "Load a module"
+msgstr ""
msgid "Local channels cannot be registered."
-msgstr "Local channels cannot be registered."
+msgstr ""
#, c-format
msgid "Log list for %s:"
-msgstr "Log list for %s:"
+msgstr ""
#, c-format
msgid "Logging changed for command %s on %s, now using log method %s%s%s."
-msgstr "Logging changed for command %s on %s, now using log method %s%s%s."
+msgstr ""
#, c-format
msgid "Logging for command %s on %s with log method %s%s%s has been removed."
-msgstr "Logging for command %s on %s with log method %s%s%s has been removed."
+msgstr ""
#, c-format
msgid "Logging is now active for command %s on %s, using log method %s%s%s."
-msgstr "Logging is now active for command %s on %s, using log method %s%s%s."
+msgstr ""
#, c-format
msgid "Login to %s"
-msgstr "Login to %s"
+msgstr ""
#, c-format
msgid "Logon news item #%d deleted."
-msgstr "Logon news item #%d deleted."
+msgstr ""
#, c-format
msgid "Logon news item #%s not found!"
-msgstr "Logon news item #%s not found!"
+msgstr ""
msgid "Logon news items:"
-msgstr "Logon news items:"
+msgstr ""
#, c-format
msgid "Logout from %s"
-msgstr "Logout from %s"
+msgstr ""
#, c-format
msgid ""
@@ -4611,9 +3954,6 @@ msgid ""
"This command may be unnecessary if your oper block is\n"
"configured without a password."
msgstr ""
-"Logs you in to %s so you gain Services Operator privileges.\n"
-"This command may be unnecessary if your oper block is\n"
-"configured without a password."
#, c-format
msgid ""
@@ -4621,13 +3961,10 @@ msgid ""
"This command is only useful if your oper block is configured\n"
"with a password."
msgstr ""
-"Logs you out from %s so you lose Services Operator privileges.\n"
-"This command is only useful if your oper block is configured\n"
-"with a password."
#, c-format
msgid "Looking for yourself, eh %s?"
-msgstr "Looking for yourself, eh %s?"
+msgstr ""
#, c-format
msgid ""
@@ -4654,34 +3991,12 @@ msgid ""
"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If what\n"
"is not given then all basic modes are removed."
msgstr ""
-"Mainly controls mode locks and mode access (which is different from channel access)\n"
-"on a channel.\n"
-" \n"
-"The %s LOCK command allows you to add, delete, and view mode locks on a channel.\n"
-"If a mode is locked on or off, services will not allow that mode to be changed. The SET\n"
-"command will clear all existing mode locks and set the new one given, while ADD and DEL\n"
-"modify the existing mode lock.\n"
-"Example:\n"
-" MODE #channel LOCK ADD +bmnt *!*@*aol*\n"
-" \n"
-"The %s SET command allows you to set modes through services. Wildcards * and ? may\n"
-"be given as parameters for list and status modes.\n"
-"Example:\n"
-" MODE #channel SET +v *\n"
-" Sets voice status to all users in the channel.\n"
-" \n"
-" MODE #channel SET -b ~c:*\n"
-" Clears all extended bans that start with ~c:\n"
-" \n"
-"The %s CLEAR command is an easy way to clear modes on a channel. what may be\n"
-"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If what\n"
-"is not given then all basic modes are removed."
msgid "Maintain the AutoKick list"
-msgstr "Maintain the AutoKick list"
+msgstr ""
msgid "Maintains network bot list"
-msgstr "Maintains network bot list"
+msgstr ""
#, c-format
msgid ""
@@ -4689,9 +4004,6 @@ msgid ""
"on the %s list receive the following privileges:\n"
" "
msgstr ""
-"Maintains the %s list for a channel. Users who match an access entry\n"
-"on the %s list receive the following privileges:\n"
-" "
#, c-format
msgid ""
@@ -4709,19 +4021,6 @@ msgid ""
"will be added to the akick list instead of the mask.\n"
"All users within that nickgroup will then be akicked.\n"
msgstr ""
-"Maintains the AutoKick list for a channel. If a user\n"
-"on the AutoKick list attempts to join the channel,\n"
-"%s will ban that user from the channel, then kick\n"
-"the user.\n"
-" \n"
-"The AKICK ADD command adds the given nick or usermask\n"
-"to the AutoKick list. If a reason is given with\n"
-"the command, that reason will be used when the user is\n"
-"kicked; if not, the default reason is \"User has been\n"
-"banned from the channel\".\n"
-"When akicking a registered nick the %s account\n"
-"will be added to the akick list instead of the mask.\n"
-"All users within that nickgroup will then be akicked.\n"
#, c-format
msgid ""
@@ -4733,20 +4032,13 @@ msgid ""
"a user level of 0, and any unregistered user has a user level\n"
"of -1."
msgstr ""
-"Maintains the access list for a channel. The access\n"
-"list specifies which users are allowed chanop status or\n"
-"access to %s commands on the channel. Different\n"
-"user levels allow for access to different subsets of\n"
-"privileges. Any registered user not on the access list has\n"
-"a user level of 0, and any unregistered user has a user level\n"
-"of -1."
#, c-format
msgid ""
"Maintains the bad words list for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
+"type %s HELP KICK %s.\n"
" \n"
"The ADD command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -4758,39 +4050,23 @@ msgid ""
"be issued every time word is said by a user.\n"
" \n"
msgstr ""
-"Maintains the bad words list for a channel. The bad\n"
-"words list determines which words are to be kicked\n"
-"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
-" \n"
-"The ADD command adds the given word to the\n"
-"bad words list. If SINGLE is specified, a kick will be\n"
-"done only if a user says the entire word. If START is\n"
-"specified, a kick will be done if a user says a word\n"
-"that starts with word. If END is specified, a kick\n"
-"will be done if a user says a word that ends with\n"
-"word. If you don't specify anything, a kick will\n"
-"be issued every time word is said by a user.\n"
-" \n"
msgid "Maintains the bad words list"
-msgstr "Maintains the bad words list"
+msgstr ""
msgid "Makes the bot do the equivalent of a \"/me\" command"
-msgstr "Makes the bot do the equivalent of a \"/me\" command"
+msgstr ""
msgid ""
"Makes the bot do the equivalent of a \"/me\" command\n"
"on the specified channel using the specified text."
msgstr ""
-"Makes the bot do the equivalent of a \"/me\" command\n"
-"on the specified channel using the specified text."
msgid "Makes the bot say the specified text on the specified channel"
-msgstr "Makes the bot say the specified text on the specified channel"
+msgstr ""
msgid "Makes the bot say the specified text on the specified channel."
-msgstr "Makes the bot say the specified text on the specified channel."
+msgstr ""
msgid ""
"Makes the given message the greet of the nickname, that\n"
@@ -4798,10 +4074,6 @@ msgid ""
"option enabled, provided that the user has the necessary\n"
"access on it."
msgstr ""
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary\n"
-"access on it."
msgid ""
"Makes the given message the greet of your nickname, that\n"
@@ -4809,170 +4081,131 @@ msgid ""
"option enabled, provided that you have the necessary\n"
"access on it."
msgstr ""
-"Makes the given message the greet of your nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that you have the necessary\n"
-"access on it."
msgid "Manage DNS zones for this network"
-msgstr "Manage DNS zones for this network"
+msgstr ""
msgid "Manage the channel's entry messages"
-msgstr "Manage the channel's entry messages"
+msgstr ""
msgid "Manage the memo ignore list"
-msgstr "Manage the memo ignore list"
+msgstr ""
msgid "Manage your auto join list"
-msgstr "Manage your auto join list"
+msgstr ""
+
+msgid "Manages your pending message queue."
+msgstr ""
#, c-format
msgid "Manipulate the %s list"
-msgstr "Manipulate the %s list"
+msgstr ""
msgid "Manipulate the AKILL list"
-msgstr "Manipulate the AKILL list"
+msgstr ""
msgid "Manipulate the DefCon system"
-msgstr "Manipulate the DefCon system"
+msgstr ""
msgid "Manipulate the topic of the specified channel"
-msgstr "Manipulate the topic of the specified channel"
+msgstr ""
msgid "Mask"
-msgstr "Mask"
-
-#, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "Mask %s already present on %s's access list."
+msgstr ""
msgid "Mask must be in the form user@host."
-msgstr "Mask must be in the form user@host."
+msgstr ""
msgid "Masks and unregistered users may not be on access lists."
-msgstr "Masks and unregistered users may not be on access lists."
+msgstr ""
msgid "Matches and returns all users that registered using given email"
-msgstr "Matches and returns all users that registered using given email"
+msgstr ""
#, c-format
msgid "Matches for %s:"
-msgstr "Matches for %s:"
+msgstr ""
#, c-format
msgid "Maximum users: %d (%s)"
-msgstr "Maximum users: %d (%s)"
+msgstr ""
#, c-format
msgid "Memo %d from %s (%s)."
-msgstr "Memo %d from %s (%s)."
+msgstr ""
#, c-format
msgid "Memo %d has been deleted."
-msgstr "Memo %d has been deleted."
+msgstr ""
+
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr ""
msgid "Memo ignore list is empty."
-msgstr "Memo ignore list is empty."
+msgstr ""
#, c-format
msgid "Memo limit disabled for %s."
-msgstr "Memo limit disabled for %s."
+msgstr ""
#, c-format
msgid "Memo limit for %s set to %d."
-msgstr "Memo limit for %s set to %d."
+msgstr ""
#, c-format
msgid "Memo limit for %s set to 0."
-msgstr "Memo limit for %s set to 0."
+msgstr ""
#, c-format
msgid "Memo sent to %s."
-msgstr "Memo sent to %s."
+msgstr ""
#, c-format
msgid "Memos for %s:"
-msgstr "Memos for %s:"
+msgstr ""
msgid "Message"
-msgstr "Message"
+msgstr ""
msgid "Message mode"
-msgstr "Message mode"
+msgstr ""
msgid "Method"
-msgstr "Method"
+msgstr ""
#, c-format
msgid "Missing parameter for mode %c."
-msgstr "Missing parameter for mode %c."
+msgstr ""
+
+#, c-format
+msgid "Missing passwords: %zu"
+msgstr ""
msgid "Mode"
-msgstr "Mode"
+msgstr ""
#, c-format
msgid "Mode %s is a virtual mode and can't be cleared."
-msgstr "Mode %s is a virtual mode and can't be cleared."
+msgstr ""
#, c-format
msgid "Mode %s is not a status or list mode."
-msgstr "Mode %s is not a status or list mode."
+msgstr ""
msgid "Mode lock"
-msgstr "Mode lock"
+msgstr ""
#, c-format
msgid "Mode locks for %s:"
-msgstr "Mode locks for %s:"
+msgstr ""
msgid "Modes"
-msgstr "Modes"
+msgstr ""
#, c-format
msgid "Modes cleared on %s and the channel destroyed."
-msgstr "Modes cleared on %s and the channel destroyed."
-
-#, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
msgstr ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
msgid ""
"Modifies or displays the certificate list for your nick.\n"
@@ -4982,309 +4215,309 @@ msgid ""
"may provide a nick to modify other users' certificate lists.\n"
" \n"
msgstr ""
-"Modifies or displays the certificate list for your nick.\n"
-"If you connect to IRC and provide a client certificate with a\n"
-"matching fingerprint in the cert list, you will be\n"
-"automatically identified to services. Services Operators\n"
-"may provide a nick to modify other users' certificate lists.\n"
-" \n"
-
-msgid "Modify the Services ignore list"
-msgstr "Modify the Services ignore list"
#, c-format
msgid "Modify the list of %s users"
-msgstr "Modify the list of %s users"
-
-msgid "Modify the list of authorized addresses"
-msgstr "Modify the list of authorized addresses"
+msgstr ""
msgid "Modify the list of privileged users"
-msgstr "Modify the list of privileged users"
+msgstr ""
msgid "Modify the nickname client certificate list"
-msgstr "Modify the nickname client certificate list"
+msgstr ""
+
+msgid "Modify the services ignore list"
+msgstr ""
msgid "Modify the session-limit exception list"
-msgstr "Modify the session-limit exception list"
+msgstr ""
#, c-format
msgid "Module %s is already loaded."
-msgstr "Module %s is already loaded."
+msgstr ""
#, c-format
msgid "Module %s isn't loaded."
-msgstr "Module %s isn't loaded."
+msgstr ""
#, c-format
msgid "Module %s loaded."
-msgstr "Module %s loaded."
+msgstr ""
#, c-format
msgid "Module %s reloaded."
-msgstr "Module %s reloaded."
+msgstr ""
#, c-format
msgid "Module %s unloaded."
-msgstr "Module %s unloaded."
+msgstr ""
msgid "Module Name"
-msgstr "Module Name"
+msgstr ""
msgid "Module settings:"
-msgstr "Module settings:"
+msgstr ""
#, c-format
msgid "Module: %s Version: %s Author: %s Loaded: %s"
-msgstr "Module: %s Version: %s Author: %s Loaded: %s"
+msgstr ""
#, c-format
msgid "Module: %s [%s] [%s]"
-msgstr "Module: %s [%s] [%s]"
+msgstr ""
+
+#, c-format
+msgid "Multiple languages matched %s. Please be more specific."
+msgstr ""
msgid "Name"
-msgstr "Name"
+msgstr ""
msgid "Name Type"
-msgstr "Name Type"
+msgstr ""
#, c-format
msgid "Network stats for %s:"
-msgstr "Network stats for %s:"
+msgstr ""
msgid "Never"
-msgstr "Never"
+msgstr ""
+
+msgid "Never-op"
+msgstr ""
msgid "Nick"
-msgstr "Nick"
+msgstr ""
#, c-format
msgid "Nick %s has been confirmed."
-msgstr "Nick %s has been confirmed."
+msgstr ""
#, c-format
msgid "Nick %s is already an operator."
-msgstr "Nick %s is already an operator."
+msgstr ""
#, c-format
msgid "Nick %s is already confirmed."
-msgstr "Nick %s is already confirmed."
+msgstr ""
#, c-format
msgid "Nick %s is an illegal nickname and cannot be used."
-msgstr "Nick %s is an illegal nickname and cannot be used."
+msgstr ""
#, c-format
msgid "Nick %s is currently in use."
-msgstr "Nick %s is currently in use."
+msgstr ""
#, c-format
msgid "Nick %s is forbidden by %s: %s"
-msgstr "Nick %s is forbidden by %s: %s"
+msgstr ""
#, c-format
msgid "Nick %s is forbidden."
-msgstr "Nick %s is forbidden."
+msgstr ""
#, c-format
msgid "Nick %s is not a Services Operator."
-msgstr "Nick %s is not a Services Operator."
+msgstr ""
#, c-format
msgid "Nick %s is part of this Network's Services."
-msgstr "Nick %s is part of this Network's Services."
+msgstr ""
#, c-format
msgid "Nick %s isn't currently in use."
-msgstr "Nick %s isn't currently in use."
+msgstr ""
#, c-format
msgid "Nick %s isn't registered."
-msgstr "Nick %s isn't registered."
+msgstr ""
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Nick %s was truncated to %d characters."
+msgid "Nick %s was truncated to %zu characters."
+msgstr ""
#, c-format
msgid "Nick %s will expire."
-msgstr "Nick %s will expire."
+msgstr ""
#, c-format
msgid "Nick %s will not expire."
-msgstr "Nick %s will not expire."
+msgstr ""
#, c-format
msgid "Nick %s doesn't have a memo from you."
-msgstr "Nick %s doesn't have a memo from you."
+msgstr ""
#, c-format
msgid "Nick %s has been logged out."
-msgstr "Nick %s has been logged out."
+msgstr ""
#, c-format
msgid "Nick %s has been ungrouped from %s."
-msgstr "Nick %s has been ungrouped from %s."
+msgstr ""
#, c-format
msgid "Nick %s is currently suspended."
-msgstr "Nick %s is currently suspended."
+msgstr ""
#, c-format
msgid "Nick %s is not in your group."
-msgstr "Nick %s is not in your group."
+msgstr ""
#, c-format
msgid "Nick %s is not suspended."
-msgstr "Nick %s is not suspended."
+msgstr ""
#, c-format
msgid "Nick %s is now released."
-msgstr "Nick %s is now released."
+msgstr ""
#, c-format
msgid "Nick %s is now suspended."
-msgstr "Nick %s is now suspended."
+msgstr ""
+
+msgid "Nick registered"
+msgstr ""
#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr "Nick too long, max length is %u characters."
+msgid "Nick too long, max length is %zu characters."
+msgstr ""
#, c-format
msgid "Nickname %s has been dropped."
-msgstr "Nickname %s has been dropped."
+msgstr ""
#, c-format
msgid "Nickname %s is already registered!"
-msgstr "Nickname %s is already registered!"
+msgstr ""
#, c-format
msgid "Nickname %s may not be registered."
-msgstr "Nickname %s may not be registered."
-
-#, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr "Nickname %s registered under your user@host-mask: %s"
+msgstr ""
#, c-format
msgid "Nickname %s registered."
-msgstr "Nickname %s registered."
+msgstr ""
msgid "No auto-op"
-msgstr "No auto-op"
+msgstr ""
msgid "No bot"
-msgstr "No bot"
+msgstr ""
msgid "No expire"
-msgstr "No expire"
+msgstr ""
#, c-format
msgid "No help available for %s."
-msgstr "No help available for %s."
+msgstr ""
#, c-format
msgid "No information about module %s is available."
-msgstr "No information about module %s is available."
+msgstr ""
#, c-format
msgid "No limit is set on %s."
-msgstr "No limit is set on %s."
+msgstr ""
msgid "No logon news items to delete!"
-msgstr "No logon news items to delete!"
+msgstr ""
#, c-format
msgid "No matches for %s found."
-msgstr "No matches for %s found."
+msgstr ""
+
+msgid "No matching entries in your message queue."
+msgstr ""
#, c-format
msgid "No matching entries on %s %s list."
-msgstr "No matching entries on %s %s list."
+msgstr ""
#, c-format
msgid "No matching entries on %s access list."
-msgstr "No matching entries on %s access list."
+msgstr ""
#, c-format
msgid "No matching entries on %s autokick list."
-msgstr "No matching entries on %s autokick list."
+msgstr ""
#, c-format
msgid "No matching entries on %s bad words list."
-msgstr "No matching entries on %s bad words list."
+msgstr ""
msgid "No matching entries on session-limit exception list."
-msgstr "No matching entries on session-limit exception list."
+msgstr ""
#, c-format
msgid "No matching entries on the %s list."
-msgstr "No matching entries on the %s list."
+msgstr ""
msgid "No matching entries on the AKILL list."
-msgstr "No matching entries on the AKILL list."
+msgstr ""
msgid "No memo was cancelable."
-msgstr "No memo was cancelable."
+msgstr ""
msgid "No memos to display."
-msgstr "No memos to display."
+msgstr ""
msgid "No modules currently loaded matching that criteria."
-msgstr "No modules currently loaded matching that criteria."
+msgstr ""
msgid "No one is using your nick, and services are not holding it."
-msgstr "No one is using your nick, and services are not holding it."
+msgstr ""
msgid "No oper block for your nick."
-msgstr "No oper block for your nick."
+msgstr ""
msgid "No oper news items to delete!"
-msgstr "No oper news items to delete!"
+msgstr ""
msgid "No random news items to delete!"
-msgstr "No random news items to delete!"
+msgstr ""
msgid "No records to display."
-msgstr "No records to display."
+msgstr ""
#, c-format
msgid "No registrations matching %s were found."
-msgstr "No registrations matching %s were found."
+msgstr ""
#, c-format
msgid "No request for nick %s found."
-msgstr "No request for nick %s found."
+msgstr ""
msgid "No signed kick when SIGNKICK LEVEL is used"
-msgstr "No signed kick when SIGNKICK LEVEL is used"
+msgstr ""
#, c-format
msgid "No stats for %s."
-msgstr "No stats for %s."
+msgstr ""
#, c-format
msgid "No such info \"%s\" on %s."
-msgstr "No such info \"%s\" on %s."
+msgstr ""
#, c-format
msgid "No users on %s match %s."
-msgstr "No users on %s match %s."
+msgstr ""
#, c-format
msgid "No-bot mode is now off on channel %s."
-msgstr "No-bot mode is now off on channel %s."
+msgstr ""
#, c-format
msgid "No-bot mode is now on on channel %s."
-msgstr "No-bot mode is now on on channel %s."
+msgstr ""
#, c-format
msgid "Non-status modes cleared on %s."
-msgstr "Non-status modes cleared on %s."
+msgstr ""
msgid "None"
-msgstr "None"
+msgstr ""
#, c-format
msgid ""
@@ -5293,297 +4526,282 @@ msgid ""
"become the new founder and it will be as if the\n"
"channel had no successor set."
msgstr ""
-"Note, however, if the successor already has too many\n"
-"channels registered (%d), they will not be able to\n"
-"become the new founder and it will be as if the\n"
-"channel had no successor set."
msgid "Nothing to do."
-msgstr "Nothing to do."
+msgstr ""
msgid "Number"
-msgstr "Number"
+msgstr ""
msgid "OPERNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "OPERNEWS {ADD|DEL|LIST} [text|num]"
+msgstr ""
msgid "Online from"
-msgstr "Online from"
+msgstr ""
#, c-format
msgid "Oper %s is configured in the configuration file(s) and can not be removed by this command."
-msgstr "Oper %s is configured in the configuration file(s) and can not be removed by this command."
+msgstr ""
msgid "Oper Info"
-msgstr "Oper Info"
+msgstr ""
#, c-format
msgid "Oper info list for %s is empty."
-msgstr "Oper info list for %s is empty."
+msgstr ""
#, c-format
msgid "Oper news item #%d deleted."
-msgstr "Oper news item #%d deleted."
+msgstr ""
#, c-format
msgid "Oper news item #%s not found!"
-msgstr "Oper news item #%s not found!"
+msgstr ""
msgid "Oper news items:"
-msgstr "Oper news items:"
+msgstr ""
#, c-format
msgid "Oper privileges removed from %s (%s)."
-msgstr "Oper privileges removed from %s (%s)."
+msgstr ""
#, c-format
msgid "Oper type %s has not been configured."
-msgstr "Oper type %s has not been configured."
-
-#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "Operflags %s have been added for %s."
-
-#, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "Operflags %s have been removed from %s."
+msgstr ""
#, c-format
msgid "Opertype %s has no allowed commands."
-msgstr "Opertype %s has no allowed commands."
+msgstr ""
#, c-format
msgid "Opertype %s has no allowed privileges."
-msgstr "Opertype %s has no allowed privileges."
+msgstr ""
#, c-format
msgid "Opertype %s receives modes %s once identified."
-msgstr "Opertype %s receives modes %s once identified."
+msgstr ""
msgid "Ops protection"
-msgstr "Ops protection"
+msgstr ""
msgid "Options"
-msgstr "Options"
+msgstr ""
msgid "POOL server.name"
-msgstr "POOL server.name"
+msgstr ""
msgid "Param"
-msgstr "Param"
+msgstr ""
msgid "Password accepted - you are now recognized."
-msgstr "Password accepted - you are now recognized."
+msgstr ""
msgid "Password accepted."
-msgstr "Password accepted."
-
-#, c-format
-msgid "Password for %s changed to %s."
-msgstr "Password for %s changed to %s."
+msgstr ""
#, c-format
msgid "Password for %s changed."
-msgstr "Password for %s changed."
-
-#, c-format
-msgid "Password for %s is %s."
-msgstr "Password for %s is %s."
+msgstr ""
msgid "Password incorrect."
-msgstr "Password incorrect."
+msgstr ""
#, c-format
msgid "Password reset email for %s has been sent."
-msgstr "Password reset email for %s has been sent."
+msgstr ""
+
+msgid "Passwords can not be changed right now. Please try again later."
+msgstr ""
+
+#, c-format
+msgid "Passwords encrypted with %s: %zu"
+msgstr ""
msgid "Peace"
-msgstr "Peace"
+msgstr ""
#, c-format
msgid "Peace option for %s is now off."
-msgstr "Peace option for %s is now off."
+msgstr ""
#, c-format
msgid "Peace option for %s is now on."
-msgstr "Peace option for %s is now on."
+msgstr ""
msgid "Persistent"
-msgstr "Persistent"
+msgstr ""
+
+#, c-format
+msgid "Please confirm that you want to drop %s with %s DROP %s %s"
+msgstr ""
-msgid "Please contact an Operator to get a vHost assigned to this nick."
-msgstr "Please contact an Operator to get a vHost assigned to this nick."
+msgid "Please contact an Operator to get a vhost assigned to this nick."
+msgstr ""
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab characters."
msgid "Please use a valid server name when juping."
-msgstr "Please use a valid server name when juping."
+msgstr ""
msgid "Please use the symbol of # when attempting to register."
-msgstr "Please use the symbol of # when attempting to register."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Please wait %d seconds and retry."
+msgid "Please wait %lu seconds and retry."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Please wait %d seconds before requesting a new vHost."
+msgid "Please wait %s before requesting a new vhost."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Please wait %d seconds before using the %s command again."
+msgid "Please wait %s before using the %s command again."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Please wait %d seconds before using the GROUP command again."
+msgid "Please wait %s before using the GROUP command again."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "Please wait %d seconds before using the REGISTER command again."
+msgid "Please wait %s before using the REGISTER command again."
+msgstr ""
#, c-format
msgid "Pooled %s."
-msgstr "Pooled %s."
+msgstr ""
msgid "Pooled/Active"
-msgstr "Pooled/Active"
+msgstr ""
msgid "Pooled/Not Active"
-msgstr "Pooled/Not Active"
+msgstr ""
msgid "Prevent a bot from being assigned by non IRC operators"
-msgstr "Prevent a bot from being assigned by non IRC operators"
+msgstr ""
msgid "Prevent a bot from being assigned to a channel"
-msgstr "Prevent a bot from being assigned to a channel"
+msgstr ""
msgid "Prevent a channel from being used preserving channel data and settings"
-msgstr "Prevent a channel from being used preserving channel data and settings"
+msgstr ""
msgid "Prevent the channel from expiring"
-msgstr "Prevent the channel from expiring"
+msgstr ""
msgid "Prevent the nickname from appearing in the LIST command"
-msgstr "Prevent the nickname from appearing in the LIST command"
+msgstr ""
msgid "Prevent the nickname from expiring"
-msgstr "Prevent the nickname from expiring"
+msgstr ""
-msgid "Prevents users being kicked by Services"
-msgstr "Prevents users being kicked by Services"
+msgid "Prevents users being kicked by services"
+msgstr ""
msgid "Private"
-msgstr "Private"
+msgstr ""
#, c-format
msgid "Private mode of bot %s is now off."
-msgstr "Private mode of bot %s is now off."
+msgstr ""
#, c-format
msgid "Private mode of bot %s is now on."
-msgstr "Private mode of bot %s is now on."
+msgstr ""
#, c-format
msgid "Private option for %s is now off."
-msgstr "Private option for %s is now off."
+msgstr ""
#, c-format
msgid "Private option for %s is now on."
-msgstr "Private option for %s is now on."
+msgstr ""
#, c-format
msgid "Private option is now off for %s."
-msgstr "Private option is now off for %s."
+msgstr ""
#, c-format
msgid "Private option is now on for %s."
-msgstr "Private option is now on for %s."
+msgstr ""
#, c-format
msgid "Privilege %s added to %s on %s, new flags are +%s"
-msgstr "Privilege %s added to %s on %s, new flags are +%s"
+msgstr ""
#, c-format
msgid "Privilege %s removed from %s on %s, new flags are +%s"
-msgstr "Privilege %s removed from %s on %s, new flags are +%s"
+msgstr ""
msgid "Protection"
-msgstr "Protection"
+msgstr ""
#, c-format
msgid "Protection is now off for %s."
-msgstr "Protection is now off for %s."
+msgstr ""
#, c-format
msgid "Protection is now on for %s, with a reduced delay."
-msgstr "Protection is now on for %s, with a reduced delay."
+msgstr ""
#, c-format
msgid "Protection is now on for %s, with no delay."
-msgstr "Protection is now on for %s, with no delay."
+msgstr ""
#, c-format
msgid "Protection is now on for %s."
-msgstr "Protection is now on for %s."
+msgstr ""
msgid ""
"Puts an AKILL for every nick on the specified channel. It\n"
"uses the entire real ident@host for every nick, and\n"
"then enforces the AKILL."
msgstr ""
-"Puts an AKILL for every nick on the specified channel. It\n"
-"uses the entire real ident@host for every nick, and\n"
-"then enforces the AKILL."
msgid "Quick protection"
-msgstr "Quick protection"
+msgstr ""
msgid "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
+msgstr ""
msgid "REGONLY enforced by "
-msgstr "REGONLY enforced by "
+msgstr ""
msgid "RESTRICTED enforced by "
-msgstr "RESTRICTED enforced by "
+msgstr ""
msgid "REVOKE server"
-msgstr "REVOKE server"
+msgstr ""
#, c-format
msgid "Random news item #%d deleted."
-msgstr "Random news item #%d deleted."
+msgstr ""
#, c-format
msgid "Random news item #%s not found!"
-msgstr "Random news item #%s not found!"
+msgstr ""
msgid "Random news items:"
-msgstr "Random news items:"
+msgstr ""
msgid "Read a memo or memos"
-msgstr "Read a memo or memos"
+msgstr ""
msgid "Real name"
-msgstr "Real name"
+msgstr ""
msgid "Realname"
-msgstr "Realname"
+msgstr ""
msgid "Reason"
-msgstr "Reason"
+msgstr ""
#, c-format
msgid "Reason for %s updated."
-msgstr "Reason for %s updated."
+msgstr ""
msgid ""
"Recovers your nick from another user or from services.\n"
@@ -5593,62 +4811,52 @@ msgid ""
"GHOST command). If they are not identified they will be\n"
"forced off of the nick."
msgstr ""
-"Recovers your nick from another user or from services.\n"
-"If services are currently holding your nick, the hold\n"
-"will be released. If another user is holding your nick\n"
-"and is identified they will be killed (similar to the old\n"
-"GHOST command). If they are not identified they will be\n"
-"forced off of the nick."
msgid "Redefine the meanings of access levels"
-msgstr "Redefine the meanings of access levels"
+msgstr ""
msgid "Regains control of your nick"
-msgstr "Regains control of your nick"
+msgstr ""
msgid "Regex is disabled."
-msgstr "Regex is disabled."
+msgstr ""
#, c-format
msgid ""
"Regex matches are also supported using the %s engine.\n"
"Enclose your mask in // if this is desired."
msgstr ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your mask in // if this is desired."
#, c-format
msgid ""
"Regex matches are also supported using the %s engine.\n"
"Enclose your pattern in // if this is desired."
msgstr ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your pattern in // if this is desired."
msgid "Register a channel"
-msgstr "Register a channel"
+msgstr ""
msgid "Register a nickname"
-msgstr "Register a nickname"
+msgstr ""
msgid "Registered"
-msgstr "Registered"
+msgstr ""
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Registered channels: %lu entries, %lu buckets, longest chain is %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr ""
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
+msgstr ""
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
+msgstr ""
#, c-format
msgid "Registered only enforced on %s."
-msgstr "Registered only enforced on %s."
+msgstr ""
#, c-format
msgid ""
@@ -5664,17 +4872,6 @@ msgid ""
"%s will also automatically give the founder\n"
"channel operator privileges when they enter the channel."
msgstr ""
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which is optional, is a\n"
-"general description of the channel's purpose.\n"
-" \n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel operator privileges when they enter the channel."
#, c-format
msgid ""
@@ -5693,335 +4890,233 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
-"Registers your nickname in the %s database. Once\n"
-"your nick is registered, you can use the SET and ACCESS\n"
-"commands to configure your nick's settings as you like\n"
-"them. Make sure you remember the password you use when\n"
-"registering - you'll need it to make changes to your nick\n"
-"later. (Note that case matters! ANOPE, Anope, and\n"
-"anope are all different passwords!)\n"
-" \n"
-"Guidelines on choosing passwords:\n"
-" \n"
-"Passwords should not be easily guessable. For example,\n"
-"using your real name as a password is a bad idea. Using\n"
-"your nickname as a password is a much worse idea ;) and,\n"
-"in fact, %s will not allow it. Also, short\n"
-"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
-"Finally, the space character cannot be used in passwords."
msgid "Registration is currently disabled."
-msgstr "Registration is currently disabled."
+msgstr ""
msgid "Regulate the use of critical commands"
-msgstr "Regulate the use of critical commands"
+msgstr ""
-msgid "Reject the requested vHost for the given nick."
-msgstr "Reject the requested vHost for the given nick."
+msgid "Reject the requested vhost for the given nick."
+msgstr ""
-msgid "Reject the requested vHost of a user"
-msgstr "Reject the requested vHost of a user"
+msgid "Reject the requested vhost of a user"
+msgstr ""
msgid "Releases a suspended channel"
-msgstr "Releases a suspended channel"
+msgstr ""
msgid ""
"Releases a suspended channel. All data and settings\n"
"are preserved from before the suspension."
msgstr ""
-"Releases a suspended channel. All data and settings\n"
-"are preserved from before the suspension."
msgid "Reload a module"
-msgstr "Reload a module"
+msgstr ""
msgid "Reload services' configuration file"
-msgstr "Reload services' configuration file"
+msgstr ""
msgid "Remove a nick from a group"
-msgstr "Remove a nick from a group"
+msgstr ""
msgid "Remove all bans preventing a user from entering a channel"
-msgstr "Remove all bans preventing a user from entering a channel"
+msgstr ""
msgid "Remove all operators from a server remotely"
-msgstr "Remove all operators from a server remotely"
+msgstr ""
#, c-format
msgid "Removed IP %s from %s."
-msgstr "Removed IP %s from %s."
+msgstr ""
#, c-format
msgid "Removed server %s from zone %s."
-msgstr "Removed server %s from zone %s."
+msgstr ""
#, c-format
msgid "Removed server %s."
-msgstr "Removed server %s."
+msgstr ""
#, c-format
msgid ""
-"Removes %s status from the selected nick on a channel. If nick is\n"
+"Removes %s status from the selected nicks on a channel. If nick is\n"
"not given, it will de%s you."
msgstr ""
-"Removes %s status from the selected nick on a channel. If nick is\n"
-"not given, it will de%s you."
#, c-format
msgid "Removes %s status from you or the specified nick on a channel"
-msgstr "Removes %s status from you or the specified nick on a channel"
+msgstr ""
msgid "Removes a selected nicks status from a channel"
-msgstr "Removes a selected nicks status from a channel"
+msgstr ""
msgid ""
"Removes a selected nicks status modes on a channel. If nick is\n"
"omitted then your status is removed. If channel is omitted then\n"
"your channel status is removed on every channel you are in."
msgstr ""
-"Removes a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is removed. If channel is omitted then\n"
-"your channel status is removed on every channel you are in."
#, c-format
msgid "Removing %s because %s covers it."
-msgstr "Removing %s because %s covers it."
+msgstr ""
msgid "Repeat kicker"
-msgstr "Repeat kicker"
+msgstr ""
-msgid "Request a vHost for your nick"
-msgstr "Request a vHost for your nick"
+msgid "Request a vhost for your nick"
+msgstr ""
msgid ""
-"Request the given vHost to be activated for your nick by the\n"
+"Request the given vhost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."
msgstr ""
-"Request the given vHost to be activated for your nick by the\n"
-"network administrators. Please be patient while your request\n"
-"is being considered."
msgid "Resend registration confirmation email"
-msgstr "Resend registration confirmation email"
+msgstr ""
msgid "Restrict access to the channel"
-msgstr "Restrict access to the channel"
+msgstr ""
msgid "Restricted access"
-msgstr "Restricted access"
+msgstr ""
#, c-format
msgid "Restricted access option for %s is now off."
-msgstr "Restricted access option for %s is now off."
+msgstr ""
#, c-format
msgid "Restricted access option for %s is now on."
-msgstr "Restricted access option for %s is now on."
+msgstr ""
#, c-format
msgid "Restricted enforced on %s."
-msgstr "Restricted enforced on %s."
+msgstr ""
msgid "Retain modes when channel is not in use"
-msgstr "Retain modes when channel is not in use"
+msgstr ""
msgid "Retain topic when channel is not in use"
-msgstr "Retain topic when channel is not in use"
-
-msgid "Retrieve the password for a nickname"
-msgstr "Retrieve the password for a nickname"
+msgstr ""
msgid "Retrieves the vhost requests"
-msgstr "Retrieves the vhost requests"
+msgstr ""
msgid "Returns the key of the given channel"
-msgstr "Returns the key of the given channel"
+msgstr ""
msgid "Returns the key of the given channel."
-msgstr "Returns the key of the given channel."
-
-msgid "Returns the matching accounts that used given email."
-msgstr "Returns the matching accounts that used given email."
-
-msgid "Returns the owner status of the given nickname"
-msgstr "Returns the owner status of the given nickname"
-
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
msgstr ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
+msgid "Returns the matching accounts that used given email."
msgstr ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
msgid "Reverses kicker"
-msgstr "Reverses kicker"
+msgstr ""
msgid "Reverses the effect of the IDENTIFY command"
-msgstr "Reverses the effect of the IDENTIFY command"
+msgstr ""
msgid "SET server"
-msgstr "SET server"
+msgstr ""
msgid "SET server.name option value"
-msgstr "SET server.name option value"
+msgstr ""
#, c-format
msgid "SSL certificate fingerprint accepted, you are now identified to %s."
-msgstr "SSL certificate fingerprint accepted, you are now identified to %s."
+msgstr ""
msgid "SSL certificate fingerprint accepted, you are now identified."
-msgstr "SSL certificate fingerprint accepted, you are now identified."
+msgstr ""
#, c-format
msgid "SSL only enforced on %s."
-msgstr "SSL only enforced on %s."
+msgstr ""
msgid "SSLONLY enforced by "
-msgstr "SSLONLY enforced by "
+msgstr ""
-msgid "Save databases and restart Services"
-msgstr "Save databases and restart Services"
+msgid "Save databases and restart services"
+msgstr ""
msgid "Searches logs for a matching pattern"
-msgstr "Searches logs for a matching pattern"
+msgstr ""
msgid "Secure founder"
-msgstr "Secure founder"
+msgstr ""
#, c-format
msgid "Secure founder option for %s is now off."
-msgstr "Secure founder option for %s is now off."
+msgstr ""
#, c-format
msgid "Secure founder option for %s is now on."
-msgstr "Secure founder option for %s is now on."
+msgstr ""
msgid "Secure ops"
-msgstr "Secure ops"
+msgstr ""
#, c-format
msgid "Secure ops option for %s is now off."
-msgstr "Secure ops option for %s is now off."
+msgstr ""
#, c-format
msgid "Secure ops option for %s is now on."
-msgstr "Secure ops option for %s is now on."
-
-#, c-format
-msgid "Secure option for %s is now off."
-msgstr "Secure option for %s is now off."
-
-#, c-format
-msgid "Secure option for %s is now on."
-msgstr "Secure option for %s is now on."
-
-#, c-format
-msgid "Secure option is now off for %s."
-msgstr "Secure option is now off for %s."
-
-#, c-format
-msgid "Secure option is now on for %s."
-msgstr "Secure option is now on for %s."
+msgstr ""
#, c-format
msgid "Secureops enforced on %s."
-msgstr "Secureops enforced on %s."
-
-msgid "Security"
-msgstr "Security"
+msgstr ""
#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the access list."
msgstr ""
-"See %s%s HELP %s for more information\n"
-"about the access list."
#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the flags system."
msgstr ""
-"See %s%s HELP %s for more information\n"
-"about the flags system."
msgid "Send a memo to a nick or channel"
-msgstr "Send a memo to a nick or channel"
+msgstr ""
msgid "Send a memo to all opers/admins"
-msgstr "Send a memo to all opers/admins"
+msgstr ""
msgid "Send a memo to all registered users"
-msgstr "Send a memo to all registered users"
+msgstr ""
msgid "Send a message to all users"
-msgstr "Send a message to all users"
+msgstr ""
+
+msgid "Send a message to all users on a server"
+msgstr ""
msgid "Sender"
-msgstr "Sender"
+msgstr ""
msgid "Sends a memo and requests a read receipt"
-msgstr "Sends a memo and requests a read receipt"
+msgstr ""
msgid ""
"Sends a passcode to the nickname with instructions on how to\n"
"reset their password. Email must be the email address associated\n"
"to the nickname."
msgstr ""
-"Sends a passcode to the nickname with instructions on how to\n"
-"reset their password. Email must be the email address associated\n"
-"to the nickname."
msgid "Sends all registered users a memo containing memo-text."
-msgstr "Sends all registered users a memo containing memo-text."
+msgstr ""
msgid "Sends all services staff a memo containing memo-text."
-msgstr "Sends all services staff a memo containing memo-text."
+msgstr ""
msgid ""
"Sends the named nick or channel a memo containing\n"
@@ -6029,10 +5124,6 @@ msgid ""
"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered."
msgstr ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that they have a new memo. The target\n"
-"nickname/channel must be registered."
msgid ""
"Sends the named nick or channel a memo containing\n"
@@ -6043,13 +5134,6 @@ msgid ""
"memo will be sent to the sender informing them that the memo\n"
"has been read."
msgstr ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that they have a new memo. The target\n"
-"nickname/channel must be registered.\n"
-"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing them that the memo\n"
-"has been read."
msgid ""
"Sends you the text of the memos specified. If LAST is\n"
@@ -6062,213 +5146,208 @@ msgid ""
" READ 2-5,7-9\n"
" Displays memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Sends you the text of the memos specified. If LAST is\n"
-"given, sends you the memo you most recently received. If\n"
-"NEW is given, sends you all of your new memos. If ALL is\n"
-"given, sends you all of your memos. Otherwise, sends you\n"
-"memo number num. You can also give a list of numbers,\n"
-"as in this example:\n"
-" \n"
-" READ 2-5,7-9\n"
-" Displays memos numbered 2 through 5 and 7 through 9."
msgid "Server"
-msgstr "Server"
+msgstr ""
+
+#, c-format
+msgid "Server %s is not linked to the network."
+msgstr ""
#, c-format
msgid "Server %s added to zone %s."
-msgstr "Server %s added to zone %s."
+msgstr ""
#, c-format
msgid "Server %s already exists."
-msgstr "Server %s already exists."
+msgstr ""
#, c-format
msgid "Server %s does not exist."
-msgstr "Server %s does not exist."
+msgstr ""
#, c-format
msgid "Server %s has no configured IPs."
-msgstr "Server %s has no configured IPs."
+msgstr ""
#, c-format
msgid "Server %s is already in zone %s."
-msgstr "Server %s is already in zone %s."
+msgstr ""
#, c-format
msgid "Server %s is already pooled."
-msgstr "Server %s is already pooled."
+msgstr ""
#, c-format
msgid "Server %s is not currently linked."
-msgstr "Server %s is not currently linked."
+msgstr ""
#, c-format
msgid "Server %s is not in zone %s."
-msgstr "Server %s is not in zone %s."
+msgstr ""
#, c-format
msgid "Server %s is not linked to the network."
-msgstr "Server %s is not linked to the network."
+msgstr ""
#, c-format
msgid "Server %s is not pooled."
-msgstr "Server %s is not pooled."
+msgstr ""
#, c-format
msgid "Server %s must be quit before it can be deleted."
-msgstr "Server %s must be quit before it can be deleted."
+msgstr ""
msgid "Servers"
-msgstr "Servers"
+msgstr ""
#, c-format
msgid "Servers found: %d"
-msgstr "Servers found: %d"
+msgstr ""
msgid "Service"
-msgstr "Service"
+msgstr ""
#, c-format
msgid "Service's hold on %s has been released."
-msgstr "Service's hold on %s has been released."
+msgstr ""
msgid "Services Operator commands"
-msgstr "Services Operator commands"
+msgstr ""
msgid "Services are in DefCon mode, please try again later."
-msgstr "Services are in DefCon mode, please try again later."
-
-msgid "Services are in read-only mode!"
-msgstr "Services are in read-only mode!"
+msgstr ""
#, c-format
msgid "Services are now at DEFCON %d."
-msgstr "Services are now at DEFCON %d."
+msgstr ""
#, c-format
msgid "Services are now in debug mode (level %d)."
-msgstr "Services are now in debug mode (level %d)."
+msgstr ""
msgid "Services are now in debug mode."
-msgstr "Services are now in debug mode."
+msgstr ""
msgid "Services are now in expire mode."
-msgstr "Services are now in expire mode."
+msgstr ""
msgid "Services are now in no expire mode."
-msgstr "Services are now in no expire mode."
+msgstr ""
msgid "Services are now in non-debug mode."
-msgstr "Services are now in non-debug mode."
+msgstr ""
msgid "Services are now in read-only mode."
-msgstr "Services are now in read-only mode."
+msgstr ""
msgid "Services are now in read-write mode."
-msgstr "Services are now in read-write mode."
+msgstr ""
+
+msgid "Services are temporarily in read-only mode."
+msgstr ""
msgid "Services have been configured to not send mail."
-msgstr "Services have been configured to not send mail."
+msgstr ""
msgid "Services ignore list:"
-msgstr "Services ignore list:"
+msgstr ""
msgid "Services is unable to change modes. Are your servers' U:lines configured correctly?"
-msgstr "Services is unable to change modes. Are your servers' U:lines configured correctly?"
+msgstr ""
#, c-format
msgid "Services up %s."
-msgstr "Services up %s."
+msgstr ""
#, c-format
msgid "Services will from now on set status modes on %s in channels."
-msgstr "Services will from now on set status modes on %s in channels."
+msgstr ""
#, c-format
msgid "Services will no longer automatically give modes to users in %s."
-msgstr "Services will no longer automatically give modes to users in %s."
+msgstr ""
#, c-format
msgid "Services will no longer set status modes on %s in channels."
-msgstr "Services will no longer set status modes on %s in channels."
+msgstr ""
#, c-format
msgid "Services will now automatically give modes to users in %s."
-msgstr "Services will now automatically give modes to users in %s."
+msgstr ""
#, c-format
msgid "Services will now reply to %s with messages."
-msgstr "Services will now reply to %s with messages."
+msgstr ""
#, c-format
msgid "Services will now reply to %s with notices."
-msgstr "Services will now reply to %s with notices."
+msgstr ""
msgid "Services' configuration has been reloaded."
-msgstr "Services' configuration has been reloaded."
+msgstr ""
msgid "Session"
-msgstr "Session"
+msgstr ""
#, c-format
msgid "Session limit for %s set to %d."
-msgstr "Session limit for %s set to %d."
+msgstr ""
msgid "Session limiting is disabled."
-msgstr "Session limiting is disabled."
+msgstr ""
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Sessions: %lu entries, %lu buckets, longest chain is %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
+msgstr ""
msgid "Set SET-options on another nickname"
-msgstr "Set SET-options on another nickname"
+msgstr ""
msgid "Set channel options and information"
-msgstr "Set channel options and information"
+msgstr ""
-msgid "Set how Services make bans on the channel"
-msgstr "Set how Services make bans on the channel"
+msgid "Set how services make bans on the channel"
+msgstr ""
-msgid "Set options related to memos"
-msgstr "Set options related to memos"
+msgid "Set nickname options and information"
+msgstr ""
-msgid "Set options, including kill protection"
-msgstr "Set options, including kill protection"
+msgid "Set options related to memos"
+msgstr ""
msgid "Set the channel as permanent"
-msgstr "Set the channel as permanent"
+msgstr ""
msgid "Set the channel description"
-msgstr "Set the channel description"
+msgstr ""
-msgid "Set the display of your group in Services"
-msgstr "Set the display of your group in Services"
+msgid "Set the display of your group in services"
+msgstr ""
msgid "Set the founder of a channel"
-msgstr "Set the founder of a channel"
+msgstr ""
-msgid "Set the language Services will use when messaging you"
-msgstr "Set the language Services will use when messaging you"
+msgid "Set the language services will use when messaging you"
+msgstr ""
msgid "Set the nickname password"
-msgstr "Set the nickname password"
+msgstr ""
msgid "Set the successor for a channel"
-msgstr "Set the successor for a channel"
+msgstr ""
msgid "Set the vhost for all nicks in a group"
-msgstr "Set the vhost for all nicks in a group"
+msgstr ""
msgid "Set the vhost of another user"
-msgstr "Set the vhost of another user"
+msgstr ""
-msgid "Set various global Services options"
-msgstr "Set various global Services options"
+msgid "Set various global services options"
+msgstr ""
msgid "Set your nickname password"
-msgstr "Set your nickname password"
+msgstr ""
#, c-format
msgid ""
@@ -6280,13 +5359,6 @@ msgid ""
"before they get banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the AMSG kicker on or off. When enabled, the bot will\n"
-"kick users who send the same message to multiple channels\n"
-"where %s bots are.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before they get banned. Don't give ttb to disable\n"
-"the ban system once activated."
#, c-format
msgid ""
@@ -6294,23 +5366,13 @@ msgid ""
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
+"BADWORDS command. Type %s HELP BADWORDS for\n"
"more information.\n"
" \n"
"ttb is the number of times a user can be kicked\n"
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the bad words kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who say certain words\n"
-"on the channels.\n"
-"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
-"more information.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the ban type that will be used by services whenever\n"
@@ -6323,15 +5385,6 @@ msgid ""
"2: ban in the form *!*@host\n"
"3: ban in the form *!*user@*.domain"
msgstr ""
-"Sets the ban type that will be used by services whenever\n"
-"they need to ban someone from your channel.\n"
-" \n"
-"Bantype is a number between 0 and 3 that means:\n"
-" \n"
-"0: ban in the form *!user@host\n"
-"1: ban in the form *!*user@host\n"
-"2: ban in the form *!*@host\n"
-"3: ban in the form *!*user@*.domain"
msgid ""
"Sets the bolds kicker on or off. When enabled, this\n"
@@ -6341,12 +5394,6 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the bolds kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use bolds.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
#, c-format
msgid ""
@@ -6362,17 +5409,6 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the caps kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are talking in\n"
-"CAPS.\n"
-"The bot kicks only if there are at least min caps\n"
-"and they constitute at least percent%% of the total\n"
-"text line (if not given, it defaults to 10 characters\n"
-"and 25%%).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the colors kicker on or off. When enabled, this\n"
@@ -6382,19 +5418,11 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the colors kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use colors.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the description for the channel, which shows up with\n"
"the LIST and INFO commands."
msgstr ""
-"Sets the description for the channel, which shows up with\n"
-"the LIST and INFO commands."
msgid ""
"Sets the flood kicker on or off. When enabled, this\n"
@@ -6406,14 +5434,6 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the flood kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are flooding\n"
-"the channel using at least ln lines in secs seconds\n"
-"(if not given, it defaults to 6 lines in 10 seconds).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the italics kicker on or off. When enabled, this\n"
@@ -6423,12 +5443,6 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the repeat kicker on or off. When enabled, this\n"
@@ -6440,14 +5454,6 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the repeat kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are repeating\n"
-"themselves num times (if num is not given, it\n"
-"defaults to 3).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the reverses kicker on or off. When enabled, this\n"
@@ -6457,12 +5463,6 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the reverses kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use reverses.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the underlines kicker on or off. When enabled, this\n"
@@ -6472,41 +5472,25 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sets the underlines kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use underlines.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
msgid ""
"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
+"of the given nick. If your IRCD supports vidents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
"added to the group after this command was used."
msgstr ""
-"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
-"using SETALL <nick> <ident>@<hostmask> will set idents\n"
-"for users as well as vhosts.\n"
-"* NOTE, this will not update the vhost for any nicks\n"
-"added to the group after this command was used."
msgid ""
"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
+"hostmask. If your IRCD supports vidents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."
msgstr ""
-"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
-"SET <nick> <ident>@<hostmask> set idents for users as\n"
-"well as vhosts."
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -6514,13 +5498,6 @@ msgid ""
" SUPERADMIN Activate or deactivate super admin mode\n"
" LIST List the options"
msgstr ""
-"Sets various global Services options. Option names\n"
-"currently defined are:\n"
-" READONLY Set read-only or read-write mode\n"
-" DEBUG Activate or deactivate debug mode\n"
-" NOEXPIRE Activate or deactivate no expire mode\n"
-" SUPERADMIN Activate or deactivate super admin mode\n"
-" LIST List the options"
#, c-format
msgid ""
@@ -6531,31 +5508,23 @@ msgid ""
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
-"Sets various memo options. option can be one of:\n"
-" \n"
-" NOTIFY Changes when you will be notified about\n"
-" new memos (only for nicknames)\n"
-" LIMIT Sets the maximum number of memos you can\n"
-" receive\n"
-" \n"
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
msgid "Sets various nickname options. option can be one of:"
-msgstr "Sets various nickname options. option can be one of:"
+msgstr ""
msgid "Sets whether services should set channel status modes on you automatically."
-msgstr "Sets whether services should set channel status modes on you automatically."
+msgstr ""
msgid ""
"Sets whether the given channel will expire. Setting this\n"
"to ON prevents the channel from expiring."
msgstr ""
-"Sets whether the given channel will expire. Setting this\n"
-"to ON prevents the channel from expiring."
+
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr ""
#, c-format
msgid ""
@@ -6565,18 +5534,14 @@ msgid ""
"is entering channels. Note that depending on channel settings\n"
"some modes may not get set automatically."
msgstr ""
-"Sets whether the given nickname will be given its status modes\n"
-"in channels automatically. Set to ON to allow %s\n"
-"to set status modes on the given nickname automatically when it\n"
-"is entering channels. Note that depending on channel settings\n"
-"some modes may not get set automatically."
msgid ""
"Sets whether the given nickname will expire. Setting this\n"
"to ON prevents the nickname from expiring."
msgstr ""
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
+
+msgid "Sets whether you can be added to a channel access list."
+msgstr ""
#, c-format
msgid ""
@@ -6585,204 +5550,149 @@ msgid ""
"when entering channels. Note that depending on channel settings some modes\n"
"may not get set automatically."
msgstr ""
-"Sets whether you will be given your channel status modes automatically.\n"
-"Set to ON to allow %s to set status modes on you automatically\n"
-"when entering channels. Note that depending on channel settings some modes\n"
-"may not get set automatically."
#, c-format
-msgid "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
-msgstr "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
+msgid "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
+msgstr ""
msgid "Setting for DEBUG must be ON, OFF, or a positive number."
-msgstr "Setting for DEBUG must be ON, OFF, or a positive number."
+msgstr ""
msgid "Setting for NOEXPIRE must be ON or OFF."
-msgstr "Setting for NOEXPIRE must be ON or OFF."
+msgstr ""
msgid "Setting for READONLY must be ON or OFF."
-msgstr "Setting for READONLY must be ON or OFF."
+msgstr ""
msgid "Setting for super admin must be ON or OFF."
-msgstr "Setting for super admin must be ON or OFF."
+msgstr ""
msgid "Should services automatically give status to users"
-msgstr "Should services automatically give status to users"
+msgstr ""
-msgid "Show status of Services and network"
-msgstr "Show status of Services and network"
+msgid "Show status of services and network"
+msgstr ""
#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr "Showed %d/%d matches for %s."
+msgid "Showed %zu/%zu matches for %s."
+msgstr ""
msgid "Sign kicks that are done with the KICK command"
-msgstr "Sign kicks that are done with the KICK command"
+msgstr ""
#, c-format
msgid "Signed kick option for %s is now off."
-msgstr "Signed kick option for %s is now off."
+msgstr ""
#, c-format
msgid ""
"Signed kick option for %s is now on, but depends of the\n"
"level of the user that is using the command."
msgstr ""
-"Signed kick option for %s is now on, but depends of the\n"
-"level of the user that is using the command."
#, c-format
msgid "Signed kick option for %s is now on."
-msgstr "Signed kick option for %s is now on."
+msgstr ""
msgid "Signed kicks"
-msgstr "Signed kicks"
+msgstr ""
#, c-format
msgid "Sorry, %s currently has too many memos and cannot receive more."
-msgstr "Sorry, %s currently has too many memos and cannot receive more."
-
-#, c-format
-msgid "Sorry, I have not seen %s."
-msgstr "Sorry, I have not seen %s."
-
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr "Sorry, bad words list modification is temporarily disabled."
-
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr "Sorry, bot assignment is temporarily disabled."
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "Sorry, bot modification is temporarily disabled."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr "Sorry, bot option setting is temporarily disabled."
-
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr "Sorry, changing bot options is temporarily disabled."
+msgstr ""
#, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
-msgstr "Sorry, channel %s list modification is temporarily disabled."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr "Sorry, channel access list modification is temporarily disabled."
-
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr "Sorry, channel autokick list modification is temporarily disabled."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr "Sorry, channel de-registration is temporarily disabled."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Sorry, channel registration is temporarily disabled."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
-msgstr "Sorry, kicker configuration is temporarily disabled."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr "Sorry, memo option setting is temporarily disabled."
-
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr "Sorry, memo sending is temporarily disabled."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Sorry, nickname de-registration is temporarily disabled."
-
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Sorry, nickname grouping is temporarily disabled."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Sorry, nickname registration is temporarily disabled."
+msgid "Sorry, %s is temporarily unavailable."
+msgstr ""
#, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
-msgstr "Sorry, the maximum of %d access entries has been reached."
+msgid "Sorry, I have not seen %s."
+msgstr ""
#, c-format
msgid "Sorry, the maximum of %d auto join entries has been reached."
-msgstr "Sorry, the maximum of %d auto join entries has been reached."
+msgstr ""
#, c-format
msgid "Sorry, the maximum of %d certificate entries has been reached."
-msgstr "Sorry, the maximum of %d certificate entries has been reached."
+msgstr ""
#, c-format
msgid "Sorry, the memo ignore list for %s is full."
-msgstr "Sorry, the memo ignore list for %s is full."
+msgstr ""
#, c-format
msgid "Sorry, you can only have %d access entries on a channel, including access entries from other channels."
-msgstr "Sorry, you can only have %d access entries on a channel, including access entries from other channels."
+msgstr ""
#, c-format
msgid "Sorry, you can only have %d autokick masks on a channel."
-msgstr "Sorry, you can only have %d autokick masks on a channel."
+msgstr ""
#, c-format
msgid "Sorry, you can only have %d bad words entries on a channel."
-msgstr "Sorry, you can only have %d bad words entries on a channel."
+msgstr ""
#, c-format
msgid "Sorry, you have already exceeded your limit of %d channels."
-msgstr "Sorry, you have already exceeded your limit of %d channels."
+msgstr ""
#, c-format
msgid "Sorry, you have already reached your limit of %d channels."
-msgstr "Sorry, you have already reached your limit of %d channels."
+msgstr ""
msgid "State"
-msgstr "State"
+msgstr ""
msgid "Statistics and maintenance for seen data"
-msgstr "Statistics and maintenance for seen data"
+msgstr ""
msgid "Statistics reset."
-msgstr "Statistics reset."
+msgstr ""
msgid "Status updated (memos, vhost, chmodes, flags)."
-msgstr "Status updated (memos, vhost, chmodes, flags)."
+msgstr ""
msgid "Stop flooding!"
-msgstr "Stop flooding!"
+msgstr ""
msgid "Stop repeating yourself!"
-msgstr "Stop repeating yourself!"
+msgstr ""
msgid "Stricter control of channel founder status"
-msgstr "Stricter control of channel founder status"
+msgstr ""
msgid "Stricter control of chanop status"
-msgstr "Stricter control of chanop status"
+msgstr ""
msgid "Successor"
-msgstr "Successor"
+msgstr ""
#, c-format
msgid "Successor for %s changed to %s."
-msgstr "Successor for %s changed to %s."
+msgstr ""
#, c-format
msgid "Successor for %s unset."
-msgstr "Successor for %s unset."
+msgstr ""
msgid "Super admin can not be set because it is not enabled in the configuration."
-msgstr "Super admin can not be set because it is not enabled in the configuration."
+msgstr ""
msgid "Suspend a given nick"
-msgstr "Suspend a given nick"
+msgstr ""
msgid "Suspend reason"
-msgstr "Suspend reason"
+msgstr ""
msgid "Suspended"
-msgstr "Suspended"
+msgstr ""
msgid "Suspended by"
-msgstr "Suspended by"
+msgstr ""
msgid "Suspended on"
-msgstr "Suspended on"
+msgstr ""
msgid ""
"Suspends a registered nickname, which prevents it from being used\n"
@@ -6790,29 +5700,23 @@ msgid ""
"the nick will be unsuspended after that period of time, else the\n"
"default expiry from the configuration is used."
msgstr ""
-"Suspends a registered nickname, which prevents it from being used\n"
-"while keeping all the data for that nick. If an expiry is given\n"
-"the nick will be unsuspended after that period of time, else the\n"
-"default expiry from the configuration is used."
msgid "Suspension expires"
-msgstr "Suspension expires"
+msgstr ""
msgid "Sync users channel modes"
-msgstr "Sync users channel modes"
+msgstr ""
msgid ""
"Syncs all modes set on users on the channel with the modes\n"
"they should have based on their access."
msgstr ""
-"Syncs all modes set on users on the channel with the modes\n"
-"they should have based on their access."
msgid "Syncs the vhost for all nicks in a group"
-msgstr "Syncs the vhost for all nicks in a group"
+msgstr ""
msgid "Syntax"
-msgstr "Syntax"
+msgstr ""
#, c-format
msgid ""
@@ -6820,9 +5724,6 @@ msgid ""
" \n"
"Lists all nicks in your group."
msgstr ""
-"Syntax: %s\n"
-" \n"
-"Lists all nicks in your group."
#, c-format
msgid ""
@@ -6835,14 +5736,6 @@ msgid ""
"group of the given nick.\n"
"Specifying a nick is limited to Services Operators."
msgstr ""
-"Syntax: %s [nickname]\n"
-" \n"
-"Without a parameter, lists all nicknames that are in\n"
-"your group.\n"
-" \n"
-"With a parameter, lists all nicknames that are in the\n"
-"group of the given nick.\n"
-"Specifying a nick is limited to Services Operators."
msgid ""
"Syntax: DEBUG {ON | OFF}\n"
@@ -6852,12 +5745,6 @@ msgid ""
"This option is equivalent to the command-line option\n"
"--debug."
msgstr ""
-"Syntax: DEBUG {ON | OFF}\n"
-" \n"
-"Sets debug mode on or off.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--debug."
#, c-format
msgid ""
@@ -6868,12 +5755,6 @@ msgid ""
"able to send any memos to you. However, you cannot set\n"
"this any higher than %d."
msgstr ""
-"Syntax: LIMIT [channel] limit\n"
-" \n"
-"Sets the maximum number of memos you (or the given channel)\n"
-"are allowed to have. If you set this to 0, no one will be\n"
-"able to send any memos to you. However, you cannot set\n"
-"this any higher than %d."
#, c-format
msgid ""
@@ -6897,25 +5778,6 @@ msgid ""
"remove their limit, may not set a limit above %d, and may\n"
"not set a hard limit."
msgstr ""
-"Syntax: LIMIT [user | channel] {limit | NONE} [HARD]\n"
-" \n"
-"Sets the maximum number of memos a user or channel is\n"
-"allowed to have. Setting the limit to 0 prevents the user\n"
-"from receiving any memos; setting it to NONE allows the\n"
-"user to receive and keep as many memos as they want. If\n"
-"you do not give a nickname or channel, your own limit is\n"
-"set.\n"
-" \n"
-"Adding HARD prevents the user from changing the limit. Not\n"
-"adding HARD has the opposite effect, allowing the user to\n"
-"change the limit (even if a previous limit was set with\n"
-"HARD).\n"
-" \n"
-"This use of the SET LIMIT command is limited to Services\n"
-"Operators. Other users may only enter a limit for themselves\n"
-"or a channel on which they have such privileges, may not\n"
-"remove their limit, may not set a limit above %d, and may\n"
-"not set a hard limit."
#, c-format
msgid ""
@@ -6923,9 +5785,6 @@ msgid ""
" \n"
"Display the various %s settings."
msgstr ""
-"Syntax: LIST\n"
-" \n"
-"Display the various %s settings."
msgid ""
"Syntax: NOEXPIRE {ON | OFF}\n"
@@ -6937,14 +5796,6 @@ msgid ""
"This option is equivalent to the command-line option\n"
"--noexpire."
msgstr ""
-"Syntax: NOEXPIRE {ON | OFF}\n"
-" \n"
-"Sets no expire mode on or off. In no expire mode, nicks,\n"
-"channels, akills and exceptions won't expire until the\n"
-"option is unset.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--noexpire."
msgid ""
"Syntax: NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
@@ -6965,54 +5816,23 @@ msgid ""
" \n"
"ON is essentially LOGON and NEW combined."
msgstr ""
-"Syntax: NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-" \n"
-"Changes when you will be notified about new memos:\n"
-" \n"
-" ON You will be notified of memos when you log on,\n"
-" when you unset /AWAY, and when they are sent\n"
-" to you.\n"
-" LOGON You will only be notified of memos when you log\n"
-" on or when you unset /AWAY.\n"
-" NEW You will only be notified of memos when they\n"
-" are sent to you.\n"
-" MAIL You will be notified of memos by email as well as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF You will not receive any notification of memos.\n"
-" \n"
-"ON is essentially LOGON and NEW combined."
msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"users will not be allowed to modify any services data,\n"
+"including channel access lists, etc. Server operators\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
"--readonly."
msgstr ""
-"Syntax: READONLY {ON | OFF}\n"
-" \n"
-"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
-"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
-"suspend or forbid nicknames and channels, and manage news,\n"
-"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
-"terminated or restarted.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--readonly."
msgid ""
"Syntax: SUPERADMIN {ON | OFF}\n"
@@ -7023,13 +5843,6 @@ msgid ""
"This option is not persistent, and should only be used when\n"
"needed, and set back to OFF when no longer needed."
msgstr ""
-"Syntax: SUPERADMIN {ON | OFF}\n"
-" \n"
-"Setting this will grant you extra privileges such as the\n"
-"ability to be \"founder\" on all channel's etc...\n"
-" \n"
-"This option is not persistent, and should only be used when\n"
-"needed, and set back to OFF when no longer needed."
#, c-format
msgid ""
@@ -7039,11 +5852,6 @@ msgid ""
"should be the same one you sent with the REGISTER\n"
"command."
msgstr ""
-"Tells %s that you are really the owner of this\n"
-"nick. Many commands require you to authenticate yourself\n"
-"with this command before you use them. The password\n"
-"should be the same one you sent with the REGISTER\n"
-"command."
#, c-format
msgid ""
@@ -7053,11 +5861,6 @@ msgid ""
"By default, limited to AOPs or those with level 5 access and above\n"
"on the channel."
msgstr ""
-"Tells %s to invite you or an optionally specified\n"
-"nick into the given channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
#, c-format
msgid ""
@@ -7069,17 +5872,10 @@ msgid ""
"By default, limited to AOPs or those with level 5 access and above\n"
"on the channel."
msgstr ""
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel. If no channel is\n"
-"given, all bans affecting you in channels you have access\n"
-"in are removed.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7087,26 +5883,18 @@ msgid ""
"text \"Juped by <nick>\", showing the nickname of the\n"
"person who jupitered the server."
msgstr ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
-"the real server of that name from connecting. The jupe\n"
-"may be removed using a standard SQUIT. If a reason is\n"
-"given, it is placed in the server information field;\n"
-"otherwise, the server information field will contain the\n"
-"text \"Juped by <nick>\", showing the nickname of the\n"
-"person who jupitered the server."
msgid "Tells you about the last time a user was seen"
-msgstr "Tells you about the last time a user was seen"
+msgstr ""
-msgid "Terminate Services WITHOUT saving"
-msgstr "Terminate Services WITHOUT saving"
+msgid "Terminate services WITHOUT saving"
+msgstr ""
msgid "Terminate services with save"
-msgstr "Terminate services with save"
+msgstr ""
msgid "Text"
-msgstr "Text"
+msgstr ""
msgid ""
"The ACCESS ADD command adds the given mask to the\n"
@@ -7117,13 +5905,6 @@ msgid ""
"When a user joins the channel the access they receive is from the\n"
"highest level entry in the access list."
msgstr ""
-"The ACCESS ADD command adds the given mask to the\n"
-"access list with the given user level; if the mask is\n"
-"already present on the list, its access level is changed to\n"
-"the level specified in the command. The level specified\n"
-"may be a numerical level or the name of a privilege (eg AUTOOP).\n"
-"When a user joins the channel the access they receive is from the\n"
-"highest level entry in the access list."
msgid ""
"The ACCESS DEL command removes the given nick from the\n"
@@ -7132,11 +5913,6 @@ msgid ""
"You may remove yourself from an access list, even if you\n"
"do not have access to modify that list otherwise."
msgstr ""
-"The ACCESS DEL command removes the given nick from the\n"
-"access list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-"You may remove yourself from an access list, even if you\n"
-"do not have access to modify that list otherwise."
msgid ""
"The ACCESS LIST command displays the access list. If\n"
@@ -7153,22 +5929,9 @@ msgid ""
"The ACCESS CLEAR command clears all entries of the\n"
"access list."
msgstr ""
-"The ACCESS LIST command displays the access list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" ACCESS #channel LIST 2-5,7-9\n"
-" Lists access entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The ACCESS VIEW command displays the access list similar\n"
-"to ACCESS LIST but shows the creator and last used time.\n"
-" \n"
-"The ACCESS CLEAR command clears all entries of the\n"
-"access list."
msgid "The CLEAR command clears the channel access list. This requires channel founder access."
-msgstr "The CLEAR command clears the channel access list. This requires channel founder access."
+msgstr ""
#, c-format
msgid ""
@@ -7179,12 +5942,6 @@ msgid ""
" %s CLEAR 30m\n"
" Will remove all entries that were added within the last 30 minutes."
msgstr ""
-"The CLEAR command lets you clean the database by removing all entries from the\n"
-"database that were added within time.\n"
-" \n"
-"Example:\n"
-" %s CLEAR 30m\n"
-" Will remove all entries that were added within the last 30 minutes."
msgid ""
"The DEL command removes the given word from the\n"
@@ -7202,38 +5959,18 @@ msgid ""
"The CLEAR command clears all entries from the\n"
"bad words list."
msgstr ""
-"The DEL command removes the given word from the\n"
-"bad words list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The LIST command displays the bad words list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" #channel LIST 2-5,7-9\n"
-" Lists bad words entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The CLEAR command clears all entries from the\n"
-"bad words list."
msgid ""
"The ENTRYMSG ADD command adds the given message to\n"
"the list of messages shown to users when they join\n"
"the channel."
msgstr ""
-"The ENTRYMSG ADD command adds the given message to\n"
-"the list of messages shown to users when they join\n"
-"the channel."
msgid ""
"The ENTRYMSG CLEAR command clears all entries from\n"
"the list of messages shown to users when they join\n"
"the channel, effectively disabling entry messages."
msgstr ""
-"The ENTRYMSG CLEAR command clears all entries from\n"
-"the list of messages shown to users when they join\n"
-"the channel, effectively disabling entry messages."
msgid ""
"The ENTRYMSG DEL command removes the specified message from\n"
@@ -7241,20 +5978,14 @@ msgid ""
"the channel. You can remove a message by specifying its number\n"
"which you can get by listing the messages as explained below."
msgstr ""
-"The ENTRYMSG DEL command removes the specified message from\n"
-"the list of messages shown to users when they join\n"
-"the channel. You can remove a message by specifying its number\n"
-"which you can get by listing the messages as explained below."
msgid ""
"The ENTRYMSG LIST command displays a listing of messages\n"
"shown to users when they join the channel."
msgstr ""
-"The ENTRYMSG LIST command displays a listing of messages\n"
-"shown to users when they join the channel."
msgid "The IMMED option is not available on this network."
-msgstr "The IMMED option is not available on this network."
+msgstr ""
#, c-format
msgid ""
@@ -7278,25 +6009,6 @@ msgid ""
"For a list of the features and functions whose levels can be\n"
"set, see HELP LEVELS DESC."
msgstr ""
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-" \n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always re-enable it). Use LEVELS SET founder to make a level\n"
-"founder only.\n"
-" \n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel.\n"
-" \n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
msgid ""
"The LIST command allows you to list existing entries on the channel access list.\n"
@@ -7304,10 +6016,6 @@ msgid ""
"access list, and only those entries are returned. If a set of flags is given, only those\n"
"on the access list with the specified flags are returned."
msgstr ""
-"The LIST command allows you to list existing entries on the channel access list.\n"
-"If a mask is given, the mask is wildcard matched against all existing entries on the\n"
-"access list, and only those entries are returned. If a set of flags is given, only those\n"
-"on the access list with the specified flags are returned."
msgid ""
"The MODIFY command allows you to modify the access list. If the mask is\n"
@@ -7317,28 +6025,15 @@ msgid ""
"only able to modify the access list if you have the proper permission on the channel,\n"
"and even then you can only give other people access to the equivalent of what your access is."
msgstr ""
-"The MODIFY command allows you to modify the access list. If the mask is\n"
-"not already on the access list it is added, then the changes are applied.\n"
-"If the mask has no more flags, then the mask is removed from the access list.\n"
-"Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n"
-"only able to modify the access list if you have the proper permission on the channel,\n"
-"and even then you can only give other people access to the equivalent of what your access is."
msgid "The STATS command prints out statistics about stored nicks and memory usage."
-msgstr "The STATS command prints out statistics about stored nicks and memory usage."
+msgstr ""
msgid ""
"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
+"for your nick immediately. You may also wish to SET HIDE it\n"
"after registering if it isn't the default setting already."
msgstr ""
-"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
-"after registering if it isn't the default setting already."
#, c-format
msgid ""
@@ -7362,240 +6057,210 @@ msgid ""
" Would message any channel operators whenever someone used the\n"
" ACCESS command on ChanServ on the channel."
msgstr ""
-"The %s command allows users to configure logging settings\n"
-"for their channel. If no parameters are given this command\n"
-"lists the current logging methods in place for this channel.\n"
-" \n"
-"Otherwise, command must be a command name, and method\n"
-"is one of the following logging methods:\n"
-" \n"
-" MESSAGE [status], NOTICE [status], MEMO\n"
-" \n"
-"Which are used to message, notice, and memo the channel respectively.\n"
-"With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
-"to your channel. Status may be a channel status such as @ or +.\n"
-" \n"
-"To remove a logging method use the same syntax as you would to add it.\n"
-" \n"
-"Example:\n"
-" %s #anope chanserv/access MESSAGE @\n"
-" Would message any channel operators whenever someone used the\n"
-" ACCESS command on ChanServ on the channel."
#, c-format
msgid "The %s list for %s is full."
-msgstr "The %s list for %s is full."
+msgstr ""
#, c-format
msgid "The %s list has been cleared."
-msgstr "The %s list has been cleared."
+msgstr ""
msgid "The AKILL list has been cleared."
-msgstr "The AKILL list has been cleared."
+msgstr ""
#, c-format
msgid "The Defcon level is now at: %d"
-msgstr "The Defcon level is now at: %d"
-
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr "The E-mail address of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr "The E-mail address of %s will now be shown in %s INFO displays."
+msgstr ""
msgid "The available flags are:"
-msgstr "The available flags are:"
+msgstr ""
msgid ""
"The defcon system can be used to implement a pre-defined\n"
"set of restrictions to services useful during an attempted\n"
"attack on the network."
msgstr ""
-"The defcon system can be used to implement a pre-defined\n"
-"set of restrictions to services useful during an attempted\n"
-"attack on the network."
#, c-format
msgid "The email address %s has reached its usage limit of %d users."
-msgstr "The email address %s has reached its usage limit of %d users."
+msgstr ""
#, c-format
msgid "The email address %s has reached its usage limit of 1 user."
-msgstr "The email address %s has reached its usage limit of 1 user."
+msgstr ""
+
+#, c-format
+msgid "The email address of %s will now be hidden from %s INFO displays."
+msgstr ""
+
+#, c-format
+msgid "The email address of %s will now be shown in %s INFO displays."
+msgstr ""
#, c-format
msgid "The entry message list for %s is full."
-msgstr "The entry message list for %s is full."
+msgstr ""
msgid "The following feature/function names are available:"
-msgstr "The following feature/function names are available:"
+msgstr ""
msgid ""
"The given mask may also be a channel, which will use the\n"
"access list from the other channel up to the given level."
msgstr ""
-"The given mask may also be a channel, which will use the\n"
-"access list from the other channel up to the given level."
#, c-format
msgid "The host %s currently has %d sessions with a limit of %d because it matches entry: %s."
-msgstr "The host %s currently has %d sessions with a limit of %d because it matches entry: %s."
+msgstr ""
#, c-format
msgid "The last memo you sent to %s (sent on %s) has been read."
-msgstr "The last memo you sent to %s (sent on %s) has been read."
+msgstr ""
#, c-format
msgid "The last memo you sent to %s (sent on %s) has not yet been read."
-msgstr "The last memo you sent to %s (sent on %s) has not yet been read."
+msgstr ""
#, c-format
msgid "The last quit message of %s will now be hidden from %s INFO displays."
-msgstr "The last quit message of %s will now be hidden from %s INFO displays."
+msgstr ""
#, c-format
msgid "The last quit message of %s will now be shown in %s INFO displays."
-msgstr "The last quit message of %s will now be shown in %s INFO displays."
+msgstr ""
#, c-format
msgid "The last seen user@host mask of %s will now be hidden from %s INFO displays."
-msgstr "The last seen user@host mask of %s will now be hidden from %s INFO displays."
+msgstr ""
#, c-format
msgid "The last seen user@host mask of %s will now be shown in %s INFO displays."
-msgstr "The last seen user@host mask of %s will now be shown in %s INFO displays."
+msgstr ""
#, c-format
msgid "The limit on %s is not valid."
-msgstr "The limit on %s is not valid."
+msgstr ""
msgid "The mask must contain at least one non wildcard character."
-msgstr "The mask must contain at least one non wildcard character."
+msgstr ""
#, c-format
msgid "The memo limit for %s may not be changed."
-msgstr "The memo limit for %s may not be changed."
+msgstr ""
#, c-format
msgid "The mode lock list of %s is full."
-msgstr "The mode lock list of %s is full."
+msgstr ""
#, c-format
msgid "The new display MUST be a nickname of the nickname group %s."
-msgstr "The new display MUST be a nickname of the nickname group %s."
+msgstr ""
#, c-format
msgid "The new display is now %s."
-msgstr "The new display is now %s."
+msgstr ""
#, c-format
msgid "The nick %s is now being changed to %s."
-msgstr "The nick %s is now being changed to %s."
+msgstr ""
msgid "The old information is the same as the new information specified."
-msgstr "The old information is the same as the new information specified."
+msgstr ""
#, c-format
msgid "The oper info already exists on %s."
-msgstr "The oper info already exists on %s."
+msgstr ""
#, c-format
msgid "The oper info list for %s is full."
-msgstr "The oper info list for %s is full."
+msgstr ""
#, c-format
msgid "The services access status of %s will now be hidden from %s INFO displays."
-msgstr "The services access status of %s will now be hidden from %s INFO displays."
+msgstr ""
#, c-format
msgid "The services access status of %s will now be shown in %s INFO displays."
-msgstr "The services access status of %s will now be shown in %s INFO displays."
+msgstr ""
msgid "The session exception list is empty."
-msgstr "The session exception list is empty."
+msgstr ""
msgid ""
"The user with your nick has been removed. Use this command again\n"
"to release services's hold on your nick."
msgstr ""
-"The user with your nick has been removed. Use this command again\n"
-"to release services's hold on your nick."
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "There are %d memos on channel %s."
+msgid "There are %zu memos on channel %s."
+msgstr ""
msgid ""
"There are no bots available at this time.\n"
"Ask a Services Operator to create one!"
msgstr ""
-"There are no bots available at this time.\n"
-"Ask a Services Operator to create one!"
msgid "There are no configured servers."
-msgstr "There are no configured servers."
+msgstr ""
#, c-format
msgid "There are no forbids of type %s."
-msgstr "There are no forbids of type %s."
+msgstr ""
msgid "There are too many nicks in your group."
-msgstr "There are too many nicks in your group."
+msgstr ""
#, c-format
msgid "There currently are no logging configurations for %s."
-msgstr "There currently are no logging configurations for %s."
+msgstr ""
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "There is %d memo on channel %s."
+msgid "There is %zu memo on channel %s."
+msgstr ""
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
+"Type %s READ %s %zu to read it."
msgstr ""
-"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
#, c-format
msgid "There is no bot assigned to %s anymore."
-msgstr "There is no bot assigned to %s anymore."
+msgstr ""
msgid "There is no logon news."
-msgstr "There is no logon news."
+msgstr ""
msgid "There is no oper news."
-msgstr "There is no oper news."
+msgstr ""
msgid "There is no random news."
-msgstr "There is no random news."
+msgstr ""
#, c-format
msgid "There is no such configuration block %s."
-msgstr "There is no such configuration block %s."
+msgstr ""
#, c-format
msgid "There is no such mode %s."
-msgstr "There is no such mode %s."
+msgstr ""
msgid "There's no email address set for your nick."
-msgstr "There's no email address set for your nick."
+msgstr ""
#, c-format
msgid "This channel has been forbidden: %s"
-msgstr "This channel has been forbidden: %s"
+msgstr ""
msgid "This channel has been suspended."
-msgstr "This channel has been suspended."
+msgstr ""
msgid "This channel is suspended."
-msgstr "This channel is suspended."
+msgstr ""
msgid "This channel may not be used."
-msgstr "This channel may not be used."
+msgstr ""
msgid ""
"This command allows managing DNS zones used for controlling what servers users\n"
@@ -7613,29 +6278,12 @@ msgid ""
" \n"
"The POOL and DEPOOL commands actually add and remove servers to their given zones."
msgstr ""
-"This command allows managing DNS zones used for controlling what servers users\n"
-"are directed to when connecting. Omitting all parameters prints out the status of\n"
-"the DNS zone.\n"
-" \n"
-"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to this\n"
-"zone with the ADDSERVER command.\n"
-" \n"
-"The ADDSERVER command adds a server to the given zone. When a query is done, the\n"
-"zone in question is served if it exists, else all servers in all zones are served.\n"
-"A server may be in more than one zone.\n"
-" \n"
-"The ADDIP command associates an IP with a server.\n"
-" \n"
-"The POOL and DEPOOL commands actually add and remove servers to their given zones."
msgid ""
"This command allows users to set the vhost of their\n"
"CURRENT nick to be the vhost for all nicks in the same\n"
"group."
msgstr ""
-"This command allows users to set the vhost of their\n"
-"CURRENT nick to be the vhost for all nicks in the same\n"
-"group."
msgid ""
"This command also creates a new group for your nickname,\n"
@@ -7643,14 +6291,10 @@ msgid ""
"the same configuration, the same set of memos and the\n"
"same channel privileges."
msgstr ""
-"This command also creates a new group for your nickname,\n"
-"that will allow you to register other nicks later sharing\n"
-"the same configuration, the same set of memos and the\n"
-"same channel privileges."
#, c-format
msgid "This command is an alias to the command %s."
-msgstr "This command is an alias to the command %s."
+msgstr ""
msgid ""
"This command is used by several commands as a way to confirm\n"
@@ -7662,17 +6306,9 @@ msgid ""
"This is also used after the RESETPASS command has been used to\n"
"force identify you to your nick so you may change your password."
msgstr ""
-"This command is used by several commands as a way to confirm\n"
-"changes made to your account.\n"
-" \n"
-"This is most commonly used to confirm your email address once\n"
-"you register or change it.\n"
-" \n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
msgid "This command lists information about the specified loaded module."
-msgstr "This command lists information about the specified loaded module."
+msgstr ""
msgid ""
"This command lists registered vhosts to the operator.\n"
@@ -7683,20 +6319,11 @@ msgid ""
"and Y will be displayed, e.g. #1-3 will display the first 3\n"
"nick/vhost entries."
msgstr ""
-"This command lists registered vhosts to the operator.\n"
-"If a key is specified, only entries whose nick or vhost match\n"
-"the pattern given in key are displayed e.g. Rob* for all\n"
-"entries beginning with \"Rob\"\n"
-"If a #X-Y style is used, only entries between the range of X\n"
-"and Y will be displayed, e.g. #1-3 will display the first 3\n"
-"nick/vhost entries."
msgid ""
"This command loads the module named modname from the modules\n"
"directory."
msgstr ""
-"This command loads the module named modname from the modules\n"
-"directory."
msgid ""
"This command makes your nickname join the target nickname's\n"
@@ -7726,32 +6353,6 @@ msgid ""
" \n"
"Note: all the nicknames of a group have the same password."
msgstr ""
-"This command makes your nickname join the target nickname's\n"
-"group. password is the password of the target nickname.\n"
-" \n"
-"Joining a group will allow you to share your configuration,\n"
-"memos, and channel privileges with all the nicknames in the\n"
-"group, and much more!\n"
-" \n"
-"A group exists as long as it is useful. This means that even\n"
-"if a nick of the group is dropped, you won't lose the\n"
-"shared things described above, as long as there is at\n"
-"least one nick remaining in the group.\n"
-" \n"
-"You may be able to use this command even if you have not registered\n"
-"your nick yet. If your nick is already registered, you'll\n"
-"need to identify yourself before using this command.\n"
-" \n"
-"It is recommended to use this command with a non-registered\n"
-"nick because it will be registered automatically when\n"
-"using this command. You may use it with a registered nick (to\n"
-"change your group) only if your network administrators allowed\n"
-"it.\n"
-" \n"
-"You can only be in one group at a time. Group merging is\n"
-"not possible.\n"
-" \n"
-"Note: all the nicknames of a group have the same password."
msgid ""
"This command manages your auto join list. When you identify\n"
@@ -7759,22 +6360,18 @@ msgid ""
"Services Operators may provide a nick to modify other users'\n"
"auto join lists."
msgstr ""
-"This command manages your auto join list. When you identify\n"
-"you will automatically join the channels on your auto join list.\n"
-"Services Operators may provide a nick to modify other users'\n"
-"auto join lists."
msgid "This command may not be used on this network because nickname ownership is disabled."
-msgstr "This command may not be used on this network because nickname ownership is disabled."
+msgstr ""
msgid "This command reloads the module named modname."
-msgstr "This command reloads the module named modname."
+msgstr ""
msgid "This command retrieves the vhost requests."
-msgstr "This command retrieves the vhost requests."
+msgstr ""
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -7786,17 +6383,6 @@ msgid ""
" Searches the last 21 days worth of logs for messages\n"
" containing Anope and lists the most recent 500 of them."
msgstr ""
-"This command searches the Services logfiles for messages\n"
-"that match the given pattern. The day and limit argument\n"
-"may be used to specify how many days of logs to search\n"
-"and the number of replies to limit to. By default this\n"
-"command searches one week of logs, and limits replies\n"
-"to 50.\n"
-" \n"
-"For example:\n"
-" LOGSEARCH +21d +500l Anope\n"
-" Searches the last 21 days worth of logs for messages\n"
-" containing Anope and lists the most recent 500 of them."
msgid ""
"This command tells you what a users access is on a channel\n"
@@ -7805,11 +6391,6 @@ msgid ""
"this command is limited to users who have the ability to modify\n"
"access entries on the channel."
msgstr ""
-"This command tells you what a users access is on a channel\n"
-"and what access entries, if any, they match. Additionally it\n"
-"will tell you of any auto kick entries they match. Usage of\n"
-"this command is limited to users who have the ability to modify\n"
-"access entries on the channel."
msgid ""
"This command ungroups your nick, or if given, the specified nick,\n"
@@ -7818,126 +6399,103 @@ msgid ""
"is reset. You may not ungroup yourself if there is only one nick in\n"
"your group."
msgstr ""
-"This command ungroups your nick, or if given, the specified nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, and url. Everything else\n"
-"is reset. You may not ungroup yourself if there is only one nick in\n"
-"your group."
msgid "This command unloads the module named modname."
-msgstr "This command unloads the module named modname."
+msgstr ""
msgid "This command will resend you the registration confirmation email."
-msgstr "This command will resend you the registration confirmation email."
-
-#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
msgstr ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
#, c-format
msgid "This nickname has been forbidden: %s"
-msgstr "This nickname has been forbidden: %s"
+msgstr ""
#, c-format
msgid "This nickname has been recovered by %s."
-msgstr "This nickname has been recovered by %s."
+msgstr ""
#, c-format
msgid ""
"This nickname has been recovered by %s. If you did not do\n"
"this then %s may have your password, and you should change it."
msgstr ""
-"This nickname has been recovered by %s. If you did not do\n"
-"this then %s may have your password, and you should change it."
msgid "This nickname has been registered; you may not use it."
-msgstr "This nickname has been registered; you may not use it."
+msgstr ""
msgid "This nickname is suspended."
-msgstr "This nickname is suspended."
+msgstr ""
#, c-format
msgid ""
"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
+"nick, type %s IDENTIFY password. Otherwise,\n"
"please choose a different nick."
msgstr ""
-"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
-"please choose a different nick."
#, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr "To delete, type: %s%s %s %d"
+msgid "To delete, type: %s %s %d"
+msgstr ""
#, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr "To delete, type: %s%s %s %s %d"
+msgid "To delete, type: %s %s %s %d"
+msgstr ""
msgid "To protect ops against bot kicks"
-msgstr "To protect ops against bot kicks"
+msgstr ""
msgid "To protect voices against bot kicks"
-msgstr "To protect voices against bot kicks"
+msgstr ""
msgid ""
"To search for channels starting with #, search for the channel\n"
"name without the #-sign prepended (anope instead of #anope)."
msgstr ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
#, c-format
msgid "Too many results for %s."
-msgstr "Too many results for %s."
+msgstr ""
#, c-format
msgid "Top %i of %s"
-msgstr "Top %i of %s"
+msgstr ""
msgid "Topic"
-msgstr "Topic"
+msgstr ""
msgid "Topic lock"
-msgstr "Topic lock"
+msgstr ""
#, c-format
msgid "Topic lock option for %s is now off."
-msgstr "Topic lock option for %s is now off."
+msgstr ""
#, c-format
msgid "Topic lock option for %s is now on."
-msgstr "Topic lock option for %s is now on."
+msgstr ""
msgid "Topic retention"
-msgstr "Topic retention"
+msgstr ""
#, c-format
msgid "Topic retention option for %s is now off."
-msgstr "Topic retention option for %s is now off."
+msgstr ""
#, c-format
msgid "Topic retention option for %s is now on."
-msgstr "Topic retention option for %s is now on."
+msgstr ""
msgid "Topic set by"
-msgstr "Topic set by"
+msgstr ""
msgid "Turn caps lock OFF!"
-msgstr "Turn caps lock OFF!"
+msgstr ""
msgid "Turn chanstats statistics on or off"
-msgstr "Turn chanstats statistics on or off"
-
-msgid "Turn nickname security on or off"
-msgstr "Turn nickname security on or off"
+msgstr ""
msgid "Turn protection on or off"
-msgstr "Turn protection on or off"
+msgstr ""
#, c-format
msgid ""
@@ -7947,11 +6505,6 @@ msgid ""
"(However, anyone who knows the nickname can still get\n"
"information on it using the INFO command.)"
msgstr ""
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
#, c-format
msgid ""
@@ -7961,35 +6514,12 @@ msgid ""
"(However, anyone who knows your nickname can still get\n"
"information on it using the INFO command.)"
msgstr ""
-"Turns %s's privacy option on or off for your nick.\n"
-"With PRIVATE set, your nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows your nickname can still get\n"
-"information on it using the INFO command.)"
-
-#, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
msgid "Turns chanstats channel statistics ON or OFF for this user."
-msgstr "Turns chanstats channel statistics ON or OFF for this user."
+msgstr ""
msgid "Turns chanstats statistics ON or OFF."
-msgstr "Turns chanstats statistics ON or OFF."
+msgstr ""
#, c-format
msgid ""
@@ -8006,18 +6536,6 @@ msgid ""
"do not use this option unless necessary. Also, your\n"
"network's administrators may have disabled this option."
msgstr ""
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
#, c-format
msgid ""
@@ -8034,89 +6552,59 @@ msgid ""
"do not use this option unless necessary. Also, your\n"
"network's administrators may have disabled this option."
msgstr ""
-"Turns the automatic protection option for your nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take your nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
msgid "Type"
-msgstr "Type"
+msgstr ""
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
"level SET."
msgstr ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option.\n"
-" \n"
-"Note: access to this command is controlled by the\n"
-"level SET."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option. The options will be set on the given\n"
"nickname."
msgstr ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information on a\n"
+"Type %s HELP %s option for more information on a\n"
"particular option."
msgstr ""
-"Type %s%s HELP %s option for more information on a\n"
-"particular option."
#, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
+msgid "Type %s SET EMAIL email in order to set your email."
msgstr ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
msgid "Un-Load a module"
-msgstr "Un-Load a module"
+msgstr ""
#, c-format
msgid "Unable to find regex engine %s."
-msgstr "Unable to find regex engine %s."
+msgstr ""
#, c-format
msgid "Unable to load module %s."
-msgstr "Unable to load module %s."
+msgstr ""
#, c-format
msgid "Unable to remove module %s."
-msgstr "Unable to remove module %s."
+msgstr ""
msgid "Unassigns a bot from a channel"
-msgstr "Unassigns a bot from a channel"
+msgstr ""
msgid ""
"Unassigns a bot from a channel. When you use this command,\n"
@@ -8125,201 +6613,201 @@ msgid ""
"be able to reassign a bot later without having to reconfigure\n"
"it entirely."
msgstr ""
-"Unassigns a bot from a channel. When you use this command,\n"
-"the bot won't join the channel anymore. However, bot\n"
-"configuration for the channel is kept, so you will always\n"
-"be able to reassign a bot later without having to reconfigure\n"
-"it entirely."
msgid "Underlines kicker"
-msgstr "Underlines kicker"
+msgstr ""
msgid "Unknown SET option."
-msgstr "Unknown SET option."
+msgstr ""
#, c-format
msgid "Unknown STATS option: %s"
-msgstr "Unknown STATS option: %s"
+msgstr ""
#, c-format
msgid "Unknown command %s."
-msgstr "Unknown command %s."
+msgstr ""
#, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Unknown command %s. \"%s%s HELP\" for help."
+msgid "Unknown command %s. \"%s HELP\" for help."
+msgstr ""
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s?"
+msgstr ""
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
+msgstr ""
#, c-format
msgid "Unknown mode character %c ignored."
-msgstr "Unknown mode character %c ignored."
+msgstr ""
#, c-format
msgid "Unknown parameter: %s"
-msgstr "Unknown parameter: %s"
+msgstr ""
+
+#, c-format
+msgid "Unknown passwords: %zu"
+msgstr ""
msgid "Unpooled"
-msgstr "Unpooled"
+msgstr ""
msgid ""
"Unregisters the named channel. Can only be used by\n"
"the channel founder."
msgstr ""
-"Unregisters the named channel. Can only be used by\n"
-"the channel founder."
msgid ""
"Unregisters the specified channel. Only Services Operators\n"
"can drop a channel of which they are not the founder of."
msgstr ""
-"Unregisters the specified channel. Only Services Operators\n"
-"can drop a channel of which they are not the founder of."
msgid "Unsuspend a given nick"
-msgstr "Unsuspend a given nick"
+msgstr ""
msgid "Unsuspends a nickname which allows it to be used again."
-msgstr "Unsuspends a nickname which allows it to be used again."
+msgstr ""
msgid ""
"Updates a selected nicks status modes on a channel. If nick is\n"
"omitted then your status is updated. If channel is omitted then\n"
"your channel status is updated on every channel you are in."
msgstr ""
-"Updates a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is updated. If channel is omitted then\n"
-"your channel status is updated on every channel you are in."
msgid "Updates a selected nicks status on a channel"
-msgstr "Updates a selected nicks status on a channel"
+msgstr ""
msgid "Updates your current status, i.e. it checks for new memos"
-msgstr "Updates your current status, i.e. it checks for new memos"
+msgstr ""
msgid ""
"Updates your current status, i.e. it checks for new memos,\n"
"sets needed channel modes and updates your vhost and\n"
"your userflags (lastseentime, etc)."
msgstr ""
-"Updates your current status, i.e. it checks for new memos,\n"
-"sets needed channel modes and updates your vhost and\n"
-"your userflags (lastseentime, etc)."
msgid "Updating databases."
-msgstr "Updating databases."
+msgstr ""
#, c-format
msgid "Uplink capab: %s"
-msgstr "Uplink capab: %s"
+msgstr ""
#, c-format
msgid "Uplink server: %s"
-msgstr "Uplink server: %s"
+msgstr ""
#, c-format
msgid "Use the %s ALL command to list all commands and their descriptions."
-msgstr "Use the %s ALL command to list all commands and their descriptions."
+msgstr ""
msgid "Used on"
-msgstr "Used on"
+msgstr ""
msgid "Used to manage channels"
-msgstr "Used to manage channels"
+msgstr ""
msgid "Used to manage the list of privileged users"
-msgstr "Used to manage the list of privileged users"
+msgstr ""
msgid "Used to modify the channel status of you or other users"
-msgstr "Used to modify the channel status of you or other users"
+msgstr ""
+
+#, c-format
+msgid "User %s isn't currently logged in to an account."
+msgstr ""
msgid "User has been banned from the channel"
-msgstr "User has been banned from the channel"
+msgstr ""
#, c-format
msgid "User limit for %s removed."
-msgstr "User limit for %s removed."
+msgstr ""
#, c-format
msgid "User limit for %s set to %d."
-msgstr "User limit for %s set to %d."
+msgstr ""
msgid "Users"
-msgstr "Users"
+msgstr ""
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Users (nick): %lu entries, %lu buckets, longest chain is %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
+msgstr ""
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Users (uid): %lu entries, %lu buckets, longest chain is %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
+msgstr ""
msgid "Users list:"
-msgstr "Users list:"
+msgstr ""
msgid "VHost"
-msgstr "VHost"
+msgstr ""
+
+#, c-format
+msgid "VHost for %s removed."
+msgstr ""
#, c-format
msgid "VHost for %s set to %s."
-msgstr "VHost for %s set to %s."
+msgstr ""
#, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "VHost for %s set to %s@%s."
+msgid "VHost for %s has been activated."
+msgstr ""
+
+#, c-format
+msgid "VHost for %s has been rejected."
+msgstr ""
#, c-format
msgid "VHost for group %s set to %s."
-msgstr "VHost for group %s set to %s."
+msgstr ""
#, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "VHost for group %s set to %s@%s."
+msgid "VHosts for group %s have been removed."
+msgstr ""
msgid "VIEW host"
-msgstr "VIEW host"
+msgstr ""
msgid "VIEW [mask | list | id]"
-msgstr "VIEW [mask | list | id]"
+msgstr ""
msgid "VIEW [mask | list]"
-msgstr "VIEW [mask | list]"
+msgstr ""
msgid "Value"
-msgstr "Value"
+msgstr ""
#, c-format
msgid "Value of %s:%s changed to %s"
-msgstr "Value of %s:%s changed to %s"
-
-msgid "Vhost"
-msgstr "Vhost"
-
-#, c-format
-msgid "Vhost for %s removed."
-msgstr "Vhost for %s removed."
+msgstr ""
msgid "View and change Services Operators"
-msgstr "View and change Services Operators"
+msgstr ""
msgid "View and change configuration file settings"
-msgstr "View and change configuration file settings"
+msgstr ""
msgid "View the list of host sessions"
-msgstr "View the list of host sessions"
+msgstr ""
msgid "Voices protection"
-msgstr "Voices protection"
+msgstr ""
msgid "Watch your language!"
-msgstr "Watch your language!"
+msgstr ""
#, c-format
msgid ""
"When private is set, the channel will not appear in\n"
"%s's %s command."
msgstr ""
-"When private is set, the channel will not appear in\n"
-"%s's %s command."
msgid ""
"Without a parameter, displays information on the number of\n"
@@ -8333,16 +6821,6 @@ msgid ""
"for the given nickname. This is limited to Services\n"
"Operators."
msgstr ""
-"Without a parameter, displays information on the number of\n"
-"memos you have, how many of them are unread, and how many\n"
-"total memos you can receive.\n"
-" \n"
-"With a channel parameter, displays the same information for\n"
-"the given channel.\n"
-" \n"
-"With a nickname parameter, displays the same information\n"
-"for the given nickname. This is limited to Services\n"
-"Operators."
msgid ""
"Without a parameter, reverses the effect of the IDENTIFY\n"
@@ -8351,22 +6829,14 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
-"Without a parameter, reverses the effect of the IDENTIFY\n"
-"command, i.e. make you not recognized as the real owner of the nick\n"
-"anymore. Note, however, that you won't be asked to reidentify\n"
-"yourself.\n"
-" \n"
-"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
-"to re-identify. This is limited to Services Operators."
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -8374,22 +6844,8 @@ msgid ""
"The RESET option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
-"The UPLINK option displays information about the current\n"
-"server Anope uses as an uplink to the network.\n"
-" \n"
-"The HASH option displays information about the hash maps.\n"
-" \n"
-"The ALL option displays all of the above statistics."
-msgstr ""
-"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
-" \n"
-"With the AKILL option, displays the current size of the\n"
-"AKILL list and the current default expiry time.\n"
-" \n"
-"The RESET option currently resets the maximum user count\n"
-"to the number of users currently present on the network.\n"
+"The PASSWORD option displays the encryption algorithms used\n"
+"for user passwords.\n"
" \n"
"The UPLINK option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
@@ -8397,633 +6853,569 @@ msgstr ""
"The HASH option displays information about the hash maps.\n"
" \n"
"The ALL option displays all of the above statistics."
+msgstr ""
msgid "Word"
-msgstr "Word"
+msgstr ""
#, c-format
msgid "You are already a member of the group of %s."
-msgstr "You are already a member of the group of %s."
+msgstr ""
msgid "You are already identified."
-msgstr "You are already identified."
+msgstr ""
#, c-format
msgid "You are already in %s!"
-msgstr "You are already in %s!"
+msgstr ""
msgid "You are no longer a super admin."
-msgstr "You are no longer a super admin."
+msgstr ""
msgid "You are not identified."
-msgstr "You are not identified."
+msgstr ""
msgid "You are not permitted to be on this channel."
-msgstr "You are not permitted to be on this channel."
+msgstr ""
msgid "You are not permitted to change your memo limit."
-msgstr "You are not permitted to change your memo limit."
+msgstr ""
msgid "You are not using a client certificate."
-msgstr "You are not using a client certificate."
+msgstr ""
msgid "You are now a super admin."
-msgstr "You are now a super admin."
-
-msgid "You are now an IRC Operator."
-msgstr "You are now an IRC Operator."
+msgstr ""
msgid "You are now identified for your nick. Change your password now."
-msgstr "You are now identified for your nick. Change your password now."
+msgstr ""
#, c-format
msgid "You are now in the group of %s."
-msgstr "You are now in the group of %s."
+msgstr ""
#, c-format
msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
-msgstr "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
+msgstr ""
-msgid "You can not NOOP Services."
-msgstr "You can not NOOP Services."
+msgid "You can not NOOP services."
+msgstr ""
msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
-msgstr "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
+msgstr ""
msgid "You can not jupe an already juped server."
-msgstr "You can not jupe an already juped server."
+msgstr ""
+
+msgid "You can not jupe your services' pseudoserver or your uplink server."
+msgstr ""
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "You can not jupe your Services' pseudoserver or your uplink server."
+msgid "You can not queue any more messages."
+msgstr ""
#, c-format
msgid "You can not reload this module directly, instead reload %s."
-msgstr "You can not reload this module directly, instead reload %s."
+msgstr ""
msgid "You can not request a receipt when sending a memo to yourself."
-msgstr "You can not request a receipt when sending a memo to yourself."
+msgstr ""
+
+msgid "You can not send a single message while you have messages queued."
+msgstr ""
#, c-format
msgid "You can't %s yourself!"
-msgstr "You can't %s yourself!"
+msgstr ""
msgid "You can't add a channel to its own access list."
-msgstr "You can't add a channel to its own access list."
+msgstr ""
#, c-format
msgid "You can't logout %s, they are a Services Operator."
-msgstr "You can't logout %s, they are a Services Operator."
-
-#, c-format
-msgid "You cannot %s on this network."
-msgstr "You cannot %s on this network."
+msgstr ""
#, c-format
msgid "You cannot set the %c flag."
-msgstr "You cannot set the %c flag."
+msgstr ""
#, c-format
msgid "You cannot set the memo limit for %s higher than %d."
-msgstr "You cannot set the memo limit for %s higher than %d."
+msgstr ""
#, c-format
msgid "You cannot set your memo limit higher than %d."
-msgstr "You cannot set your memo limit higher than %d."
+msgstr ""
msgid "You cannot unassign bots while persist is set on the channel."
-msgstr "You cannot unassign bots while persist is set on the channel."
+msgstr ""
-msgid "You cannot unset the e-mail on this network."
-msgstr "You cannot unset the e-mail on this network."
+msgid "You cannot unset the email on this network."
+msgstr ""
msgid "You cannot use this command."
-msgstr "You cannot use this command."
+msgstr ""
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "You currently have %d memos, of which %d are unread."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr ""
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "You currently have %d memos, of which 1 is unread."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr ""
#, c-format
-msgid "You currently have %d memos."
-msgstr "You currently have %d memos."
+msgid "You currently have %zu memos."
+msgstr ""
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "You currently have %d memos; all of them are unread."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr ""
msgid "You currently have 1 memo, and it has not yet been read."
-msgstr "You currently have 1 memo, and it has not yet been read."
+msgstr ""
msgid "You currently have 1 memo."
-msgstr "You currently have 1 memo."
+msgstr ""
msgid "You currently have no memos."
-msgstr "You currently have no memos."
+msgstr ""
#, c-format
msgid "You do not have access to set mode %c."
-msgstr "You do not have access to set mode %c."
+msgstr ""
+
+msgid "You do not have any messages queued and did not specify a message to send."
+msgstr ""
+
+msgid "You do not have any queued messages."
+msgstr ""
#, c-format
msgid "You do not have the access to change %s's modes."
-msgstr "You do not have the access to change %s's modes."
+msgstr ""
#, c-format
msgid "You found me, %s!"
-msgstr "You found me, %s!"
+msgstr ""
#, c-format
-msgid "You have %d new memos."
-msgstr "You have %d new memos."
-
-msgid "You have 1 new memo."
-msgstr "You have 1 new memo."
+msgid "You have %d new memo."
+msgid_plural "You have %d new memos."
+msgstr[0] ""
+msgstr[1] ""
#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
+"Type %s READ %zu to read it."
msgstr ""
-"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
#, c-format
msgid "You have been invited to %s by %s."
-msgstr "You have been invited to %s by %s."
+msgstr ""
#, c-format
msgid "You have been invited to %s."
-msgstr "You have been invited to %s."
+msgstr ""
#, c-format
msgid "You have been logged in as %s."
-msgstr "You have been logged in as %s."
+msgstr ""
msgid "You have been logged out."
-msgstr "You have been logged out."
+msgstr ""
#, c-format
msgid "You have been unbanned from %s."
-msgstr "You have been unbanned from %s."
+msgstr ""
#, c-format
msgid "You have been unbanned from %d channels."
-msgstr "You have been unbanned from %d channels."
+msgstr ""
msgid "You have no limit on the number of memos you may keep."
-msgstr "You have no limit on the number of memos you may keep."
+msgstr ""
msgid "You have no memos."
-msgstr "You have no memos."
+msgstr ""
+
+msgid "You have no messages queued."
+msgstr ""
msgid "You have no new memos."
-msgstr "You have no new memos."
+msgstr ""
#, c-format
msgid "You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
-msgstr "You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
+msgstr ""
#, c-format
msgid "You have regained control of %s."
-msgstr "You have regained control of %s."
+msgstr ""
msgid "You may drop any nick within your group."
-msgstr "You may drop any nick within your group."
+msgstr ""
#, c-format
msgid "You may not (un)lock mode %c."
-msgstr "You may not (un)lock mode %c."
-
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "You may not change the e-mail of other Services Operators."
+msgstr ""
msgid "You may not change the email of an unconfirmed account."
-msgstr "You may not change the email of an unconfirmed account."
+msgstr ""
+
+msgid "You may not change the email of other Services Operators."
+msgstr ""
msgid "You may not change the password of other Services Operators."
-msgstr "You may not change the password of other Services Operators."
+msgstr ""
-msgid "You may not drop other Services Operators' nicknames."
-msgstr "You may not drop other Services Operators' nicknames."
+#, c-format
+msgid "You may not drop %s as it is the display nick for the account."
+msgstr ""
-msgid "You may not get the password of other Services Operators."
-msgstr "You may not get the password of other Services Operators."
+msgid "You may not drop other Services Operators' nicknames."
+msgstr ""
msgid "You may not suspend other Services Operators' nicknames."
-msgstr "You may not suspend other Services Operators' nicknames."
-
-msgid "You may view but not modify the access list of other Services Operators."
-msgstr "You may view but not modify the access list of other Services Operators."
+msgstr ""
msgid "You may view but not modify the certificate list of other Services Operators."
-msgstr "You may view but not modify the certificate list of other Services Operators."
+msgstr ""
#, c-format
msgid "You might see yourself in the mirror, %s."
-msgstr "You might see yourself in the mirror, %s."
+msgstr ""
msgid "You must assign a bot to the channel before using this command."
-msgstr "You must assign a bot to the channel before using this command."
+msgstr ""
msgid "You must be a channel operator to register the channel."
-msgstr "You must be a channel operator to register the channel."
+msgstr ""
#, c-format
msgid "You must be in %s to use this command."
-msgstr "You must be in %s to use this command."
+msgstr ""
msgid "You must be logged into an account to use that command."
-msgstr "You must be logged into an account to use that command."
+msgstr ""
msgid "You must confirm your account before you can register a channel."
-msgstr "You must confirm your account before you can register a channel."
+msgstr ""
msgid "You must confirm your account before you may request a vhost."
-msgstr "You must confirm your account before you may request a vhost."
+msgstr ""
msgid "You must confirm your account before you may send a memo."
-msgstr "You must confirm your account before you may send a memo."
-
-#, c-format
-msgid "You must enter the channel name twice as a confirmation that you wish to drop %s."
-msgstr "You must enter the channel name twice as a confirmation that you wish to drop %s."
-
-#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr "You must have been using this nick for at least %d seconds to register."
+msgstr ""
#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
-msgstr "You must have the %s(ME) privilege on the channel to use this command."
+msgstr ""
msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
+"You must now supply an email for your nick.\n"
+"This email will allow you to retrieve your password in\n"
"case you forget it."
msgstr ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
-"case you forget it."
+
+#, c-format
+msgid "You must wait %s before registering your nick."
+msgstr ""
msgid "You need to be identified to use this command."
-msgstr "You need to be identified to use this command."
+msgstr ""
msgid "You will be notified by message and by mail when new memos arrive."
-msgstr "You will be notified by message and by mail when new memos arrive."
+msgstr ""
msgid "You will be notified of new memos at logon and when they arrive, and by mail when they arrive."
-msgstr "You will be notified of new memos at logon and when they arrive, and by mail when they arrive."
+msgstr ""
msgid "You will be notified of new memos at logon and when they arrive."
-msgstr "You will be notified of new memos at logon and when they arrive."
+msgstr ""
msgid "You will be notified of new memos at logon, and by mail when they arrive."
-msgstr "You will be notified of new memos at logon, and by mail when they arrive."
+msgstr ""
msgid "You will be notified of new memos at logon."
-msgstr "You will be notified of new memos at logon."
+msgstr ""
msgid "You will be notified when new memos arrive."
-msgstr "You will be notified when new memos arrive."
+msgstr ""
msgid "You will no longer be able to receive memos."
-msgstr "You will no longer be able to receive memos."
+msgstr ""
msgid "You will no longer be informed via email."
-msgstr "You will no longer be informed via email."
+msgstr ""
msgid "You will not be notified of new memos."
-msgstr "You will not be notified of new memos."
+msgstr ""
msgid "You will now be informed about new memos via email."
-msgstr "You will now be informed about new memos via email."
+msgstr ""
msgid "Your IRCd does not support SVSJOIN."
-msgstr "Your IRCd does not support SVSJOIN."
+msgstr ""
msgid "Your IRCd does not support SVSNICK."
-msgstr "Your IRCd does not support SVSNICK."
+msgstr ""
msgid "Your IRCd does not support SVSPART."
-msgstr "Your IRCd does not support SVSPART."
+msgstr ""
+
+msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
+msgstr ""
-msgid "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
-msgstr "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
+#, c-format
+msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
+msgstr ""
#, c-format
msgid "Your account %s has been successfully created."
-msgstr "Your account %s has been successfully created."
+msgstr ""
msgid "Your account is already confirmed."
-msgstr "Your account is already confirmed."
+msgstr ""
#, c-format
msgid "Your account will expire, if not confirmed, in %s."
-msgstr "Your account will expire, if not confirmed, in %s."
+msgstr ""
#, c-format
msgid "Your email address has been changed to %s."
-msgstr "Your email address has been changed to %s."
+msgstr ""
msgid "Your email address is not allowed, choose a different one."
-msgstr "Your email address is not allowed, choose a different one."
+msgstr ""
msgid "Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you."
-msgstr "Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you."
+msgstr ""
#, c-format
msgid "Your email address of %s has been confirmed."
-msgstr "Your email address of %s has been confirmed."
+msgstr ""
#, c-format
msgid "Your email has been updated to %s"
-msgstr "Your email has been updated to %s"
+msgstr ""
#, c-format
msgid "Your email has been updated to %s."
-msgstr "Your email has been updated to %s."
+msgstr ""
msgid "Your memo limit has been disabled."
-msgstr "Your memo limit has been disabled."
+msgstr ""
#, c-format
msgid "Your memo limit has been set to %d."
-msgstr "Your memo limit has been set to %d."
+msgstr ""
#, c-format
msgid "Your memo limit is %d, and may not be changed."
-msgstr "Your memo limit is %d, and may not be changed."
+msgstr ""
#, c-format
msgid "Your memo limit is %d."
-msgstr "Your memo limit is %d."
+msgstr ""
msgid "Your memo limit is 0; you will not receive any new memos."
-msgstr "Your memo limit is 0; you will not receive any new memos."
+msgstr ""
msgid "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
-msgstr "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
+msgstr ""
+
+msgid "Your message has been queued."
+msgstr ""
+
+msgid "Your message queue has been cleared."
+msgstr ""
msgid "Your nick has been logged out."
-msgstr "Your nick has been logged out."
+msgstr ""
msgid "Your nick is already registered."
-msgstr "Your nick is already registered."
+msgstr ""
msgid "Your nick is not grouped to anything, you can't ungroup it."
-msgstr "Your nick is not grouped to anything, you can't ungroup it."
+msgstr ""
msgid "Your nick isn't registered."
-msgstr "Your nick isn't registered."
+msgstr ""
#, c-format
msgid "Your nickname is now being changed to %s"
-msgstr "Your nickname is now being changed to %s"
+msgstr ""
msgid "Your oper block doesn't require logging in."
-msgstr "Your oper block doesn't require logging in."
+msgstr ""
#, c-format
msgid "Your passcode has been re-sent to %s."
-msgstr "Your passcode has been re-sent to %s."
+msgstr ""
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Your password is %s - remember this for later use."
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr ""
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr "Your password is too long. It must not exceed %u characters."
+msgid "Your password is too short. It must be longer than %u characters."
+msgstr ""
msgid "Your password reset request has expired."
-msgstr "Your password reset request has expired."
+msgstr ""
-msgid "Your vHost has been requested."
-msgstr "Your vHost has been requested."
+msgid "Your vhost has been requested."
+msgstr ""
#, c-format
msgid "Your vhost of %s is now activated."
-msgstr "Your vhost of %s is now activated."
-
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "Your vhost of %s@%s is now activated."
+msgstr ""
msgid "Your vhost was removed and the normal cloaking restored."
-msgstr "Your vhost was removed and the normal cloaking restored."
+msgstr ""
msgid "Zone"
-msgstr "Zone"
+msgstr ""
#, c-format
msgid "Zone %s already exists."
-msgstr "Zone %s already exists."
+msgstr ""
#, c-format
msgid "Zone %s does not exist."
-msgstr "Zone %s does not exist."
+msgstr ""
#, c-format
msgid "Zone %s removed."
-msgstr "Zone %s removed."
+msgstr ""
msgid "[1|2|3|4|5]"
-msgstr "[1|2|3|4|5]"
+msgstr ""
#, c-format
msgid "[Logon News - %s] %s"
-msgstr "[Logon News - %s] %s"
+msgstr ""
#, c-format
msgid "[Oper News - %s] %s"
-msgstr "[Oper News - %s] %s"
+msgstr ""
#, c-format
msgid "[Random News - %s] %s"
-msgstr "[Random News - %s] %s"
+msgstr ""
msgid "[account] password"
-msgstr "[account] password"
+msgstr ""
msgid "[channel [nick]]"
-msgstr "[channel [nick]]"
+msgstr ""
msgid "[channel] ADD entry"
-msgstr "[channel] ADD entry"
+msgstr ""
msgid "[channel] DEL entry"
-msgstr "[channel] DEL entry"
+msgstr ""
msgid "[channel] LIST"
-msgstr "[channel] LIST"
+msgstr ""
msgid "[channel] [list | NEW]"
-msgstr "[channel] [list | NEW]"
+msgstr ""
msgid "[channel] [nick]"
-msgstr "[channel] [nick]"
+msgstr ""
msgid "[channel] {num | list | LAST | ALL}"
-msgstr "[channel] {num | list | LAST | ALL}"
+msgstr ""
msgid "[channel] {num | list | LAST | NEW | ALL}"
-msgstr "[channel] {num | list | LAST | NEW | ALL}"
+msgstr ""
msgid "[key|#X-Y]"
-msgstr "[key|#X-Y]"
+msgstr ""
+
+msgid "[message]"
+msgstr ""
msgid "[nick | channel]"
-msgstr "[nick | channel]"
+msgstr ""
msgid "[nick]"
-msgstr "[nick]"
+msgstr ""
msgid "[nickname [REVALIDATE]]"
-msgstr "[nickname [REVALIDATE]]"
+msgstr ""
msgid "[nickname]"
-msgstr "[nickname]"
+msgstr ""
msgid "[parameter]"
-msgstr "[parameter]"
+msgstr ""
msgid "[+daysd] [+limitl] pattern"
-msgstr "[+daysd] [+limitl] pattern"
+msgstr ""
msgid "[+expiry] channel reason"
-msgstr "[+expiry] channel reason"
+msgstr ""
msgid "[Hostname hidden]"
-msgstr "[Hostname hidden]"
+msgstr ""
msgid "[Suspended]"
-msgstr "[Suspended]"
+msgstr ""
msgid "[Unconfirmed]"
-msgstr "[Unconfirmed]"
+msgstr ""
-msgid "[auto memo] Your requested vHost has been approved."
-msgstr "[auto memo] Your requested vHost has been approved."
+#, c-format
+msgid "[auto memo] VHost %s has been requested by %s."
+msgstr ""
-msgid "[auto memo] Your requested vHost has been rejected."
-msgstr "[auto memo] Your requested vHost has been rejected."
+msgid "[auto memo] Your requested vhost has been approved."
+msgstr ""
-#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr "[auto memo] Your requested vHost has been rejected. Reason: %s"
+msgid "[auto memo] Your requested vhost has been rejected."
+msgstr ""
#, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "[auto memo] vHost %s has been requested by %s."
+msgid "[auto memo] Your requested vhost has been rejected. Reason: %s"
+msgstr ""
msgid "[{pattern | channel} [INVISIBLE]]"
-msgstr "[{pattern | channel} [INVISIBLE]]"
+msgstr ""
msgid "[{pattern | nick} [SECRET]]"
-msgstr "[{pattern | nick} [SECRET]]"
-
-msgid "day"
-msgstr "day"
-
-msgid "days"
-msgstr "days"
+msgstr ""
msgid "does not expire"
-msgstr "does not expire"
-
-#, c-format
-msgid "expires in %d day"
-msgstr "expires in %d day"
-
-#, c-format
-msgid "expires in %d days"
-msgstr "expires in %d days"
-
-#, c-format
-msgid "expires in %d hour, %d minute"
-msgstr "expires in %d hour, %d minute"
-
-#, c-format
-msgid "expires in %d hour, %d minutes"
-msgstr "expires in %d hour, %d minutes"
-
-#, c-format
-msgid "expires in %d hours, %d minute"
-msgstr "expires in %d hours, %d minute"
-
-#, c-format
-msgid "expires in %d hours, %d minutes"
-msgstr "expires in %d hours, %d minutes"
-
-#, c-format
-msgid "expires in %d minute"
-msgstr "expires in %d minute"
+msgstr ""
#, c-format
-msgid "expires in %d minutes"
-msgstr "expires in %d minutes"
+msgid "expires in %s"
+msgstr ""
msgid "expires momentarily"
-msgstr "expires momentarily"
-
-msgid "hour"
-msgstr "hour"
-
-msgid "hours"
-msgstr "hours"
+msgstr ""
#, c-format
msgid "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-
-msgid "minute"
-msgstr "minute"
-
-msgid "minutes"
-msgstr "minutes"
+msgstr ""
msgid "not assigned yet"
-msgstr "not assigned yet"
-
-msgid "second"
-msgstr "second"
-
-msgid "seconds"
-msgstr "seconds"
-
-#, c-format
-msgid "vHost for %s has been activated."
-msgstr "vHost for %s has been activated."
-
-#, c-format
-msgid "vHost for %s has been rejected."
-msgstr "vHost for %s has been rejected."
+msgstr ""
msgid "vhost"
-msgstr "vhost"
-
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "vhosts for group %s have been removed."
-
-msgid "year"
-msgstr "year"
-
-msgid "years"
-msgstr "years"
+msgstr ""
msgid "{MODIFY|VIEW} [block name item name item value]"
-msgstr "{MODIFY|VIEW} [block name item name item value]"
+msgstr ""
msgid "{channel | nickname}"
-msgstr "{channel | nickname}"
+msgstr ""
msgid "{nick | channel}"
-msgstr "{nick | channel}"
+msgstr ""
msgid "{nick | channel} memo-text"
-msgstr "{nick | channel} memo-text"
+msgstr ""
diff --git a/language/anope.fr_FR.po b/language/anope.fr_FR.po
index 319362469..5ce766b2f 100644
--- a/language/anope.fr_FR.po
+++ b/language/anope.fr_FR.po
@@ -7,24 +7,26 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-01-06 18:19+0100\n"
-"PO-Revision-Date: 2024-01-05 19:37+0100\n"
-"Last-Translator: Thomas Fargeix <t.fargeix@gmail.com>\n"
+"POT-Creation-Date: 2024-12-12 17:11+0000\n"
+"PO-Revision-Date: 2024-11-25 01:32+0000\n"
+"Last-Translator: Val Lorentz <progval+git@progval.net>\n"
"Language-Team: French\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-"X-Generator: Poedit 3.2.2\n"
+"X-Generator: Poedit 3.4.2\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
msgstr "%d canau(x) vidé(s) et %d canau(x) supprimé(s)."
#, c-format
-msgid "%d nickname(s) dropped."
-msgstr "%d pseudo(s) effacé(s)."
+msgid "%d nickname dropped."
+msgid_plural "%d nicknames dropped."
+msgstr[0] "%d pseudo effacé."
+msgstr[1] "%d pseudos effacés."
#, c-format
msgid "%s added to %s %s list."
@@ -32,39 +34,35 @@ msgstr "%1$s ajouté à la liste des %3$s de %2$s."
#, c-format
msgid "%s added to %s access list at level %d."
-msgstr "%s ajouté à la liste d'accès de %s avec le niveau %d."
+msgstr "%s ajouté(e) à la liste d'accès de %s avec le niveau %d."
#, c-format
msgid "%s added to %s access list at privilege %s (level %d)"
-msgstr "%s ajouté à la liste d'accès de %s avec le privilège %s (niveau %d)"
+msgstr "%s ajouté(e) à la liste d'accès de %s avec le privilège %s (niveau %d)"
#, c-format
msgid "%s added to %s autokick list."
-msgstr "%s ajouté à la liste de kicks automatiques de %s."
+msgstr "%s ajouté(e) à la liste de kicks automatiques de %s."
#, c-format
msgid "%s added to %s bad words list."
-msgstr "%s ajouté à la liste des mots interdits de %s."
-
-#, c-format
-msgid "%s added to %s's access list."
-msgstr "%s ajouté à la liste d'accès de %s."
+msgstr "%s ajouté(e) à la liste des mots interdits de %s."
#, c-format
msgid "%s added to %s's certificate list."
-msgstr "%s ajouté à la liste des certificats de %s."
+msgstr "%s ajouté(e) à la liste des certificats de %s."
#, c-format
msgid "%s added to ignore list."
-msgstr "%s ajouté à la liste d'ignore."
+msgstr "%s ajouté(e) à la liste d'ignore."
#, c-format
msgid "%s added to the %s list."
-msgstr "%s ajouté à la liste des %s."
+msgstr "%s ajouté(e) à la liste des %s."
#, c-format
msgid "%s added to the AKILL list."
-msgstr "%s ajouté à la liste d'AKILL."
+msgstr "%s ajouté(e) à la liste d'AKILL."
#, c-format
msgid ""
@@ -86,49 +84,49 @@ msgid ""
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
+"below; to use them, type %s command. For\n"
"more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
"%s vous permet d'avoir un bot sur votre canal.\n"
-"Il a été conçu pour les utilisateurs qui ne peuvent\n"
+"Il a été conçu pour les utilisateurices qui ne peuvent\n"
"pas héberger ou configurer un bot, ou pour\n"
"être utilisé sur les réseaux qui n'autorisent pas\n"
-"les bots d'utilisateurs. Les commandes disponibles\n"
+"les bots d'utilisateurices. Les commandes disponibles\n"
"sont listées ci-dessous. Pour les utiliser, tapez\n"
-"%s%s commande. Pour plus d'informations sur\n"
-"une commande spécifique, tapez %s%s %s commande.\n"
+"%s commande. Pour plus d'informations sur\n"
+"une commande spécifique, tapez %s %s commande.\n"
#, c-format
msgid ""
"%s allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
+"nicknames; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
"%s vous permet d'enregistrer un pseudo et d'empêcher les\n"
"autres de l'utiliser. Les commandes suivantes permettent\n"
-" l'enregistrement et la gestion des pseudos. Pour les\n"
-"utiliser, tapez %s%s commande. Pour plus\n"
+"l'enregistrement et la gestion des pseudos. Pour les\n"
+"utiliser, tapez %s commande. Pour plus\n"
"d'informations sur une certaine commande, tapez\n"
-"%s%s %s commande.\n"
+"%s %s commande.\n"
#, c-format
msgid ""
"%s allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
+"accounts; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
"%s vous permet d'enregistrer un compte.\n"
"Les commandes suivantes permettent l'enregistrement et\n"
"la maintenance de comptes.\n"
-"Pour les utiliser, tapez %s%s commande.\n"
+"Pour les utiliser, tapez %s commande.\n"
"Pour plus d'informations sur une commande spécifique, tapez\n"
-"%s%s %s commande.\n"
+"%s %s commande.\n"
#, c-format
msgid ""
@@ -137,17 +135,17 @@ msgid ""
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
+"%s command. For more information on a\n"
+"specific command, type %s HELP command.\n"
msgstr ""
"%s vous permet d'enregistrer et de contrôler divers\n"
-"aspects des canaux. %s empêche souvent les utilisateurs\n"
-"malveillants de faire des \"take overs\" sur les canaux\n"
-"en limitant ceux qui sont autorisés à être OP.\n"
+"aspects des canaux. %s empêche souvent les utilisateurices\n"
+"malveillant(e)s de faire des \"take overs\" sur les canaux\n"
+"en limitant celleux qui sont autorisé(e)s à être OP.\n"
"Les commandes disponibles sont listées ci-dessous,\n"
-"pour les utiliser, tapez %s%s commande. Pour plus \n"
+"pour les utiliser, tapez %s commande. Pour plus \n"
"d'informations sur une commande spécifique, tapez\n"
-"%s%s HELP commande.\n"
+"%s HELP commande.\n"
#, c-format
msgid "%s already exists in %s bad words list."
@@ -167,7 +165,7 @@ msgstr "%s ne peut être utilisé comme nombre de fois avant un ban."
#, c-format
msgid "%s changed your usermodes to %s."
-msgstr "%s a changé vos modes utilisateur en %s."
+msgstr "%s a changé vos modes utilisateurices en %s."
#, c-format
msgid "%s channel list:"
@@ -175,47 +173,47 @@ msgstr "Liste de canaux de %s :"
#, c-format
msgid "%s deleted from %s %s list."
-msgstr "%1$s supprimé de la liste des %3$s de %2$s."
+msgstr "%1$s supprimé(e) de la liste des %3$s de %2$s."
#, c-format
msgid "%s deleted from %s access list."
-msgstr "%s supprimé de la liste d'accès de %s."
+msgstr "%s supprimé(e) de la liste d'accès de %s."
#, c-format
msgid "%s deleted from %s autokick list."
-msgstr "%s supprimé de la liste de kicks automatiques de %s."
+msgstr "%s supprimé(e) de la liste de kicks automatiques de %s."
#, c-format
msgid "%s deleted from %s bad words list."
-msgstr "%s supprimé de la liste des mots interdits de %s."
-
-#, c-format
-msgid "%s deleted from %s's access list."
-msgstr "%s supprimé de la liste d'accès de %s."
+msgstr "%s supprimé(e) de la liste des mots interdits de %s."
#, c-format
msgid "%s deleted from %s's certificate list."
-msgstr "%s supprimé de la liste de certificats de %s."
+msgstr "%s supprimé(e) de la liste de certificats de %s."
#, c-format
msgid "%s deleted from session-limit exception list."
-msgstr "%s supprimé de la liste des exceptions à la limitation de sessions."
+msgstr "%s supprimé(e) de la liste des exceptions à la limitation de sessions."
#, c-format
msgid "%s deleted from the %s list."
-msgstr "%s supprimé de la liste des %s."
+msgstr "%s supprimé(e) de la liste des %s."
#, c-format
msgid "%s deleted from the AKILL list."
-msgstr "%s supprimé de la liste d'AKILL."
+msgstr "%s supprimé(e) de la liste d'AKILL."
#, c-format
msgid "%s disabled on channel %s."
msgstr "Le niveau %s est maintenant désactivé sur le canal %s."
#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr "%s ne souhaite pas être ajouté(e) aux listes d'accès de canaux."
+
+#, c-format
msgid "%s has been invited to %s."
-msgstr "%s a été invité sur %s."
+msgstr "%s a été invité(e) sur %s."
#, c-format
msgid "%s has been joined to %s."
@@ -227,7 +225,7 @@ msgstr "%s a été PART de %s."
#, c-format
msgid "%s has been unbanned from %s."
-msgstr "%s a été débanni de %s."
+msgstr "%s a été débanni(e) de %s."
#, c-format
msgid "%s has no access in any channels."
@@ -243,7 +241,7 @@ msgstr "%s a trop de canaux enregistrés."
#, c-format
msgid "%s is a super administrator."
-msgstr "%s est un super-administrateur."
+msgstr "%s est un super-administrateurice."
#, c-format
msgid ""
@@ -254,17 +252,17 @@ msgid ""
"registered in order to send a memo.\n"
"%s's commands include:"
msgstr ""
-"%s est un utilitaire permettant aux utilisateurs IRC\n"
-"d'envoyer de courts messages aux autres utilisateurs IRC,\n"
+"%s est un utilitaire permettant aux utilisateurices IRC\n"
+"d'envoyer de courts messages aux autres utilisateurices IRC,\n"
"qu'ils soient connectés à ce moment là ou non, ou aux \n"
-"canaux(*). Le pseudo de l'expéditeur et du destinataire (ou\n"
+"canaux(*). Les pseudos d'expéditeurice et destinataire (ou\n"
"du canal) doivent être enregistrés pour pouvoir envoyer un\n"
"mémo.\n"
"Les commandes de %s sont :"
#, c-format
msgid "%s is already in %s!"
-msgstr "%s est déjà sur %s ! "
+msgstr "%s est déjà sur %s !"
#, c-format
msgid "%s is already in %s."
@@ -276,11 +274,11 @@ msgstr "%s ajouté à votre liste d'ignore."
#, c-format
msgid "%s is already suspended."
-msgstr "%s est déjà suspendu."
+msgstr "%s est déjà suspendu(e)."
#, c-format
msgid "%s is not a registered unforbidden nick or channel."
-msgstr "%s n'est pas un pseudo ou canal enregistré qui n'est pas interdit."
+msgstr "%s n'est pas un pseudo ou canal enregistré interdit."
#, c-format
msgid "%s is not a valid ban type."
@@ -291,7 +289,7 @@ msgid "%s is not a valid bot or registered channel."
msgstr "%s n'est pas un bot ou canal enregistré valide."
#, c-format
-msgid "%s is not a valid e-mail address."
+msgid "%s is not a valid email address."
msgstr "%s n'est pas une adresse email valide."
#, c-format
@@ -304,7 +302,7 @@ msgstr "%s n'est pas sur %s."
#, c-format
msgid "%s is not on the ignore list."
-msgstr "%s n'a pas été trouvé dans la liste des ignorés."
+msgstr "%s introuvable dans la liste des ignorés."
#, c-format
msgid "%s is on the auto kick list of %s (%s)."
@@ -312,7 +310,7 @@ msgstr "%s est dans la liste de kicks automatiques de %s (%s)."
#, c-format
msgid "%s is the founder of %s."
-msgstr "%s est le fondateur de %s."
+msgstr "%s est le/la fondateurice de %s."
#, c-format
msgid "%s matches access entry %s (from entry %s), which has privilege %s."
@@ -324,7 +322,7 @@ msgstr "%s correspond à l'entrée d'accès %s, qui a le privilège %s."
#, c-format
msgid "%s matches an except on %s and cannot be banned until the except has been removed."
-msgstr "%s correspond à une exception sur %s et ne peut pas être banni tant que l'exception n'a pas été supprimée."
+msgstr "%s correspond à une exception sur %s et ne peut pas être banni(e) tant que l'exception n'a pas été supprimée."
#, c-format
msgid "%s matches auto kick entry %s on %s (%s)."
@@ -347,24 +345,20 @@ msgid "%s not found on %s bad words list."
msgstr "%s introuvable sur la liste des mots interdits de %s."
#, c-format
-msgid "%s not found on %s's access list."
-msgstr "%s introuvable sur la liste d'accès de %s."
-
-#, c-format
msgid "%s not found on %s's certificate list."
msgstr "%s introuvable dans la liste de certificats de %s."
#, c-format
msgid "%s not found on ignore list."
-msgstr "%s n'a pas été trouvé dans la liste des ignorés."
+msgstr "%s introuvable dans la liste des ignorés."
#, c-format
msgid "%s not found on session list, but has a limit of %d because it matches entry: %s."
-msgstr "%s non trouvé sur la liste de sessions, mais a une limite de %d parce l'entrée suivante correspond : %s."
+msgstr "%s introuvable sur la liste de sessions, mais a une limite de %d parce l'entrée suivante correspond : %s."
#, c-format
msgid "%s not found on session-limit exception list."
-msgstr "%s non trouvé sur la liste des exceptions à la limitation de sessions."
+msgstr "%s introuvable sur la liste des exceptions à la limitation de sessions."
#, c-format
msgid "%s not found on the %s list."
@@ -376,31 +370,31 @@ msgstr "%s introuvable sur la liste d'AKILL."
#, c-format
msgid "%s removed from the %s access list."
-msgstr "%s supprimé de la liste d'accès de %s."
+msgstr "%s supprimé(e) de la liste d'accès de %s."
#, c-format
msgid "%s removed from the ignore list."
-msgstr "%s supprimé de la liste d'ignorés."
+msgstr "%s supprimé(e) de la liste d'ignorés."
#, c-format
msgid "%s users list:"
-msgstr "Liste des utilisateurs de %s :"
+msgstr "Liste des utilisateurices de %s :"
#, c-format
msgid "%s will no longer be ignored."
-msgstr "%s n'est plus ignoré."
+msgstr "%s n'est plus ignoré(e)."
#, c-format
msgid "%s will now be ignored for %s."
-msgstr "%s est ignoré pour %s."
+msgstr "%s est ignoré(e) pour %s."
#, c-format
msgid "%s will now permanently be ignored."
-msgstr "%s est ignoré définitivement."
+msgstr "%s est ignoré(e) définitivement."
#, c-format
-msgid "%s%s HELP %s for more information."
-msgstr "%s%s HELP %s pour plus d'informations."
+msgid "%s HELP %s for more information."
+msgstr "%s HELP %s pour plus d'informations."
msgid "ADD nick user host real"
msgstr "ADD pseudo user host realname"
@@ -438,7 +432,7 @@ msgstr ""
"Notez que les masques pseudo!user@host et user@host sont invalides !\n"
"Seuls les masques d'hôtes réels, tels que box.host.dom ou *.host.dom,\n"
"sont autorisés parce que la limitation de sessions ne prend pas en compte le\n"
-"pseudo ou l'utilisateur. limite doit être un nombre supérieur ou égal à\n"
+"pseudo ou l'utilisateurice. limite doit être un nombre supérieur ou égal à\n"
"zéro. Cette limite définit combien de sessions sont autorisées simultanément\n"
"pour cet hôte. Une valeur de zéro signifie que l'hôte n'a pas de limite de\n"
"sessions. Consultez l'aide de AKILL pour les détails sur le format du\n"
@@ -462,18 +456,18 @@ msgid ""
"up on the given server. REVOKE removes this\n"
"restriction."
msgstr ""
-"SET kill tous les opérateurs du serveur indiqué\n"
-"et empêche les opérateurs d'opérer sur le serveur indiqué.\n"
+"SET kill toustes les opérateurices du serveur indiqué\n"
+"et empêche les opérateurices d'opérer sur le serveur indiqué.\n"
"REVOKE supprime cette restriction."
#, c-format
msgid ""
"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
+"%s command; type %s HELP LEVELS for\n"
"information."
msgstr ""
-"Les niveaux d'accès utilisateur peuvent être vus en utilisant\n"
-"la commande %s. Tapez %s%s HELP LEVELS pour\n"
+"Les niveaux d'accès utilisateurice peuvent être vus en utilisant\n"
+"la commande %s. Tapez %s HELP LEVELS pour\n"
"plus d'informations."
#, c-format
@@ -495,9 +489,6 @@ msgstr "canal"
msgid "channel bantype"
msgstr "canal type-du-ban"
-msgid "channel channel"
-msgstr "canal canal"
-
msgid "channel command method [status]"
msgstr "canal commande méthode [statut]"
@@ -523,16 +514,16 @@ msgid "channel time"
msgstr "canal temps"
msgid "channel user reason"
-msgstr "canal utilisateur raison"
+msgstr "canal utilisateurice raison"
msgid "channel what"
-msgstr "canal [quoi]"
+msgstr "canal quoi"
-msgid "channel ADD mask"
-msgstr "canal ADD masque"
+msgid "channel ADD mask level [description]"
+msgstr "canal ADD masque niveau [description]"
-msgid "channel ADD mask level"
-msgstr "canal ADD masque niveau"
+msgid "channel ADD mask [description]"
+msgstr "canal ADD mask [description]"
msgid "channel ADD message"
msgstr "canal ADD message"
@@ -600,6 +591,9 @@ msgstr "canal VIEW [masque | numéro-entrée | liste]"
msgid "channel VIEW [mask | list]"
msgstr "canal VIEW [masque | liste]"
+msgid "channel [code]"
+msgstr "canal [modes]"
+
msgid "channel [description]"
msgstr "canal [description]"
@@ -618,8 +612,8 @@ msgstr "canal [+expiration] [raison]"
msgid "channel [+expiry] {nick | mask} [reason]"
msgstr "canal [+expiration] {pseudo | masque} [raison]"
-msgid "channel [MODIFY] mask changes"
-msgstr "canal [MODIFY] masque modifications"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr "canal [MODIFY] masque modifications [description]"
msgid "channel [SET] [topic]"
msgstr "canal [SET] [sujet]"
@@ -681,9 +675,6 @@ msgstr "pseudo canal"
msgid "nick channel [reason]"
msgstr "pseudo canal [raison]"
-msgid "nick flags"
-msgstr "pseudo flags"
-
msgid "nick hostmask"
msgstr "pseudo hostmask"
@@ -714,6 +705,9 @@ msgstr "pseudo nouvel-affichage"
msgid "nickname new-password"
msgstr "pseudo nouveau-motdepasse"
+msgid "nickname [code]"
+msgstr "pseudo [code]"
+
msgid "nickname [parameter]"
msgstr "pseudo [paramètre]"
@@ -768,6 +762,9 @@ msgstr "modèle [SUSPENDED] [NOEXPIRE]"
msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
msgstr "modèle [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
+msgid "server [message]"
+msgstr "nom-du-serveur [message]"
+
msgid "server [reason]"
msgstr "nom-du-serveur [raison]"
@@ -842,12 +839,12 @@ msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
" \n"
"Les comptes qui ne sont plus utilisés sont sujets à \n"
"l'expiration automatique, c'est-à-dire qu'ils seront effacés\n"
-"après %d jours de non utilisation."
+"après %lu jours de non utilisation."
msgid ""
" \n"
@@ -864,7 +861,7 @@ msgid ""
msgstr ""
" \n"
"Le bot rejoindra le canal dès qu'il y a au moins\n"
-"%d utilisateur(s) dessus."
+"%d utilisateurice(s) dessus."
#, c-format
msgid ""
@@ -874,19 +871,19 @@ msgid ""
"fantasy commands on a channel when prefixed\n"
"with one of the following fantasy characters: %s\n"
" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
+"Note that users wanting to use fantasy commands\n"
+"MUST have enough access for both the FANTASY\n"
+"privilege and the command they are executing."
msgstr ""
" \n"
"Active ou désactive le mode fantaisie sur un\n"
"canal. Quand elle est active, cette option\n"
-"permet aux utilisateurs d'utiliser les commandes\n"
+"permet aux utilisateurices d'utiliser les commandes\n"
"précédées par l'un des caractères suivants : %s\n"
" \n"
-"Notez que les utilisateurs souhaitant utiliser\n"
+"Notez que les utilisateurices souhaitant utiliser\n"
"les commandes fantaisistes DOIVENT avoir\n"
-"accès à la fois au niveau FANTASIA et le niveau\n"
+"accès à la fois au niveau FANTASY et le niveau\n"
"correspondant à la commande."
msgid ""
@@ -900,7 +897,7 @@ msgstr ""
"Active ou désactive le mode message d'accueil\n"
"sur un canal. Quand elle est active, cette option\n"
"fait afficher au bot les messages d'accueil de chaque\n"
-"utilisateur qui a un accès suffisant au canal."
+"utilisateurice qui a un accès suffisant au canal."
msgid ""
" \n"
@@ -946,27 +943,27 @@ msgstr ""
#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
" \n"
-"Notez que tout canal non utilisé pendant %d jours\n"
+"Notez que tout canal non utilisé pendant %lu jours\n"
"(c'est-à-dire une période pendant laquelle aucun\n"
-"utilisateur figurant sur la liste d'accès du canal\n"
+"utilisateurice figurant sur la liste d'accès du canal\n"
"ne vient sur le canal) il sera automatiquement effacé."
#, c-format
msgid ""
" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
+"See the %s command (%s HELP ACCESS) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"
msgstr ""
" \n"
-"Voir la commande %s (%s%s HELP ACCESS) pour\n"
+"Voir la commande %s (%s HELP ACCESS) pour\n"
"plus d'informations sur comment donner des privilèges\n"
-"à d'autres utilisateurs du canal.\n"
+"à d'autres utilisateurices du canal.\n"
msgid ""
" \n"
@@ -975,7 +972,7 @@ msgid ""
"any nickname."
msgstr ""
" \n"
-"Les Opérateurs des Services peuvent également effacer n'importe quel\n"
+"Les Opérateurices des Services peuvent également effacer n'importe quel\n"
"pseudo et peuvent voir la liste d'accès pour n'importe quel pseudo."
msgid ""
@@ -985,7 +982,7 @@ msgid ""
"lists and settings for any channel."
msgstr ""
" \n"
-"Les Opérateurs des Services peuvent aussi, en fonction de leurs\n"
+"Les Opérateurices des Services peuvent aussi, en fonction de leurs\n"
"accès, effacer tout canal, voir (et modifier) les listes d'accès, des\n"
"niveaux et des kicks automatiques, ainsi que les paramètres de\n"
"tout canal."
@@ -1067,18 +1064,18 @@ msgstr ""
" \n"
"La commande AKICK DEL supprime le pseudo ou masque\n"
"donné de la liste des kicks automatiques. Cependant, elle ne\n"
-"supprime pas les bans placés par ceux-ci. Ils doivent être\n"
+"supprime pas les bans placés par celleux-ci. Ils doivent être\n"
"supprimés manuellement.\n"
" \n"
"La commande AKICK LIST affiche la liste des kicks\n"
-"automatique, ou éventuellement seulement ceux qui\n"
+"automatiques, ou éventuellement seulement celleux qui\n"
"correspondent au masque indiqué.\n"
" \n"
"La commande AKICK VIEW est une version plus détaillée\n"
"de la commande AKICK LIST.\n"
" \n"
"La commande AKICK ENFORCE fait appliquer la liste des\n"
-"AKICK par %s en expulsant les utilisateurs qui correspondent à\n"
+"AKICK par %s en expulsant les utilisateurices qui correspondent à\n"
"un masque de la liste des kicks automatiques.\n"
" \n"
"La commande AKICK CLEAR vide la liste des kicks\n"
@@ -1225,17 +1222,17 @@ msgid ""
msgstr ""
" \n"
"Cette option empêche un bot d'être attribué à un\n"
-"canal par des utilisateurs qui ne sont pas Opérateurs\n"
+"canal par des utilisateurices qui ne sont pas Opérateurices\n"
"IRC."
#, c-format
msgid ""
" \n"
-"Type %s%s HELP command for help on any of the\n"
+"Type %s HELP command for help on any of the\n"
"above commands."
msgstr ""
" \n"
-"Tapez %s%s HELP command pour obtenir de l'aide sur\n"
+"Tapez %s HELP command pour obtenir de l'aide sur\n"
"les commandes ci-dessus."
#, c-format
@@ -1251,7 +1248,7 @@ msgid " Providing service: %s"
msgstr " Fournit le service : %s"
msgid " This oper is configured in the configuration file."
-msgstr " Cet oper est configuré dans le fichier de configuration."
+msgstr " Cet oper est configuré(e) dans le fichier de configuration."
#, c-format
msgid " Loaded at: %p"
@@ -1259,11 +1256,7 @@ msgstr " Chargé à : %p"
#, c-format
msgid " but %s mysteriously dematerialized."
-msgstr " mais %s s'est mystérieusement dématérialisé."
-
-#, c-format
-msgid "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr "\"/msg %s\" n'est plus supporté. Utilisez \"/msg %s@%s\" ou \"/%s\" à la place."
+msgstr " mais %s s'est mystérieusement dématérialisé(e)."
msgid "\"Jupiter\" a server"
msgstr "\"Jupiter\" un serveur"
@@ -1273,10 +1266,10 @@ msgid "%-8s %s"
msgstr "%-8s %s"
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "%2lu %-16s lettres : %s, mots : %s, lignes : %s, smileys : %s, actions : %s"
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr "%2d %-16s lettres : %s, mots : %s, lignes : %s, smileys : %s, actions : %s"
-msgid "%b %d %H:%M:%S %Y %Z"
+msgid "%b %d %Y %H:%M:%S %Z"
msgstr "%d %b %Y %H:%M:%S %Z"
#, c-format
@@ -1304,8 +1297,34 @@ msgid "%d modules loaded."
msgstr "%d modules chargés."
#, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d pseudo(s) dans le groupe."
+msgid "%lld day"
+msgid_plural "%lld days"
+msgstr[0] "%lld jour"
+msgstr[1] "%lld jours"
+
+#, c-format
+msgid "%lld hour"
+msgid_plural "%lld hours"
+msgstr[0] "%lld heure"
+msgstr[1] "%lld heures"
+
+#, c-format
+msgid "%lld minute"
+msgid_plural "%lld minutes"
+msgstr[0] "%lld minute"
+msgstr[1] "%lld minutes"
+
+#, c-format
+msgid "%lld second"
+msgid_plural "%lld seconds"
+msgstr[0] "%lld seconde"
+msgstr[1] "%lld secondes"
+
+#, c-format
+msgid "%lld year"
+msgid_plural "%lld years"
+msgstr[0] "%lld année"
+msgstr[1] "%lld années"
#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
@@ -1341,39 +1360,39 @@ msgstr "%s (%d répétitions)"
#, c-format
msgid "%s (%s) was kicked from %s (\"%s\") %s ago%s"
-msgstr "%s (%s) a été kické de %s (\"%s\") il y a %s%s"
+msgstr "%s (%s) a été kické(e) de %s (\"%s\") il y a %s%s"
#, c-format
msgid "%s (%s) was kicked from a secret channel %s ago%s"
-msgstr "%s (%s) a été kické d'un canal secret il y a %s%s"
+msgstr "%s (%s) a été kické(e) d'un canal secret il y a %s%s"
#, c-format
msgid "%s (%s) was last seen changing nick from %s to %s %s ago%s"
-msgstr "%s (%s) a été vu pour la dernière fois, changeant son pseudo de %s en %s il y a %s%s"
+msgstr "%s (%s) a été vu(e) pour la dernière fois, changeant son pseudo de %s en %s il y a %s%s"
#, c-format
msgid "%s (%s) was last seen changing nick to %s %s ago%s"
-msgstr "%s (%s) a été vu pour la dernière fois, changeant son pseudo en %s il y a %s%s"
+msgstr "%s (%s) a été vu(e) pour la dernière fois, changeant son pseudo en %s il y a %s%s"
#, c-format
msgid "%s (%s) was last seen connecting %s ago (%s)%s"
-msgstr "%s (%s) s'est connecté pour la dernière fois il y a %s (%s)%s"
+msgstr "%s (%s) s'est connecté(e) pour la dernière fois il y a %s (%s)%s"
#, c-format
msgid "%s (%s) was last seen joining %s %s ago%s"
-msgstr "%s (%s) a été vu pour la dernière fois, joignant %s il y a %s%s"
+msgstr "%s (%s) a été vu(e) pour la dernière fois, rejoignant %s il y a %s%s"
#, c-format
msgid "%s (%s) was last seen joining a secret channel %s ago%s"
-msgstr "%s (%s) a été vu pour la dernière fois, joignant un canal secret il y a %s%s"
+msgstr "%s (%s) a été vu(e) pour la dernière fois, rejoignant un canal secret il y a %s%s"
#, c-format
msgid "%s (%s) was last seen parting %s %s ago%s"
-msgstr "%s (%s) a été vu pour la dernière fois, quittant le canal %s, il y a %s%s"
+msgstr "%s (%s) a été vu(e) pour la dernière fois, quittant le canal %s, il y a %s%s"
#, c-format
msgid "%s (%s) was last seen parting a secret channel %s ago%s"
-msgstr "%s (%s) a été vu pour la dernière fois, quittant un canal secret, il y a %s%s"
+msgstr "%s (%s) a été vu(e) pour la dernière fois, quittant un canal secret, il y a %s%s"
#, c-format
msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
@@ -1404,8 +1423,16 @@ msgid "%s bad words list is empty."
msgstr "La liste des mots interdits de %s est vide."
#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr "%s ne peut plus être ajouté(e) aux liste d'accès de canaux."
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr "%s peut maintenant être ajouté(e) aux listes d'accès de canaux."
+
+#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
-msgstr "%s ne peut être successeur du canal %s car il en est le fondateur."
+msgstr "%s ne peut être successeur(e) du canal %s car il en est le/la fondateurice."
#, c-format
msgid "%s commands:"
@@ -1413,23 +1440,23 @@ msgstr "Commandes %s :"
#, c-format
msgid "%s coverage is too wide; Please use a more specific mask."
-msgstr "%s correspond à trop d'utilisateurs. Merci d'indiquer un masque plus spécifique."
+msgstr "%s correspond à trop d'utilisateurices. Merci d'indiquer un masque plus spécifique."
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s a actuellement %d mémos, dont %d n'ont pas été lus."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr "%s a actuellement %zu mémos, dont %zu n'ont pas été lus."
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s a actuellement %d mémos, dont 1 n'a pas été lu."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr "%s a actuellement %zu mémos, dont 1 n'a pas été lu."
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s a actuellement %d mémos."
+msgid "%s currently has %zu memos."
+msgstr "%s a actuellement %zu mémos."
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s a actuellement %d mémos, dont aucun n'a été lu."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr "%s a actuellement %zu mémos, dont aucun n'a été lu."
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
@@ -1445,7 +1472,7 @@ msgstr "%s n'a actuellement aucun mémo."
#, c-format
msgid "%s deleted from the %s forbid list."
-msgstr "%s supprimé de la liste des %s interdits."
+msgstr "%s supprimé(e) de la liste des %s interdit(e)s."
#, c-format
msgid "%s for %s set to %s."
@@ -1477,7 +1504,7 @@ msgstr "%s est %s"
#, c-format
msgid "%s is a Services Operator of type %s."
-msgstr "%s est un Opérateur des Services du type %s."
+msgstr "%s est un(e) Opérateurice des Services du type %s."
#, c-format
msgid "%s is a client on services."
@@ -1509,7 +1536,7 @@ msgstr ""
#, c-format
msgid "%s is currently online."
-msgstr "%s est actuellement connecté."
+msgstr "%s est actuellement connecté(e)."
#, c-format
msgid "%s is disabled"
@@ -1533,19 +1560,19 @@ msgstr "%s n'est pas une méthode de log valide."
#, c-format
msgid "%s is not notified of new memos."
-msgstr "%s n'est pas notifié pour les nouveaux mémos."
+msgstr "%s n'est pas notifié(e) des nouveaux mémos."
#, c-format
msgid "%s is notified of new memos at logon and when they arrive."
-msgstr "%s est notifié pour les nouveaux mémos quand ils arrivent et à la connexion."
+msgstr "%s est notifié(e) des nouveaux mémos quand ils arrivent et à la connexion."
#, c-format
msgid "%s is notified of new memos at logon."
-msgstr "%s est notifié pour les nouveaux mémos à la connexion."
+msgstr "%s est notifié(e) des nouveaux mémos à la connexion."
#, c-format
msgid "%s is notified when new memos arrive."
-msgstr "%s est notifié quand de nouveaux mémos arrivent."
+msgstr "%s est notifié(e) quand de nouveaux mémos arrivent."
#, c-format
msgid "%s is on the channel right now (as %s)!"
@@ -1577,7 +1604,7 @@ msgstr "Paramètres %s :"
#, c-format
msgid "%s was last seen here %s ago."
-msgstr "%s a été vu il y a %s."
+msgstr "%s a été vu(e) il y a %s."
#, c-format
msgid "%s was not found on %s's auto join list."
@@ -1585,7 +1612,7 @@ msgstr "%s introuvable sur la liste de JOIN automatiques de %s."
#, c-format
msgid "%s was removed from %s's auto join list."
-msgstr "%s supprimé de la liste de JOIN automatiques de %s."
+msgstr "%s supprimé(e) de la liste de JOIN automatiques de %s."
#, c-format
msgid "%s will not send you any notification of memos."
@@ -1608,10 +1635,6 @@ msgid "%s!%s@%s (%s) added to the bot list."
msgstr "%s!%s@%s (%s) ajouté à la liste des bots."
#, c-format
-msgid "%s's access list is empty."
-msgstr "La liste d'accès de %s est vide."
-
-#, c-format
msgid "%s's auto join list is empty."
msgstr "La liste de JOIN automatiques de %s est vide."
@@ -1632,6 +1655,18 @@ msgid "%s's memo limit is %d."
msgstr "La limite de mémos de %s est de %d."
#, c-format
+msgid "%u channel"
+msgid_plural "%u channels"
+msgstr[0] "%u canal"
+msgstr[1] "%u canaux"
+
+#, c-format
+msgid "%zu nickname in the group."
+msgid_plural "%zu nicknames in the group."
+msgstr[0] "%zu pseudo dans le groupe."
+msgstr[1] "%zu pseudos dans le groupe."
+
+#, c-format
msgid "(%s ago)"
msgstr "(il y a %s)"
@@ -1640,7 +1675,7 @@ msgid "(%s from now)"
msgstr "(dans %s)"
msgid "(Split)"
-msgstr "(Déconnecté)"
+msgstr "(Déconnecté(e))"
#, c-format
msgid "(by %s on %s) %s"
@@ -1650,7 +1685,7 @@ msgid "(disabled)"
msgstr "(désactivé)"
msgid "(founder only)"
-msgstr "(fondateur seulement)"
+msgstr "(fondateurice seulement)"
msgid "(now)"
msgstr "(maintenant)"
@@ -1660,10 +1695,10 @@ msgstr "* AKILL tous les nouveaux clients qui se connectent"
#, c-format
msgid "* Force channel modes (%s) to be set on all channels"
-msgstr "* Impose les modes %s sur tous les canaux."
+msgstr "* Impose les modes %s sur tous les canaux"
msgid "* Ignore non-opers with a message"
-msgstr "* Ignore les utilisateurs non opers avec un avertissement"
+msgstr "* Ignore les utilisateurices non opers avec un avertissement"
msgid "* Kill any new clients connecting"
msgstr "* Kill tous les nouveaux clients qui se connectent"
@@ -1681,7 +1716,7 @@ msgid "* No new nick registrations"
msgstr "* Pas d'enregistrement de nouveaux pseudos"
msgid "* Silently ignore non-opers"
-msgstr "* Ignore silencieusement les utilisateurs non opers"
+msgstr "* Ignore silencieusement les utilisateurices non opers"
#, c-format
msgid "* Use the reduced session limit of %d"
@@ -1693,40 +1728,44 @@ msgstr ", mais %s s'est mystérieusement dématérialisé."
#, c-format
msgid ". %s is still online."
-msgstr "%s est toujours connecté."
+msgstr "%s est toujours connecté(e)."
msgid "<unknown>"
msgstr "<inconnu>"
#, c-format
-msgid "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
-msgstr "Un mot-code a été envoyé à %s, merci de suivre les instructions que vous avez reçu pour changer votre adresse email."
+msgid "A confirmation email has been sent to %s. Follow the instructions in it to change your email address."
+msgstr "Un email de confirmation a été envoyé à %s. Merci de suivre les instructions que vous avez reçues pour changer votre adresse email."
msgid "A massmemo has been sent to all registered users."
msgstr "Un mémo de masse a été envoyé à tous les pseudos enregistrés."
msgid "A memo informing the user will also be sent, which includes the reason for the rejection if supplied."
-msgstr "Un mémo informant l'utilisateur sera également envoyé, incluant la raison pour le rejet, si elle a été communiquée."
+msgstr "Un mémo informant l'utilisateurice sera également envoyé, incluant la raison pour le rejet, si elle a été communiquée."
msgid "A memo informing the user will also be sent."
-msgstr "Un mémo informant l'utilisateur sera également envoyé."
+msgstr "Un mémo informant l'utilisateurice sera également envoyé."
#, c-format
msgid ""
"A notification memo has been sent to %s informing them you have\n"
"read their memo."
-msgstr "Un accusé de réception a été envoyé a %s, l'informant que\n"
+msgstr ""
+"Un accusé de réception a été envoyé a %s, l'informant que\n"
"vous avez lu son mémo."
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr "L'ident d'un vhost doit être d'un format valide pour un ident."
-
-msgid "A vHost must be in the format of a valid hostname."
+msgid "A vhost must be in the format of a valid hostname."
msgstr "Un vhost doit être d'un format valide pour un nom de domaine."
+msgid "A vident must be in the format of a valid ident."
+msgstr "Une vident doit être d'un format valide pour une ident."
+
msgid "ADD expiry {nick|mask} [reason]"
msgstr "ADD expiration {pseudo|masque} [raison]"
+msgid "ADD message"
+msgstr "ADD message"
+
msgid "ADD oper type"
msgstr "ADD oper type"
@@ -1742,9 +1781,6 @@ msgstr "ADD [+expiration] masque limite raison"
msgid "ADD [nickname] channel [key]"
msgstr "ADD [pseudo] canal [clé]"
-msgid "ADD [nickname] mask"
-msgstr "ADD [pseudo] masque"
-
msgid "ADD [nickname] [fingerprint]"
msgstr "ADD [pseudo] [fingerprint]"
@@ -1768,10 +1804,10 @@ msgstr "ADDZONE nom.de.la.zone"
#, c-format
msgid "AKICK ENFORCE for %s complete; %d users were affected."
-msgstr "L'application des kicks automatiques pour %s est terminée : %d utilisateurs expulsés."
+msgstr "L'application des kicks automatiques pour %s est terminée : %d utilisateurices expulsés."
msgid "AKILL all users on a specific channel"
-msgstr "AKILL tous les utilisateurs d'un canal spécifique."
+msgstr "AKILL toustes les utilisateurices d'un canal"
msgid "AKILL list is empty."
msgstr "La liste d'AKILL est vide."
@@ -1810,20 +1846,28 @@ msgstr "Liste d'accès de %s :"
#, c-format
msgid "Access to this command requires the permission %s to be present in your opertype."
-msgstr "L'accès à cette commande requiert que la permission %s soit présente pour votre type d'opérateur."
+msgstr "L'accès à cette commande requiert que la permission %s soit présente pour votre type d'oper."
msgid "Account"
-msgstr ""
+msgstr "Compte"
#, c-format
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
msgstr "Le compte %s a déjà atteint le nombre maximum de connexions simultanées (%u)."
-msgid "Activate security features"
-msgstr "Active les fonctions de sécurité"
+msgid "Account id"
+msgstr "Identifiant de compte"
+
+msgid "Account registered"
+msgstr "Compte créé"
+
+msgid "Accounts can not be registered right now. Please try again later."
+msgstr ""
+"Impossible de créer des comptes maintenant, veuillez réessayez un peu\n"
+"plus tard."
-msgid "Activate the requested vHost for the given nick."
-msgstr "Active la demande de vHost pour le pseudo donné."
+msgid "Activate the requested vhost for the given nick."
+msgstr "Active le vhost demandé pour le pseudo donné."
msgid ""
"Activates the vhost currently assigned to the nick in use.\n"
@@ -1831,7 +1875,7 @@ msgid ""
"on you will see the vhost instead of your real host/IP address."
msgstr ""
"Active le vhost actuellement configuré pour ce pseudo.\n"
-"Lorsque vous utilisez cette commande, tous les utilisateurs\n"
+"Lorsque vous utilisez cette commande, toustes les utilisateurices\n"
"qui feront un /whois sur vous verront ce vhost à la place de\n"
"votre host ou votre adresse ip réels."
@@ -1884,12 +1928,28 @@ msgstr ""
"permission SET."
msgid ""
+"Additionally, Services Operators with the chanserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
+msgstr ""
+"De plus, les Opérateurices des Services avec la permission chanserv/drop/override\n"
+"peuvent remplacer mot-code par OVERRIDE pour supprimer sans code de\n"
+"confirmation."
+
+msgid ""
"Additionally, Services Operators with the nickserv/confirm permission can\n"
"replace passcode with a users nick to force validate them."
msgstr ""
-"De plus, les Opérateurs des Services avec la permission nickserv/confirm\n"
+"De plus, les Opérateurices des Services avec la permission nickserv/confirm\n"
"peuvent remplacer mot-code par un pseudo pour le valider."
+msgid ""
+"Additionally, Services Operators with the nickserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
+msgstr ""
+"De plus, les Opérateurices des Services avec la permission nickserv/drop/override\n"
+"peuvent remplacer mot-code pour supprimer sans code de\n"
+"confirmation."
+
#, c-format
msgid ""
"Additionally, if fantasy is enabled fantasy commands\n"
@@ -1932,7 +1992,7 @@ msgid "All modes cleared on %s."
msgstr "Tous les modes ont été retirés de %s."
msgid "All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."
-msgstr "Tous les nouveaux comptes doivent être validés par un administrateur. Merci d'attendre que votre enregistrement soit confirmé."
+msgstr "Tous les nouveaux comptes doivent être validés par un(e) administrateurice. Merci d'attendre que votre enregistrement soit confirmé."
msgid "All of your memos have been deleted."
msgstr "Tous vos mémos ont été supprimés."
@@ -1942,7 +2002,7 @@ msgstr "Toutes les news pour opers ont été supprimées."
#, c-format
msgid "All operators from %s have been removed."
-msgstr "Tous les opérateurs de %s ont été supprimés."
+msgstr "Tous les opérateurices de %s ont été supprimés."
msgid "All random news items deleted."
msgstr "Toutes les news aléatoires ont été supprimées."
@@ -1953,108 +2013,98 @@ msgstr "Tous les paramètres de %s ont été clonés sur %s."
#, c-format
msgid "All user modes on %s have been synced."
-msgstr "Tous les modes utilisateurs de %s ont été synchronisés."
+msgstr "Tous les modes utilisateurices de %s ont été synchronisés."
#, c-format
msgid "All vhosts in the group %s have been set to %s."
msgstr "Tous les vhosts du groupe %s ont été changés en %s."
-#, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "Tous les vhosts du groupe %s ont été changés en %s@%s."
-
-msgid "Allowed to (de)halfop him/herself"
-msgstr "Autorisé à se (dé)halfop soi-même"
+msgid "Allowed to (de)halfop themself"
+msgstr "Autorisé(e) à se (dé)halfop soi-même"
msgid "Allowed to (de)halfop users"
-msgstr "Autorisé à (dé)halfoper des utilisateurs"
+msgstr "Autorisé(e) à (dé)halfoper des utilisateurices"
-msgid "Allowed to (de)op him/herself"
-msgstr "Autorisé à se (dé)oper soi-même"
+msgid "Allowed to (de)op themself"
+msgstr "Autorisé(e) à se (dé)oper soi-même"
msgid "Allowed to (de)op users"
-msgstr "Autorisé à (dé)op des utilisateurs"
+msgstr "Autorisé(e) à (dé)op des utilisateurices"
-msgid "Allowed to (de)owner him/herself"
-msgstr "Autorisé à se (dé)owner soi-même"
+msgid "Allowed to (de)owner themself"
+msgstr "Autorisé(e) à se (dé)owner soi-même"
msgid "Allowed to (de)owner users"
-msgstr "Autorisé à (dé)owner des utilisateurs"
+msgstr "Autorisé(e) à (dé)owner des utilisateurices"
-msgid "Allowed to (de)protect him/herself"
-msgstr "Autorisé à se (dé)protect soi-même"
+msgid "Allowed to (de)protect themself"
+msgstr "Autorisé(e) à se (dé)protect soi-même"
msgid "Allowed to (de)protect users"
-msgstr "Autorisé à (dé)protect des utilisateurs"
+msgstr "Autorisé(e) à (dé)protect des utilisateurices"
-msgid "Allowed to (de)voice him/herself"
-msgstr "Autorisé à se (dé)voice soi-même"
+msgid "Allowed to (de)voice themself"
+msgstr "Autorisé(e) à se (dé)voice soi-même"
msgid "Allowed to (de)voice users"
-msgstr "Autorisé à (dé)voicer des utilisateurs"
+msgstr "Autorisé(e) à (dé)voicer des utilisateurices"
msgid "Allowed to assign/unassign a bot"
-msgstr "Autorisé à assigner/désassigner un bot"
+msgstr "Autorisé(e) à assigner/désassigner un bot"
msgid "Allowed to ban users"
-msgstr "Autorisé à bannir des utilisateurs"
+msgstr "Autorisé(e) à bannir des utilisateurices"
msgid "Allowed to change channel topics"
-msgstr "Autorisation de changer le sujet du canal"
+msgstr "Autorisé(e) de changer le sujet du canal"
msgid "Allowed to get full INFO output"
-msgstr "Autorisé à voir toutes les infos avec INFO"
+msgstr "Autorisé(e) à voir toutes les infos avec INFO"
msgid "Allowed to issue commands restricted to channel founders"
-msgstr "Autorisé à exécuter des commandes restreintes aux fondateurs"
+msgstr "Autorisé(e) à exécuter des commandes restreintes aux fondateurices"
msgid "Allowed to modify channel badwords list"
-msgstr "Autorisé à modifier la liste des mots interdits du canal"
+msgstr "Autorisé(e) à modifier la liste des mots interdits du canal"
+
+msgid "Allowed to modify channel settings"
+msgstr "Autorisé(e) à changer les paramètres du canal"
msgid "Allowed to modify the access list"
-msgstr "Autorisé à modifier la liste d'accès"
+msgstr "Autorisé(e) à modifier la liste d'accès"
msgid "Allowed to read channel memos"
-msgstr "Autorisé à lire les mémos du canal"
+msgstr "Autorisé(e) à lire les mémos du canal"
-msgid "Allowed to set channel settings"
-msgstr "Autorisé à changer les paramètres du canal"
+msgid "Allowed to unban themself"
+msgstr "Autorisé(e) à se débannir soi-même"
msgid "Allowed to unban users"
-msgstr "Autorisé à débannir des utilisateurs"
+msgstr "Autorisé(e) à débannir des utilisateurices"
msgid "Allowed to use GETKEY command"
-msgstr "Autorisé à utiliser la commande GETKEY"
+msgstr "Autorisé(e) à utiliser la commande GETKEY"
msgid "Allowed to use SAY and ACT commands"
-msgstr "Autorisé à utiliser les commandes SAY et ACT"
+msgstr "Autorisé(e) à utiliser les commandes SAY et ACT"
msgid "Allowed to use fantasy commands"
-msgstr "Autorisé à utiliser les commandes fantaisies."
+msgstr "Autorisé(e) à utiliser les commandes fantaisies"
msgid "Allowed to use the AKICK command"
-msgstr "Autorisé à utiliser la commande AKICK"
+msgstr "Autorisé(e) à utiliser la commande AKICK"
msgid "Allowed to use the INVITE command"
-msgstr "Autorisé à utiliser la commande INVITE"
+msgstr "Autorisé(e) à utiliser la commande INVITE"
msgid "Allowed to use the KICK command"
-msgstr "Autorisé à utiliser la commande KICK"
+msgstr "Autorisé(e) à utiliser la commande KICK"
msgid "Allowed to use the MODE command"
-msgstr "Autorisé à utiliser la commande MODE"
+msgstr "Autorisé(e) à utiliser la commande MODE"
msgid "Allowed to view the access list"
-msgstr "Autorisé à voir la liste d'accès"
-
-#, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
-msgstr ""
-"Permet aux Administrateurs d'envoyer des messages à tous\n"
-"les utilisateurs connectés au réseau. Le message sera envoyé\n"
-"avec le pseudo %s."
+msgstr "Autorisé(e) à voir la liste d'accès"
msgid ""
"Allows Services Operators to change modes for any channel.\n"
@@ -2062,18 +2112,18 @@ msgid ""
"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
"If CLEAR ALL is given then all modes, including user status, is removed."
msgstr ""
-"Permet aux Opérateurs des Services de changer n'importe quel mode\n"
+"Permet aux Opérateurices des Services de changer n'importe quel mode\n"
"de n'importe quel canal. Les paramètres sont les mêmes que la commande\n"
"/MODE normale. On peut aussi indiquer CLEAR pour vider tous les modes du\n"
"canal. Si CLEAR ALL est indiqué, alors tous les modes et statuts des\n"
-"utilisateurs sont supprimés."
+"utilisateurices sont supprimés."
msgid ""
"Allows Services Operators to change modes for any user.\n"
"Parameters are the same as for the standard /MODE command."
msgstr ""
-"Permet aux Opérateurs des Services de changer les modes de n'importe\n"
-"quel utilisateur. Les paramètres sont les mêmes que pour la commande\n"
+"Permet aux Opérateurices des Services de changer les modes de n'importe\n"
+"quel utilisateurice. Les paramètres sont les mêmes que pour la commande\n"
"/MODE normale."
msgid ""
@@ -2095,8 +2145,8 @@ msgid ""
"currently registered. If an unregistered user is currently\n"
"using the nick, they will be killed."
msgstr ""
-"Permet aux Opérateurs des Services de créer, modifier, et\n"
-"supprimer les bots que les utilisateurs pourront\n"
+"Permet aux Opérateurices des Services de créer, modifier, et\n"
+"supprimer les bots que les utilisateurices pourront\n"
"utiliser sur leurs canaux.\n"
" \n"
"BOT ADD ajoute un bot avec les pseudo, username, hostname\n"
@@ -2110,47 +2160,39 @@ msgstr ""
"BOT DEL supprime le bot donné de la liste des bots.\n"
" \n"
"Note: vous ne pouvez pas créer un bot avec un pseudo\n"
-"déjà enregistré. Si un utilisateur utilise le pseudo sans l'avoir\n"
+"déjà enregistré. Si un(e) utilisateurice utilise le pseudo sans l'avoir\n"
" enregistré, il sera déconnecté lors de la création du bot."
msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Permet aux Opérateurs des Services de mettre des Operflags à un utilisateur.\n"
-"Les flags doivent être préfixés de : \"+\" ou \"-\". \n"
-"Pour supprimer tous les flags, indiquez seulement \"-\" à la place."
-
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
"Ignores will not be enforced on IRC Operators."
msgstr ""
-"Permet aux Opérateurs des Services de faire en sorte que les services\n"
+"Permet aux Opérateurices des Services de faire en sorte que les services\n"
"ignorent un pseudo ou un masque pour un certain temps ou jusqu'au\n"
-"prochain redémarrage. Le format par défaut pour la durée est en\n"
-"secondes. Vous pouvez toutefois le définir différemment. Les unités\n"
-"valides sont: s pour secondes, m pour minutes, h pour heures\n"
-"et d pour jours. Il n'est pas possible de combiner ces unités.\n"
-"Pour ignorer cet utilisateur de façon permanente, indiquez 0 comme durée.\n"
-"Pour ajouter un masque, vous devez le définir au format user@host\n"
-"ou pseudo!user@host, n'importe quoi d'autre sera considéré comme un\n"
+"prochain redémarrage. Le format par défaut pour la durée est en secondes.\n"
+"Vous pouvez toutefois le définir différemment en utilisant des unités.\n"
+"Les unités valides sont: s pour secondes, m pour minutes, h pour\n"
+"heures et d pour jours.\n"
+"Il n'est pas possible de combiner ces unités.\n"
+"Pour ignorer cet(te) utilisateurice de façon permanente, indiquez 0 comme durée.\n"
+"Pour ajouter un masque, vous devez le définir au formatpseudo!user@host,\n"
+"tout autre format sera considéré comme un\n"
"pseudo. Les jokers sont autorisés.\n"
" \n"
-"Cette commande ne fonctionnera pas sur les Opérateurs IRC."
+"Cette commande ne fonctionnera pas sur les Opérateurices IRC."
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2170,10 +2212,10 @@ msgid ""
"current AKILL default expiry time can be found with the\n"
"STATS AKILL command."
msgstr ""
-"Permet aux Opérateurs des Services de manipuler la liste\n"
-"d'AKILL. Si un utilisateur correspondant à un masque d'AKILL\n"
-"tente de se connecter, les Services enverront un KILL pour\n"
-"cet utilisateur et, sur les serveurs le supportant, demandera\n"
+"Permet aux Opérateurices des Services de manipuler la liste\n"
+"d'AKILL. Si un(e) utilisateurice correspondant à un masque d'AKILL\n"
+"tente de se connecter, les services enverront un KILL pour\n"
+"cet(te) utilisateurice et, sur les serveurs le supportant, demandera\n"
"à tous les serveurs d'ajouter un ban du masque qui correspondait.\n"
" \n"
"AKILL ADD ajoute le masque user@host donné à la liste \n"
@@ -2183,7 +2225,7 @@ msgstr ""
"1h30m) ne sont pas permises. Si l'unité n'est pas incluse,\n"
"la valeur est en jours par défaut (donc +30 est équivalent\n"
"à 30 jours). Pour ajouter une AKILL qui n'expire pas, utilisez\n"
-"+0. Si le masque utilisateur à ajouter commence par un +,\n"
+"+0. Si le masque utilisateurice à ajouter commence par un +,\n"
"une échéance doit être donnée, même si c'est la même que\n"
"celle par défaut. L'échéance par défaut pour les AKILLs peut \n"
"être consultée par la commande STATS AKILL."
@@ -2191,27 +2233,27 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
-"Permet aux Opérateurs des Services de manipuler la liste des SNLINE.\n"
-"Si un utilisateur avec un realname correspond à un masque SNLINE tente\n"
-"de se connecter, les Services n'autoriseront pas la session IRC\n"
+"Permet aux Opérateurices des Services de manipuler la liste des SNLINE.\n"
+"Si un(e) utilisateurice avec un realname correspond à un masque SNLINE tente\n"
+"de se connecter, les services n'autoriseront pas la session IRC\n"
"à se poursuivre."
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
"regular expression, the expression will be matched against\n"
"channels too."
msgstr ""
-"Permet aux Opérateurs des Services de manipuler la liste de SQLINE.\n"
-"Si un utilisateur avec un pseudo correspondant à un masque SQLINE\n"
-"tente de se connecter, les Services le déconnecteront.\n"
+"Permet aux Opérateurices des Services de manipuler la liste de SQLINE.\n"
+"Si un(e) utilisateurice avec un pseudo correspondant à un masque SQLINE\n"
+"tente de se connecter, les services le déconnecteront.\n"
"Si le premier caractère du masque est #, les services empêcheront\n"
"d'utiliser les canaux correspondants au masque. Si le masque est\n"
"une expression régulière, elle sera utilisée pour bloquer des\n"
@@ -2227,12 +2269,12 @@ msgid ""
"source of help regarding session limiting. The content of\n"
"this notice is a config setting."
msgstr ""
-"Permet aux Opérateurs des Services de manipuler la liste de hosts qui\n"
+"Permet aux Opérateurices des Services de manipuler la liste de hosts qui\n"
"ont une limite de sessions spécifique, autorisant certaines machines,\n"
"comme les hébergeurs de shell, à avoir plus du nombre par défaut\n"
"de clients à la fois. Une fois qu'un host atteint la limite de sessions,\n"
"tous les clients qui tentent de se connecter depuis ce host seront\n"
-"killés. Avant que l'utilisateur soit killé, on lui envoie une notice\n"
+"killé(e)s. Avant que l'utilisateurice soit killé(e), on lui envoie une notice\n"
"d'aide sur les limites de sessions. Le contenu de la notice est\n"
"défini dans la configuration."
@@ -2252,7 +2294,7 @@ msgid ""
"limiting and how to set session limits specific to certain\n"
"hosts and groups thereof."
msgstr ""
-"Permet aux Opérateurs des Services de voir la liste des sessions.\n"
+"Permet aux Opérateurices des Services de voir la liste des sessions.\n"
" \n"
"SESSION LIST liste les hôtes ayant au minimum seuil\n"
"sessions. La limite minimale doit être un nombre supérieur à 1,\n"
@@ -2284,7 +2326,54 @@ msgstr ""
" \n"
"LOCK et UNLOCK peuvent être utilisés pour activer ou désactiver\n"
"le verrouillage du topic. Lorsque le topic est bloqué, il ne sera pas modifiable,\n"
-"sauf par les utilisateurs qui ont le privilège TOPIC."
+"sauf par les utilisateurices qui ont le privilège TOPIC."
+
+msgid ""
+"Allows queueing messages to send to users on the network.\n"
+"\n"
+"The QUEUE ADD command adds the given message to the message queue.\n"
+"The QUEUE CLEAR command clears the message queue.\n"
+"The QUEUE DEL command removes the specified message from the message queue. The\n"
+"message number can be obtained from the output of the QUEUE LIST command.\n"
+"The QUEUE LIST command lists all messages that are currently in the message queue."
+msgstr ""
+"Permet de mettre des messages dans la file d'attente d'utilisateurices du réseau.\n"
+"\n"
+"La commande QUEUE ADD ajoute le message à la file d'attendte.\n"
+"La commande QUEUE CLEAR vide la file d'attente.\n"
+"La commande QUEUE DEL supprimer le message donné de la file. Le numéro de message\n"
+"peut être obtenu avec la commande QUEUE LIST.\n"
+"La commande QUEUE LIST liste tous les messages actuellement dans la file d'attente."
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on a server. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+"Permet d'envoyer des messages à toustes les utilisateurices d'un serveur.\n"
+"Le message sera envoyé par %s.\n"
+"\n"
+"Vous pouvez soit envoyer un message en le spécifiant en paramètre, soit en\n"
+"ne fournissant pas de paramètre pour envoyer un message précédemment\n"
+"mis dans la queue.\n"
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on the network. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+"Permet d'envoyer des messages à toustes les utilisateurices du réseau.\n"
+"Le message sera envoyé par %s.\n"
+"\n"
+"Vous pouvez soit envoyer un message en le spécifiant en paramètre, soit en\n"
+"ne fournissant pas de paramètre pour envoyer un message précédemment\n"
+"mis dans la queue.\n"
#, c-format
msgid ""
@@ -2295,7 +2384,7 @@ msgid ""
" \n"
"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
msgstr ""
-"Permet au staff de kicker un utilisateur d'un canal.\n"
+"Permet au staff de kicker un(e) utilisateurice d'un canal.\n"
"Les paramètres sont les mêmes que pour la commande /KICK\n"
"normale. Le message de kick sera préfixé par le pseudo de\n"
"l'IRCop ayant utilisé la commande KICK, par exemple :\n"
@@ -2308,7 +2397,7 @@ msgid ""
" \n"
"Available options:"
msgstr ""
-"Permet au fondateur du canal de configurer diverses options\n"
+"Permet au fondateurice du canal de configurer diverses options\n"
"du canal et d'autres informations.\n"
" \n"
"Options disponibles :"
@@ -2318,8 +2407,8 @@ msgid ""
"Note that operators removed by this command but are still set in\n"
"the configuration file are not permanently affected by this."
msgstr ""
-"Vous permet de voir et de modifier les Opérateurs des Services.\n"
-"Notez que les opérateurs supprimés par cette commande mais\n"
+"Vous permet de voir et de modifier les Opérateurices des Services.\n"
+"Notez que les opérateurices supprimés par cette commande mais\n"
"toujours présents dans le fichier de configuration ne sont pas supprimés\n"
"de manière permanente."
@@ -2330,7 +2419,7 @@ msgid ""
"restarted, or the configuration is reloaded.\n"
" \n"
"Example:\n"
-" MODIFY nickserv forcemail no"
+" MODIFY nickserv regdelay 15m"
msgstr ""
"Vous permet de voir et de modifier les paramètres de configuration.\n"
"Les paramètres modifiés par cette commande le sont temporairement\n"
@@ -2341,8 +2430,8 @@ msgstr ""
" MODIFY nickserv forcemail no"
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
"Vous permet de choisir la façon dont les Services communiquent avec\n"
@@ -2351,8 +2440,8 @@ msgstr ""
#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
"Vous permet de choisir la façon dont les Services communiquent\n"
@@ -2365,17 +2454,17 @@ msgid ""
"to memo you or a channel, they will not be told that you have\n"
"them ignored."
msgstr ""
-"Vous permet d'ignorer les mémos des utilisateurs par pseudo ou host\n"
+"Vous permet d'ignorer les mémos des utilisateurices par pseudo ou host\n"
"envoyés à un canal ou à vous-même. Si quelqu'un sur la liste des ignorés\n"
-"essaye de vous envoyer un mémo (ou à un canal), il ne sera pas averti que\n"
-"vous l'avez ignoré."
+"essaye de vous envoyer un mémo (ou à un canal), iel ne sera pas averti(e) que\n"
+"vous l'avez ignoré(e)."
msgid ""
"Allows you to kill a user from the network.\n"
"Parameters are the same as for the standard /KILL\n"
"command."
msgstr ""
-"Vous permet de killer un utilisateur du réseau.\n"
+"Vous permet de killer un(e) utilisateurice du réseau.\n"
"Les paramètres sont les mêmes que pour la commande /KILL\n"
"normale."
@@ -2383,7 +2472,7 @@ msgstr ""
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
+"nick. You can hide the email address (EMAIL), last seen\n"
"user@host mask (USERMASK), the services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2401,7 +2490,7 @@ msgstr ""
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
+"nick. You can hide your email address (EMAIL), last seen\n"
"user@host mask (USERMASK), your services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2442,11 +2531,11 @@ msgstr ""
"Des méthodes alternatives de modification de la liste d'accès sont\n"
"disponibles."
-msgid "Approve the requested vHost of a user"
-msgstr "Approuve la requête de vHost d'un utilisateur"
+msgid "Approve the requested vhost of a user"
+msgstr "Approuve la vhost demandée par un(e) utilisateurice"
msgid "As a Services Operator, you may drop any nick."
-msgstr "En tant qu'Opérateur des Services vous pouvez supprimer n'importe quel pseudo."
+msgstr "En tant qu'Opérateurice des Services vous pouvez supprimer n'importe quel pseudo."
msgid "Assigns a bot to a channel"
msgstr "Attribue un bot à un canal"
@@ -2461,31 +2550,31 @@ msgstr ""
"vos besoins sur ce canal."
msgid "Associate a URL with the channel"
-msgstr "Associe un URL à un canal"
+msgstr "Associe une URL à un canal"
msgid "Associate a URL with this account"
-msgstr "Associe un URL avec ce compte"
+msgstr "Associe une URL avec ce compte"
msgid "Associate a URL with your account"
-msgstr "Attribue un URL à votre compte"
+msgstr "Attribue une URL à votre compte"
msgid "Associate a greet message with your nickname"
msgstr "Associe un message d'accueil à votre pseudo"
-msgid "Associate an E-mail address with the channel"
+msgid "Associate an email address with the channel"
msgstr "Associe une adresse email au canal"
-msgid "Associate an E-mail address with your nickname"
+msgid "Associate an email address with your nickname"
msgstr "Associe une adresse email à votre pseudo"
msgid "Associate oper info with a nick or channel"
msgstr "Associe une info oper à un pseudo ou un canal"
-msgid "Associates the given E-mail address with the nickname."
-msgstr "Associe une adresse email donnée à un pseudo"
+msgid "Associates the given email address with the nickname."
+msgstr "Associe une adresse email donnée à un pseudo."
msgid ""
-"Associates the given E-mail address with your nickname.\n"
+"Associates the given email address with your nickname.\n"
"This address will be displayed whenever someone requests\n"
"information on the nickname with the INFO command."
msgstr ""
@@ -2501,7 +2590,7 @@ msgid "Autokick list for %s:"
msgstr "Liste de kicks automatiques de %s :"
msgid "Automatic channel operator status upon join"
-msgstr "Statut d'opérateur automatique lors du join"
+msgstr "Statut d'opérateurice automatique lors du join"
msgid "Automatic halfop upon join"
msgstr "Halfop automatique lors du join"
@@ -2520,7 +2609,7 @@ msgid "Available commands for %s:"
msgstr "Aide disponible pour %s :"
msgid "Available opertypes:"
-msgstr "Types d'opérateurs disponibles :"
+msgstr "Types d'opérateurices disponibles :"
#, c-format
msgid "Available privileges for %s:"
@@ -2568,8 +2657,8 @@ msgstr ""
"Un temps d'expiration peut être donné pour que les\n"
"services suppriment ce ban après ce délai.\n"
" \n"
-"Par défaut, limité aux AOPs ou à ceux ayant un niveau \n"
-"d'accès de 5 ou plus sur le canal. Les fondateurs peuvent\n"
+"Par défaut, limité aux AOPs ou à celleux ayant un niveau \n"
+"d'accès de 5 ou plus sur le canal. Les fondateurices peuvent\n"
"bannir des masques."
#, c-format
@@ -2635,15 +2724,15 @@ msgid "Bot bans will no longer automatically expire."
msgstr "Le bans du bot n'expireront plus automatiquement."
#, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Les hosts des bots ne doivent contenir que %d caractères."
+msgid "Bot hosts may only be %zu characters long."
+msgstr "Les hosts des bots ne doivent contenir que %zu caractères."
msgid "Bot hosts may only contain valid host characters."
msgstr "Les hosts des bots ne doivent contenir que des caractères valides pour un host."
#, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Les ident des bots ne doivent contenir que %d caractères."
+msgid "Bot idents may only be %zu characters long."
+msgstr "Les ident des bots ne doivent contenir que %zu caractères."
msgid "Bot idents may only contain valid ident characters."
msgstr "Les ident des bots ne doivent contenir que des caractères valides pour un ident."
@@ -2659,8 +2748,8 @@ msgid "Bot nick"
msgstr "Pseudo du bot"
#, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Les pseudos des bots ne doivent contenir que %d caractères."
+msgid "Bot nicks may only be %zu characters long."
+msgstr "Les pseudos des bots ne doivent contenir que %zu caractères."
msgid "Bot nicks may only contain valid nick characters."
msgstr "Les pseudos des bots ne peuvent contenir que des caractères valides."
@@ -2671,7 +2760,7 @@ msgid ""
"after %d kicks for the same user."
msgstr ""
"Le bot kickera pour la raison : %s.\n"
-"Il placera un ban après %d kicks du même utilisateur."
+"Il placera un ban après %d kicks du même utilisateurice."
#, c-format
msgid "Bot will now kick for %s."
@@ -2685,7 +2774,7 @@ msgid ""
msgstr ""
"Le bot kickera maintenant les majuscules (qui doivent\n"
"constituer au moins %d caractères et %d%% du message \n"
-"entier), et bannira après %d kicks du même utilisateur."
+"entier), et bannira après %d kicks du même utilisateurice."
#, c-format
msgid ""
@@ -2702,7 +2791,7 @@ msgid ""
"and will place a ban after %d kicks for the same user."
msgstr ""
"Le bot kickera maintenant le flood (%d lignes en %d \n"
-"secondes), et bannira après %d kicks du même utilisateur."
+"secondes), et bannira après %d kicks du même utilisateurice."
#, c-format
msgid "Bot will now kick for flood (%d lines in %d seconds)."
@@ -2717,8 +2806,8 @@ msgid ""
"kicks for the same user."
msgstr ""
"Le bot kickera maintenant les répétitions (les \n"
-"utilisateurs qui répètent %d fois la même chose), et \n"
-"bannira après %d kicks du même utilisateur."
+"utilisateurices qui répètent %d fois la même chose), et \n"
+"bannira après %d kicks du même utilisateurice."
#, c-format
msgid ""
@@ -2726,7 +2815,7 @@ msgid ""
"same message %d time)."
msgstr ""
"Le bot kickera maintenant les répétitions (les \n"
-"utilisateurs qui répètent %d fois la même chose)."
+"utilisateurices qui répètent %d fois la même chose)."
#, c-format
msgid ""
@@ -2735,8 +2824,8 @@ msgid ""
"kicks for the same user."
msgstr ""
"Le bot kickera maintenant les répétitions (les \n"
-"utilisateurs qui répètent %d fois la même chose), et \n"
-"bannira après %d kicks du même utilisateur."
+"utilisateurices qui répètent %d fois la même chose), et \n"
+"bannira après %d kicks du même utilisateurice."
#, c-format
msgid ""
@@ -2744,7 +2833,7 @@ msgid ""
"same message %d times)."
msgstr ""
"Le bot kickera maintenant les répétitions (les \n"
-"utilisateurs qui répètent %d fois la même chose)."
+"utilisateurices qui répètent %d fois la même chose)."
#, c-format
msgid "Bot won't kick for %s anymore."
@@ -2769,7 +2858,7 @@ msgid "CLEAR time"
msgstr "CLEAR temps"
msgid "Cancel the last memo you sent"
-msgstr "Annule le dernier mémo que vous avez envoyé."
+msgstr "Annule le dernier mémo que vous avez envoyé"
msgid "Cancel the registration of a channel"
msgstr "Annule l'enregistrement d'un canal"
@@ -2798,47 +2887,47 @@ msgid "Caps kicker"
msgstr "Kicker de majuscules"
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
msgstr ""
"Provoque un arrêt immédiat des Services, les bases de données\n"
"ne sont pas sauvegardées. Cette commande ne devrait pas être\n"
-"utilisée à moins que des dommages dans la copie en mémoire des\n"
-"bases de données ne soient soupçonnés."
+"utilisée à moins soupçonner des dommages dans la copie en mémoire\n"
+"des bases de données qui ne doivent pas être sauvegardés."
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
"Provoque le rechargement du fichier de configuration des\n"
"Services. Notez que certaines directives demandent tout\n"
-"de même le redémarrage des Services pour prendre effet\n"
+"de même le redémarrage des services pour prendre effet\n"
"(comme les pseudos des services, l'activation de la limite\n"
"de sessions, etc.)"
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr ""
"Provoque la sauvegarde de toutes les bases de données et\n"
-"le redémarrage des Services (c'est à dire qu'elle stoppe\n"
+"le redémarrage des services (c'est à dire qu'elle stoppe\n"
"le programme et le relance immédiatement)."
-msgid "Causes Services to save all databases and then shut down."
+msgid "Causes services to save all databases and then shut down."
msgstr ""
"Provoque la sauvegarde de toutes les bases de données puis\n"
-"l'arrêt des Services."
+"l'arrêt des services."
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr ""
"Provoque la sauvegarde de toutes les bases de données dès\n"
-"que vous le demandez."
+"que vous envoyez la commande."
#, c-format
msgid "Certificate list for %s:"
@@ -2850,57 +2939,57 @@ msgstr "ChanServ est requis pour activer les canaux persistants sur ce réseau."
msgid "Change channel modes"
msgstr "Modifie les modes des canaux"
-msgid "Change the communication method of Services"
-msgstr "Change le mode de communication des Services"
+msgid "Change the communication method of services"
+msgstr "Change le mode de communication des services"
msgid "Change user modes"
-msgstr "Modifie les modes des utilisateurs."
+msgstr "Modifie les modes des utilisateurices"
#, c-format
msgid "Changed usermodes of %s to %s."
-msgstr "Modes utilisateurs de %s changés en %s."
+msgstr "Modes utilisateurices de %s changés en %s."
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
"Change le pseudo utilisé pour nommer le groupe de\n"
-"pseudos dans les Services. Le nouvel affichage DOIT être un\n"
+"pseudos dans les services. Le nouvel affichage DOIT être un\n"
"pseudo de ce groupe."
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
"Change le pseudo utilisé pour nommer votre groupe de\n"
-"pseudos dans les Services. Le nouvel affichage DOIT être un\n"
+"pseudos dans les services. Le nouvel affichage DOIT être un\n"
"pseudo de votre groupe."
msgid ""
"Changes the founder of a channel. The new nickname must\n"
"be a registered one."
msgstr ""
-"Change le fondateur d'un canal. Le nouveau pseudo doit être\n"
+"Change le/la fondateurice d'un canal. Le nouveau pseudo doit être\n"
"enregistré."
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Change la langue utilisée par les Services lorsqu'ils envoient un message\n"
-"à un utilisateur donné (par exemple, quand ils répondent à une\n"
-"commande qu'il a envoyé). La langue doit être choisie\n"
+"Change la langue utilisée par les services lorsqu'ils envoient un message\n"
+"à un(e) utilisateurice donné (par exemple, quand ils répondent à une\n"
+"commande qu'iel a envoyé). La langue doit être choisie\n"
"dans la liste suivante des langues supportées :"
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Change la langue utilisée par les Services lorsqu'ils vous\n"
+"Change la langue utilisée par les services lorsqu'ils vous\n"
"envoient un message (par exemple, quand ils répondent à une\n"
"commande que vous avez envoyé). La langue doit être choisi\n"
"dans la liste suivante des langues supportées :"
@@ -2927,15 +3016,23 @@ msgid ""
"become the new founder, but if the access list is empty, the\n"
"channel will be dropped."
msgstr ""
-"Change le successeur d'un canal. Si le pseudo du fondateur\n"
+"Change le/la successeur(e) d'un canal. Si le pseudo fondateur\n"
"expire ou est effacé alors que le canal est toujours enregistré,\n"
-" le successeur deviendra le nouveau fondateur du canal. Le\n"
+" le/la successeur(e) deviendra le nouveau fondateurice du canal. Le\n"
"nouveau pseudo doit être enregistré. Si il n'y a pas de \n"
-"successeur configuré, alors le premier pseudo sur la liste \n"
+"successeur(e) configuré, alors le premier pseudo sur la liste \n"
"d'accès (avec le plus haut accès, si applicable) deviendra \n"
-"le nouveau fondateur, mais si la liste d'accès est vide, \n"
+"le nouveau fondateurice, mais si la liste d'accès est vide, \n"
"alors le canal sera supprimé."
+#, c-format
+msgid "Changing your usermodes to %s"
+msgstr "Changement de vos modes utilisateurices en %s"
+
+#, c-format
+msgid "Changing your vhost to %s"
+msgstr "Changement de votre vhost en %s"
+
msgid "Channel"
msgstr "Canal"
@@ -3038,15 +3135,15 @@ msgid "Channels that %s has access on:"
msgstr "Liste des canaux auxquels %s a accès :"
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Canaux : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Canaux : %zu entrées, %zu paniers, plus longue chaîne : %zu"
msgid "Chanstats"
msgstr "Chanstats"
#, c-format
msgid "Chanstats statistics are now disabled for %s"
-msgstr "Les statistiques Chanstats sont maintenant désactivées pour %s."
+msgstr "Les statistiques Chanstats sont maintenant désactivées pour %s"
msgid "Chanstats statistics are now disabled for this channel."
msgstr "Les statistiques Chanstats sont maintenant désactivées pour ce canal."
@@ -3056,7 +3153,7 @@ msgstr "Les statistiques Chanstats sont maintenant désactivées pour votre pseu
#, c-format
msgid "Chanstats statistics are now enabled for %s"
-msgstr "Les statistiques Chanstats sont maintenant activées pour %s."
+msgstr "Les statistiques Chanstats sont maintenant activées pour %s"
msgid "Chanstats statistics are now enabled for this channel."
msgstr "Les statistiques Chanstats sont maintenant activées pour ce canal."
@@ -3071,7 +3168,7 @@ msgid ""
msgstr ""
"Vérifie la dernière fois que pseudo a rejoint ou quitté un canal, ou\n"
"modifié son pseudo sur le réseau, et selon les paramètres du canal et\n"
-"de l'utilisateur, sur quel canal."
+"de l'utilisateurice, sur quel canal."
msgid "Checks if last memo to a nick was read"
msgstr "Vérifie si le dernier mémo envoyé à un pseudo a été lu"
@@ -3123,7 +3220,7 @@ msgid "Configures caps kicker"
msgstr "Configure les kickers pour les majuscules"
msgid "Configures channel logging settings"
-msgstr "Configure les paramètres de logs du canal."
+msgstr "Configure les paramètres de logs du canal"
msgid "Configures color kicker"
msgstr "Configure les kickers pour les couleurs"
@@ -3156,7 +3253,7 @@ msgid "Control modes and mode locks on a channel"
msgstr "Contrôle les modes et les modes verrouillés sur un canal"
msgid "Controls what messages will be sent to users when they join the channel."
-msgstr "Contrôle quels messages sont envoyés aux utilisateurs lorsqu'ils joignent le canal."
+msgstr "Contrôle quels messages sont envoyés aux utilisateurices lorsqu'ils joignent le canal."
msgid ""
"Copies all settings, access, akicks, etc from channel to the\n"
@@ -3167,7 +3264,7 @@ msgstr ""
"Copie tous les paramètres, accès, akicks, etc. de canal sur le canal\n"
"cible. Si quoi est ACCESS, AKICK, BADWORDS ou\n"
"LEVELS alors seuls ces paramètres sont clonés.\n"
-"Vous devez être fondateur de canal et cible."
+"Vous devez être fondateurice de canal et cible."
msgid "Copy all settings from one channel to another"
msgstr "Copie tous les paramètres d'un canal à un autre"
@@ -3192,20 +3289,23 @@ msgid "Current module list:"
msgstr "Liste des modules actuels :"
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Nombre d'AKILLs : %d"
+msgid "Current number of AKILLs: %zu"
+msgstr "Nombre d'AKILLs : %zu"
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Nombre de SNLINEs : %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr "Nombre de SNLINEs : %zu"
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Nombre de SQLINEs : %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr "Nombre de SQLINEs : %zu"
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Utilisateurs actuels : %d (%d ops)"
+msgid "Current users: %zu (%d ops)"
+msgstr "Utilisateurices actuels : %zu (%d ops)"
+
+msgid "DEL entry-num"
+msgstr "DEL numéro-d'entrée"
msgid "DEL oper"
msgstr "DEL oper"
@@ -3219,9 +3319,6 @@ msgstr "DEL [pseudo] canal"
msgid "DEL [nickname] fingerprint"
msgstr "DEL [pseudo] fingerprint"
-msgid "DEL [nickname] mask"
-msgstr "DEL [pseudo] masque"
-
msgid "DEL {mask | entry-num | list | id}"
msgstr "DEL {masque | num | liste | id}"
@@ -3263,7 +3360,7 @@ msgid ""
msgstr ""
"Désactive le vhost que vous utilisez actuellement.\n"
"L'utilisation de cette commande rendra visible votre host/IP pour\n"
-"les utilisateurs qui exécutent un /whois sur vous."
+"les utilisateurices qui exécutent un /whois sur vous."
msgid "Deactivates your assigned vhost"
msgstr "Désactive votre vHost assigné"
@@ -3341,13 +3438,13 @@ msgid "Default SQLINE expiry time: No expiration"
msgstr "Temps d'échéance des SQLINEs par défaut: Pas d'échéance"
msgid "Define messages to be randomly shown to users at logon"
-msgstr "Définit les messages affichés aléatoirement aux utilisateurs à la connexion"
+msgstr "Définit les messages affichés aléatoirement aux utilisateurices à la connexion"
msgid "Define messages to be shown to users at logon"
-msgstr "Définit les messages affichés aux utilisateurs à la connexion"
+msgstr "Définit les messages affichés aux utilisateurices à la connexion"
msgid "Define messages to be shown to users who oper"
-msgstr "Définit les messages affichés aux utilisateurs qui deviennent opérateurs IRC"
+msgstr "Définit les messages affichés aux utilisateurices qui deviennent opérateurices IRC"
msgid "Delete a memo or memos"
msgstr "Efface un ou des mémos"
@@ -3384,6 +3481,10 @@ msgid "Deleted %d entries from the AKILL list."
msgstr "%d entrées supprimées de la liste d'AKILL."
#, c-format
+msgid "Deleted %u entries from your message queue."
+msgstr "%u entrées supprimées de votre file d'attente."
+
+#, c-format
msgid "Deleted 1 entry from %s access list."
msgstr "1 entrée supprimée de la liste d'accès de %s."
@@ -3413,6 +3514,9 @@ msgstr "Information supprimée de %s."
msgid "Deleted one entry from %s %s list."
msgstr "Une entrée a été supprimée de la liste %2$s de %1$s."
+msgid "Deleted one entry from your message queue."
+msgstr "Une entrée a été supprimée de votre file d'attente."
+
msgid ""
"Deletes the specified memo or memos. You can supply\n"
"multiple memo numbers or ranges of numbers instead of a\n"
@@ -3505,11 +3609,11 @@ msgstr "%d enregistrements affichés (Total : %d)"
#, c-format
msgid "Displayed all records (count: %d)."
-msgstr "Tous les enregistrements sont affichés (Total : %d) "
+msgstr "Tous les enregistrements sont affichés (Total : %d)."
#, c-format
msgid "Displayed records from %d to %d."
-msgstr "Les enregistrements de %d à %d sont affichés"
+msgstr "Les enregistrements de %d à %d sont affichés."
#, c-format
msgid "Displayed records matching key %s (count: %d)."
@@ -3526,7 +3630,7 @@ msgid ""
"used."
msgstr ""
"Affiche des informations sur le pseudo indiqué, telles que\n"
-"le propriétaire du pseudo, l'adresse avec laquelle il était\n"
+"le/la propriétaire du pseudo, l'adresse avec laquelle iel était\n"
"connecté pour la dernière fois, et les options du pseudo. Si\n"
"aucun pseudo n'est donné et que vous êtes identifié, votre compte\n"
"sera utilisé, autrement, votre pseudo sera utilisé."
@@ -3538,16 +3642,16 @@ msgid "Displays one or more vhost entries"
msgstr "Affiche une ou plusieurs entrées vHost"
msgid "Displays the top 10 users of a channel"
-msgstr "Affiche le top 10 des utilisateurs d'un canal"
+msgstr "Affiche le top 10 des utilisateurices d'un canal"
msgid "Displays the top 10 users of the network"
-msgstr "Affiche le top 10 des utilisateurs du réseau"
+msgstr "Affiche le top 10 des utilisateurices du réseau"
msgid "Displays the top 3 users of a channel"
-msgstr "Affiche le top 3 des utilisateurs d'un canal"
+msgstr "Affiche le top 3 des utilisateurices d'un canal"
msgid "Displays the top 3 users of the network"
-msgstr "Affiche le top 3 des utilisateurs du réseau"
+msgstr "Affiche le top 3 des utilisateurices du réseau"
msgid "Displays this list and give information about commands"
msgstr "Affiche cette liste et donne des informations sur les commandes"
@@ -3588,19 +3692,7 @@ msgid ""
msgstr ""
"Efface le pseudo indiqué de la base de données. Une fois que votre pseudo\n"
"est effacé, vous perdez tous les accès et les canaux que vous possédez.\n"
-"N'importe quel utilisateur pourra prendre le contrôle de ce pseudo."
-
-#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "L'adresse email pour %s a été changée en %s."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "L'adresse email pour %s a été effacée."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "L'adresse email pour %s est invalide."
+"N'importe quel utilisateurice pourra prendre le contrôle de ce pseudo."
#, c-format
msgid ""
@@ -3610,10 +3702,10 @@ msgid ""
"sent in order to avoid flooding the user. If there are\n"
"more news messages, only the most recent will be sent."
msgstr ""
-"Modifie ou affiche la liste des news de connexion. Lorsqu'un\n"
-"utilisateur se connecte au réseau, ces messages lui seront\n"
+"Modifie ou affiche la liste des news de connexion. Lorsqu'un(e)\n"
+"utilisateurice se connecte au réseau, ces messages lui seront\n"
"envoyés. Cependant, pas plus de %d messages ne seront\n"
-"envoyés pour éviter le flood des utilisateurs. S'il y a\n"
+"envoyés pour éviter le flood des utilisateurices. S'il y a\n"
"trop de messages de news, seuls les plus récents seront envoyés."
#, c-format
@@ -3624,10 +3716,10 @@ msgid ""
"be sent in order to avoid flooding the user. If there are\n"
"more news messages, only the most recent will be sent."
msgstr ""
-"Modifie ou affiche la liste des news pour opers. Quand un\n"
-"utilisateur utilise la commande /OPER, ces messages lui seront\n"
+"Modifie ou affiche la liste des news pour opers. Quand un(e)\n"
+"utilisateurice utilise la commande /OPER, ces messages lui seront\n"
"envoyés. Cependant, pas plus de %d messages seront \n"
-"envoyés afin de ne pas flooder l'utilisateur. S'il y a trop de \n"
+"envoyés afin de ne pas flooder l'utilisateurice. S'il y a trop de \n"
"messages news, seuls les plus récents seront envoyés."
msgid ""
@@ -3635,18 +3727,30 @@ msgid ""
"user connects to the network, one (and only one) of the\n"
"random news will be randomly chosen and sent to them."
msgstr ""
-"Modifie ou affiche la liste des news aléatoires. Lorsqu'un\n"
-"utilisateur se connecte au réseau, une (et une seule) de ces\n"
+"Modifie ou affiche la liste des news aléatoires. Lorsqu'un(e)\n"
+"utilisateurice se connecte au réseau, une (et une seule) de ces\n"
"news sera choisie et lui sera envoyée."
msgid "Email address"
msgstr "Adresse email"
#, c-format
+msgid "Email address for %s changed to %s."
+msgstr "L'adresse email de %s a été changée en %s."
+
+#, c-format
+msgid "Email address for %s unset."
+msgstr "L'adresse email de %s a été effacée."
+
+#, c-format
+msgid "Email for %s is invalid."
+msgstr "L'adresse email de %s est invalide."
+
+#, c-format
msgid "Email matched: %s (%s) to %s."
msgstr "Email trouvé : %s (%s) pour %s."
-msgid "Enable fantaisist commands"
+msgid "Enable fantasy commands"
msgstr "Active les commandes fantaisistes"
msgid "Enable greet messages"
@@ -3665,7 +3769,7 @@ msgid ""
"not automatically gain any status from %s."
msgstr ""
"Active ou désactive l'auto op par %s sur un canal. Lorsque l'auto op\n"
-"est inactif, les utilisateurs qui joignent le canal ne recevront aucun\n"
+"est inactif, les utilisateurices qui joignent le canal ne recevront aucun\n"
"statut de la part de %s."
msgid ""
@@ -3683,8 +3787,8 @@ msgid ""
"and attempt to re-set them the next time they authenticate."
msgstr ""
"Active ou désactive l'option de maintien des modes d'un pseudo. Si le maintien\n"
-"des modes est activé, les services se rappelleront des modes utilisateurs de l'utilisateur\n"
-"et tenteront de les remettre la prochaine fois que cet utilisateur se connectera."
+"des modes est activé, les services se rappelleront des modes utilisateurices de l'utilisateurice\n"
+"et tenteront de les remettre la prochaine fois que cet(te) utilisateurice se connectera."
msgid ""
"Enables or disables keepmodes for your nick. If keep\n"
@@ -3692,22 +3796,10 @@ msgid ""
"and attempt to re-set them the next time you authenticate."
msgstr ""
"Active ou désactive l'option de maintien des modes de votre pseudo. Si le maintien\n"
-"des modes est activé, les services se rappelleront de vos modes utilisateurs\n"
+"des modes est activé, les services se rappelleront de vos modes utilisateurices\n"
"et tenteront de les remettre la prochaine fois que vous vous connecterez."
msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Active ou désactive les sécurités pour un canal.\n"
-"Lorsque SECURE est activé, seuls les utilisateurs\n"
-"qui se sont authentifiés auprès des services, et qui ne\n"
-"sont pas seulement reconnus par ceux-ci, auront accès\n"
-"au canal, sur la base de la liste d'accès."
-
-msgid ""
"Enables or disables signed kicks for a\n"
"channel. When SIGNKICK is set, kicks issued with\n"
"the KICK command will have the nick that used the\n"
@@ -3722,7 +3814,7 @@ msgstr ""
"par la commande KICK contiendront dans la raison\n"
"le pseudo qui a utilisé la commande.\n"
" \n"
-"Si vous utilisez LEVEL, ceux qui ont un niveau\n"
+"Si vous utilisez LEVEL, celleux qui ont un niveau\n"
"supérieur ou égal au niveau SIGNKICK sur le canal\n"
"n'auront pas leurs kicks signés."
@@ -3735,12 +3827,12 @@ msgid ""
msgstr ""
"Active ou désactive l'option de paix pour un canal.\n"
"Quand elle est active, cette option empêche un \n"
-"utilisateur de kicker, bannir ou enlever un privilège\n"
+"utilisateurice de kicker, bannir ou enlever un privilège\n"
"de canal d'un user qui a un niveau supérieur ou\n"
"égal au sien via les commandes de %s."
msgid "Enables or disables the private option for a channel."
-msgstr "Active ou désactive l'option privée pour un canal."
+msgstr "Active ou désactive l'option privé pour un canal."
msgid ""
"Enables or disables the restricted access option for a\n"
@@ -3748,7 +3840,7 @@ msgid ""
"instead be kicked and banned from the channel."
msgstr ""
"Active ou désactive l'option d'accès restreint pour un canal.\n"
-"Quand l'accès restreint est activé, les utilisateurs qui ne sont\n"
+"Quand l'accès restreint est activé, les utilisateurices qui ne sont\n"
"pas inscrits à la liste d'accès seront kickés et bannis du canal."
msgid ""
@@ -3758,10 +3850,10 @@ msgid ""
"and not those who have founder level access through\n"
"the access/qop command."
msgstr ""
-"Active ou désactive l'option contrôle du fondateur pour un canal.\n"
-"Lorsque le contrôle du fondateur est activé, seul le vrai \n"
-"fondateur pourra effacer le canal, changer son fondateur \n"
-"et son successeur, et non pas ceux qui ont le level propriétaire\n"
+"Active ou désactive l'option contrôle de fondateurice pour un canal.\n"
+"Lorsque le contrôle de fondateurice est activé, seul le/la vrai(e) \n"
+"fondateurice pourra effacer le canal, changer son/sa fondateurice \n"
+"et son successeur(e), et non pas celleux qui ont le level propriétaire\n"
"en utilisant l'accès/la commande qop."
msgid ""
@@ -3770,8 +3862,8 @@ msgid ""
"will not be allowed channel operator status."
msgstr ""
"Active ou désactive le contrôle des OPs sur un canal.\n"
-"Lorsque le contrôle des OPs est actif, les utilisateurs \n"
-"qui ne sont pas sur la liste d'accès ne pourront être opérateurs\n"
+"Lorsque le contrôle des OPs est actif, les utilisateurices \n"
+"qui ne sont pas sur la liste d'accès ne pourront être opérateurices\n"
"du salon."
#, c-format
@@ -3785,8 +3877,8 @@ msgstr ""
"Active ou désactive l'option de maintien du sujet pour\n"
"un canal. Lorsque %s est défini, le \n"
"sujet pour le canal sera retenu par %s même après que le\n"
-"dernier utilisateur ait quitté le canal, et sera restauré\n"
-"la prochaine fois que le canal sera créé. "
+"dernier utilisateurice ait quitté le canal, et sera restauré\n"
+"la prochaine fois que le canal sera créé."
#, c-format
msgid ""
@@ -3812,7 +3904,7 @@ msgid ""
msgstr ""
"Active ou désactive la persistance du canal. Lorsqu'un canal\n"
"est persistant, le bot restera dessus lorsqu'il n'y a plus\n"
-"d'utilisateur sur le canal.\n"
+"d'utilisateurice sur le canal.\n"
" \n"
"Si votre serveur IRC n'a pas de mode de canaux permanents (persistants)\n"
"vous devez avoir un bot des services sur votre canal pour le rendre\n"
@@ -3859,11 +3951,11 @@ msgid "End of entry message list."
msgstr "Fin de la liste de messages d'entrée."
#, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Fin de la liste des interdits - %d/%d correspondances affichées."
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr "Fin de la liste des interdit(e)s - %zu/%zu correspondances affichées."
msgid "End of forbid list."
-msgstr "Fin de la liste des interdits."
+msgstr "Fin de la liste des interdit(e)s."
#, c-format
msgid "End of list - %d channels shown."
@@ -3878,7 +3970,7 @@ msgstr "Fin de la liste des news."
#, c-format
msgid "End of users list. %u users shown."
-msgstr "Fin de la liste des utilisateurs. %u utilisateurs affichées."
+msgstr "Fin de la liste des utilisateurices. %u utilisateurices affichées."
msgid "Enforce various channel modes and set options"
msgstr "Applique les modes et les paramètres divers d'un canal"
@@ -3906,10 +3998,10 @@ msgstr ""
" \n"
"Utilisez SECUREOPS pour faire appliquer l'option SECUREOPS, même si\n"
"elle n'est pas activée. Utilisez RESTRICTED pour faire appliquer l'option RESTRICTED,\n"
-"même si elle n'est pas activée. Utilisez REGONLY pour kicker tous les\n"
-"utilisateurs non enregistrés du canal. Utilisez SSLONLY pour kicker tous les utilisateurs\n"
+"même si elle n'est pas activée. Utilisez REGONLY pour kicker toustes les\n"
+"utilisateurices non enregistré(e)s du canal. Utilisez SSLONLY pour kicker toustes les utilisateurices\n"
"qui n'utilisent pas une connexion sécurisée sur le canal. BANS forcera les bans sur le canal\n"
-"en kickant les utilisateurs affectés, et LIMIT kickera les utilisateurs\n"
+"en kickant les utilisateurices affectés, et LIMIT kickera les utilisateurices\n"
"jusqu'à ce que leur nombre ne dépasse plus la limite du canal, si elle est définie."
msgid "English"
@@ -3944,12 +4036,12 @@ msgid "Error reloading configuration file: %s"
msgstr "Erreur en rechargeant le fichier de configuration : %s"
#, c-format
-msgid "Error! The vHost ident is too long, please use an ident shorter than %d characters."
-msgstr "Erreur ! L'ident du vHost est trop long, merci d'utiliser un ident plus court que %d caractères."
+msgid "Error! The vhost is too long, please use a hostname shorter than %zu characters."
+msgstr "Erreur ! Le vhost est trop long, merci d'utiliser un hostname plus court que %zu caractères."
#, c-format
-msgid "Error! The vHost is too long, please use a hostname shorter than %d characters."
-msgstr "Erreur ! Le vHost est trop long, merci d'utiliser un hostname plus court que %d caractères."
+msgid "Error! The vident is too long, please use an ident shorter than %zu characters."
+msgstr "Erreur ! La vident est trop longue, merci d'utiliser une ident plus court que %zu caractères."
msgid ""
"Examples:\n"
@@ -4005,7 +4097,7 @@ msgid "Fantasy mode is now on on channel %s."
msgstr "Le mode fantaisie est maintenant activé sur le canal %s."
msgid "Find a user's status on a channel"
-msgstr "Trouve le statut d'un utilisateur sur un canal"
+msgstr "Trouve le statut d'un(e) utilisateurice sur un canal"
#, c-format
msgid "Fingerprint %s already present on %s's certificate list."
@@ -4037,54 +4129,48 @@ msgstr ""
"et adresses email. Les jokers sont acceptés pour toutes les entrées."
msgid "Forbid list is empty."
-msgstr "La liste des interdits est vide."
+msgstr "La liste des interdit(e)s est vide."
msgid "Forbid list:"
-msgstr "Liste des interdits :"
+msgstr "Liste des interdit(e)s :"
#, c-format
msgid "Forbid on %s was not found."
msgstr "Interdiction sur %s non trouvée."
msgid "Forbid usage of nicknames, channels, and emails"
-msgstr "Interdit l'utilisation de pseudos, canaux et adresses email."
+msgstr "Interdit l'utilisation de pseudos, canaux et adresses email"
-msgid "Force the Services databases to be updated immediately"
-msgstr "Oblige les bases de données des Services à être sauvegardées immédiatement."
+msgid "Force the services databases to be updated immediately"
+msgstr "Oblige les bases de données des services à être sauvegardées immédiatement"
msgid "Forcefully change a user's nickname"
-msgstr "Force le changement de pseudo d'un utilisateur"
+msgstr "Force le changement de pseudo d'un(e) utilisateurice"
msgid "Forcefully changes a user's nickname from nick to newnick."
-msgstr "Force le changement de pseudo d'un utilisateur de pseudo à nouveau-pseudo."
+msgstr "Force le changement de pseudo d'un(e) utilisateurice de pseudo à nouveau-pseudo."
msgid "Forcefully join a user to a channel"
-msgstr "Oblige un utilisateur à joindre un canal."
+msgstr "Oblige un(e) utilisateurice à joindre un canal"
msgid "Forcefully join a user to a channel."
-msgstr "Oblige un utilisateur à joindre un canal."
+msgstr "Oblige un(e) utilisateurice à joindre un canal."
msgid "Forcefully part a user from a channel"
-msgstr "Oblige un utilisateur à partir d'un canal."
+msgstr "Oblige un(e) utilisateurice à partir d'un canal"
msgid "Forcefully part a user from a channel."
-msgstr "Oblige un utilisateur à partir d'un canal."
+msgstr "Oblige un(e) utilisateurice à partir d'un canal."
msgid "Founder"
-msgstr "Fondateur"
+msgstr "Fondateurice"
#, c-format
msgid "Founder of %s changed to %s."
-msgstr "Le fondateur de %s est maintenant %s."
-
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "La commande GETPASS est indisponible car le chiffrement est utilisé."
+msgstr "Le/la fondateurice de %s est maintenant %s."
msgid "Ghost with your nick has been killed."
-msgstr "L'utilisateur fantôme utilisant votre pseudo a été déconnecté."
-
-msgid "Give Operflags to a certain user"
-msgstr "Donne certains Operflags à un utilisateur"
+msgstr "L'utilisateurice fantôme utilisant votre pseudo a été déconnecté."
#, c-format
msgid ""
@@ -4106,7 +4192,7 @@ msgstr "Le message d'accueil sera affiché lors d'un JOIN"
#, c-format
msgid "Greet message for %s changed to %s."
-msgstr "Le message d'accueil de %s a été changé en %s"
+msgstr "Le message d'accueil de %s a été changé en %s."
#, c-format
msgid "Greet message for %s unset."
@@ -4175,7 +4261,7 @@ msgid "Ignore list is empty."
msgstr "La liste des ignorés est vide."
msgid "Ignore list:"
-msgstr "Liste des ignorés :"
+msgstr "Liste des ignoré(e)s :"
msgid "Immediate protection"
msgstr "Protection immédiate"
@@ -4190,11 +4276,11 @@ msgid "Info about a loaded module"
msgstr "Informations à propos d'un module chargé"
#, c-format
-msgid "Information for bot %s:"
+msgid "Information about bot %s:"
msgstr "Information à propos du bot %s :"
#, c-format
-msgid "Information for channel %s:"
+msgid "Information about channel %s:"
msgstr "Informations à propos du canal %s :"
#, c-format
@@ -4205,13 +4291,13 @@ msgid "Invalid expiry time."
msgstr "Temps d'expiration invalide."
msgid "Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames."
-msgstr "Masque d'hôte invalide. Seuls les masques d'hôtes réels sont valides puisque les exceptions ne sont pas comparées aux pseudos et utilisateurs."
+msgstr "Masque d'hôte invalide. Seuls les masques d'hôtes réels sont valides puisque les exceptions ne sont pas comparées aux pseudos et utilisateurices."
#, c-format
msgid "Invalid limit %s, using %d."
msgstr "Limite %s invalide, %d sera utilisé."
-msgid "Invalid passcode has been entered, please check the e-mail again, and retry."
+msgid "Invalid passcode has been entered, please check the email again, and retry."
msgstr "Un mot-code invalide a été entré, merci de re-vérifier votre email et de réessayer."
msgid "Invalid passcode."
@@ -4255,11 +4341,11 @@ msgid "Key for channel %s is %s."
msgstr "La clé du canal %s est %s."
msgid "Kick a user from a channel"
-msgstr "Expulse un utilisateur d'un canal"
+msgstr "Expulse un(e) utilisateurice d'un canal"
#, c-format
msgid "Kicked %d/%d users matching %s from %s."
-msgstr "A kické %d/%d utilisateurs correspondant à %s sur %s."
+msgstr "A kické %d/%d utilisateurices correspondant à %s sur %s."
msgid "Kicks a specified nick from a channel"
msgstr "Expulse le pseudo spécifié d'un canal"
@@ -4272,19 +4358,19 @@ msgid ""
msgstr ""
"Kicke le pseudo désigné d'un canal.\n"
" \n"
-"Par défaut, limité aux AOPs ou à ceux ayant un niveau \n"
-"d'accès de 5 ou plus sur le canal. Les fondateurs du salon\n"
+"Par défaut, limité aux AOPs ou à celleux ayant un niveau \n"
+"d'accès de 5 ou plus sur le canal. Les fondateurices du salon\n"
"peuvent aussi spécifier un masque."
msgid "Kill a user"
-msgstr "Kill un utilisateur"
+msgstr "Kill un(e) utilisateurice"
msgid "LIMIT enforced by "
msgstr "LIMIT appliquée par "
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr "LIMIT appliquée sur %s, %d utilisateurs supprimés."
+msgid "LIMIT enforced on %s, %zu users removed."
+msgstr "LIMIT appliquée sur %s, %zu utilisateurices supprimés."
msgid "LIST threshold"
msgstr "LIST seuil"
@@ -4301,8 +4387,9 @@ msgstr "LIST [pseudo]"
msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
msgstr "LOGONNEWS {ADD|DEL|LIST} [texte|numéro]"
-msgid "Language changed to English."
-msgstr "Votre langue est maintenant le Français."
+#, c-format
+msgid "Language changed to %s."
+msgstr "Votre langue est maintenant %s."
#, c-format
msgid "Language for %s changed to %s."
@@ -4339,7 +4426,7 @@ msgstr "Le niveau pour %s du channel %s est maintenant de %d."
#, c-format
msgid "Level for %s on channel %s changed to founder only."
-msgstr "Le niveau pour %s sur le canal %s est désormais restreint au fondateur."
+msgstr "Le niveau pour %s sur le canal %s est désormais restreint au fondateurice."
#, c-format
msgid "Level must be between %d and %d inclusive."
@@ -4380,7 +4467,7 @@ msgid ""
"Bots prefixed by a * are reserved for IRC Operators."
msgstr ""
"Liste tous les bots disponibles sur ce réseau.\n"
-"Les bots préfixés par * sont réservés aux Opérateurs IRC."
+"Les bots préfixés par * sont réservés aux Opérateurices IRC."
msgid "Lists all channel records"
msgstr "Liste tous les canaux"
@@ -4398,7 +4485,7 @@ msgstr ""
"soient enregistrés ou non.\n"
" \n"
"Si modèle est donné, seuls les canaux correspondants sont listés. Si\n"
-"un pseudo est donné, les canaux sur lesquels est l'utilisateur ayant\n"
+"un pseudo est donné, les canaux sur lesquels est l'utilisateurice ayant\n"
"ce pseudo seront listés. Si SECRET est spécifié, liste seulement les canaux \n"
"correspondants à modèle qui ont le mode +s ou +p."
@@ -4413,7 +4500,7 @@ msgstr ""
" \n"
"Les canaux qui ont l'option NOEXPIRE activée seront\n"
"préfixés d'un point d'exclamation. Le paramètre pseudo est\n"
-"restreint aux Opérateurs des Services."
+"restreint aux Opérateurices des Services"
msgid "Lists all nicknames in your group"
msgstr "Liste les pseudos dans votre groupe"
@@ -4450,9 +4537,9 @@ msgid ""
" Lists all registered channels within the given range (51-100)."
msgstr ""
"Liste tous les canaux enregistrés qui correspondent au modèle donné. Les\n"
-"canaux ayant l'option PRIVATE ne seront affichés qu'aux Opérateurs\n"
+"canaux ayant l'option PRIVATE ne seront affichés qu'aux Opérateurices\n"
"des Services avec les accès nécessaires. Les canaux ayant l'option\n"
-"NOEXPIRE seront préfixés par un ! pour les Opérateurs des \n"
+"NOEXPIRE seront préfixés par un ! pour les Opérateurices des \n"
"Services.\n"
"Notez qu'un modèle dont le premier caractère est '#' est une plage de\n"
"numéros. Les noms de canaux doivent être écrits sans '#'.\n"
@@ -4461,7 +4548,7 @@ msgstr ""
"seuls les canaux qui sont respectivement SUSPENDED ou NOEXPIRE\n"
"seront affichés. Si plusieurs options sont données, tous les canaux\n"
"correspondant à au moins une des options seront affichés.\n"
-"Notez que ces options sont limitées aux Opérateurs des Services.\n"
+"Notez que ces options sont limitées aux Opérateurices des Services.\n"
" \n"
"Exemples :\n"
" \n"
@@ -4507,9 +4594,9 @@ msgid ""
msgstr ""
"Liste tous les pseudos enregistrés qui correspondent au modèle\n"
"donné, de format pseudo!user@host. Les pseudos ayant l'option\n"
-"PRIVATE ne seront affichés qu'aux Opérateurs des Services. Les\n"
+"PRIVATE ne seront affichés qu'aux Opérateurices des Services. Les\n"
"pseudos ayant l'option NOEXPIRE auront leur pseudo préfixé\n"
-"par un ! pour les Opérateurs des Services.\n"
+"par un ! pour les Opérateurices des Services.\n"
" \n"
"Notez que si le premier caractère est '#', il s'agit d'une plage de numéros.\n"
" \n"
@@ -4517,7 +4604,7 @@ msgstr ""
"seuls les pseudos qui sont suspendus, non-confirmés ou qui n'expirent pas\n"
"seront affichés. Si plus d'une option sont indiquées, tous les pseudos\n"
"correspondants à un des critères seront affichés. Ces options sont restreintes\n"
-"aux Opérateurs des Services. \n"
+"aux Opérateurices des Services. \n"
" \n"
"Exemples :\n"
" \n"
@@ -4536,7 +4623,7 @@ msgstr ""
" Liste tous les pseudos enregistrés entre 51 et 100."
msgid "Lists all user records"
-msgstr "Liste tous les utilisateurs"
+msgstr "Liste toustes les utilisateurices"
msgid ""
"Lists all users currently online on the IRC network, whether their\n"
@@ -4547,13 +4634,13 @@ msgid ""
"only users that are on the given channel. If INVISIBLE is specified, only users\n"
"with the +i flag will be listed."
msgstr ""
-"Liste tous les utilisateurs connectés sur le réseau IRC, enregistrés\n"
+"Liste toustes les utilisateurices connectés sur le réseau IRC, enregistrés\n"
"ou non.\n"
" \n"
-"Si modèle est donné (format pseudo!user@host), seuls les utilisateurs \n"
+"Si modèle est donné (format pseudo!user@host), seuls les utilisateurices \n"
"correspondants seront listés. Si canal est donné, seuls les \n"
-"utilisateurs du canal seront listés. Si INVISIBLE est indiqué,\n"
-"seuls les utilisateurs avec le mode +i seront listés."
+"utilisateurices du canal seront listés. Si INVISIBLE est indiqué,\n"
+"seuls les utilisateurices avec le mode +i seront listés."
msgid ""
"Lists any memos you currently have. With NEW, lists only\n"
@@ -4563,7 +4650,7 @@ msgid ""
" LIST 2-5,7-9\n"
" Lists memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Liste tous les mémos que vous avez actuellement. Avec NEW,\n"
+"Liste toustes les mémos que vous avez actuellement. Avec NEW,\n"
"liste uniquement les nouveaux mémos (non lus). Les mémos non\n"
"lus sont marqués avec une \"*\" à gauche du numéro du mémo. Vous\n"
"pouvez également spécifier une liste de numéros, comme dans\n"
@@ -4589,9 +4676,9 @@ msgid ""
"time will also be displayed when applicable."
msgstr ""
"Liste les informations concernant un canal enregistré,\n"
-"notamment son fondateur, la date d'enregistrement,\n"
-"la date de dernière utilisation et la description. Si l'utilisateur\n"
-"qui exécute la commande a les accès appropriés, alors le successeur,\n"
+"notamment son/sa fondateurice, la date d'enregistrement,\n"
+"la date de dernière utilisation et la description. Si l'utilisateurice\n"
+"qui exécute la commande a les accès appropriés, alors le/la successeur(e),\n"
"le dernier topic défini, les paramètres et le délai d'expiration\n"
" seront également affichés s'ils sont disponibles."
@@ -4642,7 +4729,7 @@ msgid ""
"This command may be unnecessary if your oper block is\n"
"configured without a password."
msgstr ""
-"Vous connecte à %s pour obtenir les privilèges d'Opérateur des Services.\n"
+"Vous connecte à %s pour obtenir les privilèges d'Opérateurice des Services.\n"
"Cette commande est utile uniquement si votre bloc oper est configuré\n"
"avec un mot de passe."
@@ -4653,7 +4740,7 @@ msgid ""
"with a password."
msgstr ""
"Vous déconnecte de %s pour que vous n'ayez plus les privilèges\n"
-"d'Opérateur des Services. Cette commande est utile uniquement si\n"
+"d'Opérateurice des Services. Cette commande est utile uniquement si\n"
"votre bloc oper est configuré avec un mot de passe."
#, c-format
@@ -4700,7 +4787,7 @@ msgstr ""
"peuvent être donnés en tant que paramètre pour les modes de statut et de listes.\n"
"Exemple :\n"
" MODE #canal SET +v *\n"
-" Donne le statut voice à tous les utilisateurs du canal.\n"
+" Donne le statut voice à toustes les utilisateurices du canal.\n"
" \n"
" MODE #canal SET -b ~c:*\n"
" Supprime tous les bans étendus qui commencent par ~c:\n"
@@ -4721,8 +4808,9 @@ msgid ""
"on the %s list receive the following privileges:\n"
" "
msgstr ""
-"Gère la liste des %s pour un canal. Les utilisateurs qui correspondent à un\n"
-"une entrée sur la liste des %s recevront les privilèges suivants :"
+"Gère la liste des %s pour un canal. Les utilisateurices qui correspondent à\n"
+"une entrée sur la liste des %s recevront les privilèges suivants :\n"
+" "
#, c-format
msgid ""
@@ -4740,18 +4828,18 @@ msgid ""
"will be added to the akick list instead of the mask.\n"
"All users within that nickgroup will then be akicked.\n"
msgstr ""
-"Gère la liste des AutoKicks sur un canal. Si un utilisateur\n"
+"Gère la liste des AutoKicks sur un canal. Si un(e) utilisateurice\n"
"sur la liste des kicks automatiques tente de joindre le canal, %s\n"
-"bannira cet utilisateur du canal, puis le kickera.\n"
+"bannira cet(te) utilisateurice du canal, puis le kickera.\n"
" \n"
"La commande AKICK ADD ajoute le pseudo ou le masque\n"
-"utilisateur donné à la liste des kicks automatiques. Si une raison est\n"
+"utilisateurice donné à la liste des kicks automatiques. Si une raison est\n"
"donnée avec la commande, cette raison sera utilisée lors du kick\n"
-"de l'utilisateur, sinon, la raison par défaut \"L'utilisateur a été banni\n"
+"de l'utilisateurice, sinon, la raison par défaut \"L'utilisateurice a été banni(e)\n"
"du canal\".\n"
"Si le pseudo est enregistré le compte %s\n"
"sera ajouté à la liste des kicks automatiques à la place du masque.\n"
-"Tous les utilisateurs de ce groupe seront akick.\n"
+"Tous les utilisateurices de ce groupe seront akick.\n"
#, c-format
msgid ""
@@ -4764,18 +4852,18 @@ msgid ""
"of -1."
msgstr ""
"Gère la liste d'accès d'un canal. La liste d'accès spécifie\n"
-"quels utilisateurs doivent obtenir le statut d'opérateur ou\n"
-"accéder aux commandes %s du canal. Des niveaux d'utilisateur\n"
+"quels utilisateurices doivent obtenir le statut d'opérateurice ou\n"
+"accéder aux commandes %s du canal. Des niveaux d'utilisateurice\n"
"différents existent pour des accès à différents types de privilèges.\n"
-"Un utilisateur enregistré qui n'est pas sur la liste d'accès a un niveau\n"
-"utilisateur de 0 et un utilisateur non-enregistré a un niveau de -1."
+"Un utilisateurice enregistré(e) qui n'est pas sur la liste d'accès a un niveau\n"
+"utilisateurice de 0 et un(e) utilisateurice non-enregistré(e) a un niveau de -1."
#, c-format
msgid ""
"Maintains the bad words list for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
+"type %s HELP KICK %s.\n"
" \n"
"The ADD command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -4790,17 +4878,17 @@ msgstr ""
"Gère la liste des mots interdits d'un canal. La liste\n"
"des mots interdits détermine quels mots doivent être kickés\n"
"quand le kicker de mots interdits est activé. Pour plus\n"
-"d'information, tapez %s%s HELP KICK %s.\n"
+"d'information, tapez %s HELP KICK %s.\n"
" \n"
"La commande ADD ajoute le mot donné à la liste\n"
"de mots interdits. Si SINGLE est donné, un kick ne sera\n"
-"effectué que si un utilisateur dit le mot en entier. Si\n"
+"effectué que si un(e) utilisateurice dit le mot en entier. Si\n"
"START est donné, un kick ne sera effectué que si un\n"
-"utilisateur dit un mot qui commence par mot. Si END\n"
-"est spécifié, un kick ne sera effectué que si un utilisateur\n"
+"utilisateurice dit un mot qui commence par mot. Si END\n"
+"est spécifié, un kick ne sera effectué que si un(e) utilisateurice\n"
"dit un mot qui se termine par mot. Si vous ne spécifiez\n"
"rien, un kick sera effectué chaque fois que mot est dit\n"
-"par un utilisateur.\n"
+"par un(e) utilisateurice.\n"
" \n"
msgid "Maintains the bad words list"
@@ -4817,7 +4905,7 @@ msgstr ""
"sur le canal donné avec le texte donné."
msgid "Makes the bot say the specified text on the specified channel"
-msgstr "Fait dire au bot le texte donné sur un canal."
+msgstr "Fait dire au bot le texte donné sur un canal"
msgid "Makes the bot say the specified text on the specified channel."
msgstr "Fait dire au bot le texte donné sur un canal."
@@ -4856,6 +4944,9 @@ msgstr "Gère la liste d'ignore de mémos"
msgid "Manage your auto join list"
msgstr "Gère la liste des JOIN automatiques"
+msgid "Manages your pending message queue."
+msgstr "Gère votre file d'attente de messages."
+
#, c-format
msgid "Manipulate the %s list"
msgstr "Contrôle la liste des %s"
@@ -4872,15 +4963,11 @@ msgstr "Change le sujet sur un canal spécifié"
msgid "Mask"
msgstr "Masque"
-#, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "Le masque %s existe déjà dans la liste d'accès de %s."
-
msgid "Mask must be in the form user@host."
msgstr "Le masque doit être de la forme user@host."
msgid "Masks and unregistered users may not be on access lists."
-msgstr "Les masques et les utilisateurs non enregistrés ne peuvent pas être dans la liste d'accès."
+msgstr "Les masques et les utilisateurices non enregistré(e)s ne peuvent pas être dans la liste d'accès."
msgid "Matches and returns all users that registered using given email"
msgstr "Cherche et retourne la liste des pseudos enregistrés avec l'email donné"
@@ -4891,7 +4978,7 @@ msgstr "Correspondances pour %s :"
#, c-format
msgid "Maximum users: %d (%s)"
-msgstr "Record d'utilisateurs : %d (%s)"
+msgstr "Record d'utilisateurices : %d (%s)"
#, c-format
msgid "Memo %d from %s (%s)."
@@ -4901,6 +4988,10 @@ msgstr "Mémo %d par %s (%s)."
msgid "Memo %d has been deleted."
msgstr "Le mémo %d a été supprimé."
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr "Le mémo %zu a été supprimé."
+
msgid "Memo ignore list is empty."
msgstr "La liste des ignorés est vide."
@@ -4937,6 +5028,10 @@ msgstr "Méthode"
msgid "Missing parameter for mode %c."
msgstr "Paramètre manquant pour le mode %c."
+#, c-format
+msgid "Missing passwords: %zu"
+msgstr "Mots de passe manquants : %zu"
+
msgid "Mode"
msgstr "Mode"
@@ -4962,48 +5057,6 @@ msgstr "Modes"
msgid "Modes cleared on %s and the channel destroyed."
msgstr "Modes supprimés sur %s et canal détruit."
-#, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
-msgstr ""
-"Modifie ou affiche la liste d'accès de votre pseudo. C'est\n"
-"la liste des adresses qui seront automatiquement reconnues\n"
-"par %s comme autorisées à utiliser le pseudo. Si vous voulez\n"
-"utiliser le pseudo depuis une adresse différente, vous devez\n"
-"envoyer une commande IDENTIFY pour que %s vous reconnaisse.\n"
-"Les Opérateurs des Services peuvent indiquer un pseudo pour\n"
-"modifier la liste d'accès d'un autre utilisateur.\n"
-" \n"
-"Exemples :\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Autorise l'accès à l'utilisateur anyone d'une\n"
-" machine avec le domaine bepeg.com.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Inverse de la commande précédente.\n"
-" \n"
-" ACCESS LIST\n"
-" Affiche votre liste d'accès."
-
msgid ""
"Modifies or displays the certificate list for your nick.\n"
"If you connect to IRC and provide a client certificate with a\n"
@@ -5016,26 +5069,23 @@ msgstr ""
"Si vous vous connectez à IRC et fournissez un certificat avec\n"
"une empreinte (fingerprint) dans la liste des certificats, votre\n"
"pseudo sera automatiquement identifié auprès des services.\n"
-"Les Opérateurs des Services peuvent fournir un pseudo\n"
-"pour modifier la liste de certificats d'autres utilisateurs\n"
+"Les Opérateurices des Services peuvent fournir un pseudo\n"
+"pour modifier la liste de certificats d'autres utilisateurices\n"
" \n"
-msgid "Modify the Services ignore list"
-msgstr "Modifie la liste d'ignore des Services"
-
#, c-format
msgid "Modify the list of %s users"
-msgstr "Modifie la liste des utilisateurs %s"
-
-msgid "Modify the list of authorized addresses"
-msgstr "Modifie la liste des adresses autorisées"
+msgstr "Modifie la liste des utilisateurices %s"
msgid "Modify the list of privileged users"
-msgstr "Modifie la liste des utilisateurs privilégiés"
+msgstr "Modifie la liste des utilisateurices privilégiés"
msgid "Modify the nickname client certificate list"
msgstr "Modifie la liste de certificats du pseudo"
+msgid "Modify the services ignore list"
+msgstr "Modifie la liste d'ignore des services"
+
msgid "Modify the session-limit exception list"
msgstr "Modifie la liste d'exceptions à la limite de sessions"
@@ -5073,6 +5123,10 @@ msgstr "Module : %s Version : %s Auteur : %s Chargé : %s"
msgid "Module: %s [%s] [%s]"
msgstr "Module : %s [%s] [%s]"
+#, c-format
+msgid "Multiple languages matched %s. Please be more specific."
+msgstr "Plusieurs langues correspondent à %s. Soyez plus précis(e)."
+
msgid "Name"
msgstr "Nom"
@@ -5086,6 +5140,9 @@ msgstr "Statistiques de réseau pour %s :"
msgid "Never"
msgstr "Jamais"
+msgid "Never-op"
+msgstr "Jamais-op"
+
msgid "Nick"
msgstr "Pseudo"
@@ -5095,7 +5152,7 @@ msgstr "Le pseudo %s a été confirmé."
#, c-format
msgid "Nick %s is already an operator."
-msgstr "Le pseudo %s est déjà un opérateur."
+msgstr "Le pseudo %s est déjà opérateurice."
#, c-format
msgid "Nick %s is already confirmed."
@@ -5119,7 +5176,7 @@ msgstr "Le pseudo %s est interdit."
#, c-format
msgid "Nick %s is not a Services Operator."
-msgstr "%s n'est pas un Opérateur des Services."
+msgstr "%s n'est pas un(e) Opérateurice des Services."
#, c-format
msgid "Nick %s is part of this Network's Services."
@@ -5134,8 +5191,8 @@ msgid "Nick %s isn't registered."
msgstr "Le pseudo %s n'est pas enregistré."
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Le pseudo %s a été tronqué à %d caractères."
+msgid "Nick %s was truncated to %zu characters."
+msgstr "Le pseudo %s a été tronqué à %zu caractères."
#, c-format
msgid "Nick %s will expire."
@@ -5177,9 +5234,12 @@ msgstr "Le pseudo %s a été libéré."
msgid "Nick %s is now suspended."
msgstr "Le pseudo %s a été suspendu."
+msgid "Nick registered"
+msgstr "Pseudo enregistré"
+
#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr "Pseudo trop long, la taille maximale est de %u caractères."
+msgid "Nick too long, max length is %zu characters."
+msgstr "Pseudo trop long, la taille maximale est de %zu caractères."
#, c-format
msgid "Nickname %s has been dropped."
@@ -5194,10 +5254,6 @@ msgid "Nickname %s may not be registered."
msgstr "Le pseudo %s ne peut pas être enregistré."
#, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr "Le pseudo %s est maintenant enregistré sous votre masque : %s"
-
-#, c-format
msgid "Nickname %s registered."
msgstr "Le pseudo %s est maintenant enregistré."
@@ -5229,6 +5285,9 @@ msgstr "Aucune news de connexion à supprimer !"
msgid "No matches for %s found."
msgstr "Aucune correspondance pour %s trouvée."
+msgid "No matching entries in your message queue."
+msgstr "Aucune entrée correspondante dans votre file d'attente de messages."
+
#, c-format
msgid "No matching entries on %s %s list."
msgstr "Aucune entrée correspondante sur la liste des %2$s de %1$s."
@@ -5290,7 +5349,7 @@ msgid "No request for nick %s found."
msgstr "Pas de requête trouvée pour le pseudo %s."
msgid "No signed kick when SIGNKICK LEVEL is used"
-msgstr "Pas de kick signés lorsque SIGNKICK LEVEL est utilisé."
+msgstr "Pas de kick signés lorsque SIGNKICK LEVEL est utilisé"
#, c-format
msgid "No stats for %s."
@@ -5302,7 +5361,7 @@ msgstr "Aucune informations \"%s\" sur %s."
#, c-format
msgid "No users on %s match %s."
-msgstr "Aucun utilisateur sur %s ne correspond à %s."
+msgstr "Aucun(e) utilisateurice sur %s ne correspond à %s."
#, c-format
msgid "No-bot mode is now off on channel %s."
@@ -5326,10 +5385,10 @@ msgid ""
"become the new founder and it will be as if the\n"
"channel had no successor set."
msgstr ""
-"Cependant, si le successeur a déjà trop de canaux\n"
-"enregistrés (%d), il ne pourra pas devenir le nouveau \n"
-"fondateur, et le canal sera effacé à la place,\n"
-"comme si aucun successeur n'avait été défini."
+"Cependant, si le/la successeur(e) a déjà trop de canaux\n"
+"enregistrés (%d), iel ne pourra pas devenir le nouveau \n"
+"fondateurice, et le canal sera effacé à la place,\n"
+"comme si aucun successeur(e) n'avait été défini."
msgid "Nothing to do."
msgstr "Rien à faire."
@@ -5371,27 +5430,19 @@ msgstr "Privilèges d'oper retirés de %s (%s)."
#, c-format
msgid "Oper type %s has not been configured."
-msgstr "Le type d'opérateur %s n'a pas été configuré."
-
-#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "Les operflags %s ont été ajoutés à %s."
-
-#, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "Les operflags %s ont été retirés de %s."
+msgstr "Le type d'oper %s n'a pas été configuré."
#, c-format
msgid "Opertype %s has no allowed commands."
-msgstr "Le type d'opérateur %s n'a aucune commande autorisée."
+msgstr "Le type d'oper %s n'a aucune commande autorisée."
#, c-format
msgid "Opertype %s has no allowed privileges."
-msgstr "Le type d'opérateur %s n'a aucun privilège autorisé."
+msgstr "Le type d'oper %s n'a aucun privilège autorisé."
#, c-format
msgid "Opertype %s receives modes %s once identified."
-msgstr "Le type d'opérateur %s reçoit les modes %s une fois identifié."
+msgstr "Le type d'oper %s reçoit les modes %s une fois identifié."
msgid "Ops protection"
msgstr "Protection des OPs"
@@ -5412,17 +5463,9 @@ msgid "Password accepted."
msgstr "Mot de passe accepté."
#, c-format
-msgid "Password for %s changed to %s."
-msgstr "Le mot de passe de %s a été changé en %s."
-
-#, c-format
msgid "Password for %s changed."
msgstr "Le mot de passe de %s a été changé."
-#, c-format
-msgid "Password for %s is %s."
-msgstr "Le mot de passe de %s est %s."
-
msgid "Password incorrect."
msgstr "Mot de passe incorrect."
@@ -5430,6 +5473,15 @@ msgstr "Mot de passe incorrect."
msgid "Password reset email for %s has been sent."
msgstr "Un email de réinitialisation de mot de passe pour %s a été envoyé."
+msgid "Passwords can not be changed right now. Please try again later."
+msgstr ""
+"Impossible de changer de mot de passe maintenant, veuillez réessayez un peu\n"
+"plus tard."
+
+#, c-format
+msgid "Passwords encrypted with %s: %zu"
+msgstr "Mots de passes chiffrés avec %s: %zu"
+
msgid "Peace"
msgstr "Paix"
@@ -5444,18 +5496,21 @@ msgstr "Le mode 'paix' est désormais ACTIF pour %s."
msgid "Persistent"
msgstr "Persistant"
-msgid "Please contact an Operator to get a vHost assigned to this nick."
-msgstr "Merci de contacter un Opérateur pour obtenir un vHost assigné pour ce pseudo."
+#, c-format
+msgid "Please confirm that you want to drop %s with %s DROP %s %s"
+msgstr "Veuillez confirmer que vous voulez supprimer %s avec %s DROP %s %s"
+
+msgid "Please contact an Operator to get a vhost assigned to this nick."
+msgstr "Merci de contacter un(e) Opérateurice pour obtenir un vhost assigné à ce pseudo."
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
"Merci de réessayer avec un mot de passe plus difficile à deviner. Les mots de passe\n"
-"devraient comporter au moins cinq caractères, ne pas être facilement devinables\n"
-"(comme votre nom ou votre pseudo) et ne peuvent pas contenir d'espace ou de\n"
-"tabulation."
+"ne pas être facilement devinables (comme votre nom ou votre pseudo) et ne peuvent\n"
+"pas contenir d'espace ou de tabulation.\n"
msgid "Please use a valid server name when juping."
msgstr "Veuillez indiquer un nom de serveur valide pour JUPE."
@@ -5464,24 +5519,24 @@ msgid "Please use the symbol of # when attempting to register."
msgstr "Merci d'utiliser le symbole # lorsque vous tentez d'enregistrer un canal."
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Attendez %d secondes et réessayez."
+msgid "Please wait %lu seconds and retry."
+msgstr "Attendez %lu secondes et réessayez."
#, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Veuillez patienter %d secondes avant de redemander un nouveau vHost."
+msgid "Please wait %s before requesting a new vhost."
+msgstr "Veuillez patienter %s avant de redemander un nouveau vhost."
#, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Veuillez patienter %d secondes avant d'utiliser la commande %s à nouveau."
+msgid "Please wait %s before using the %s command again."
+msgstr "Veuillez patienter %s avant d'utiliser la commande %s à nouveau."
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Veuillez patienter %d secondes avant d'utiliser la commande GROUP à nouveau."
+msgid "Please wait %s before using the GROUP command again."
+msgstr "Veuillez patienter %s avant d'utiliser la commande GROUP à nouveau."
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "Veuillez patienter %d secondes avant d'utiliser la commande REGISTER à nouveau."
+msgid "Please wait %s before using the REGISTER command again."
+msgstr "Veuillez patienter %s avant d'utiliser la commande REGISTER à nouveau."
#, c-format
msgid "Pooled %s."
@@ -5494,13 +5549,13 @@ msgid "Pooled/Not Active"
msgstr "Dans la pool/Inactif"
msgid "Prevent a bot from being assigned by non IRC operators"
-msgstr "Empêche un bot d'être assigné par un utilisateur non opérateur IRC."
+msgstr "Empêche un bot d'être assigné par un(e) utilisateurice non opérateurice IRC"
msgid "Prevent a bot from being assigned to a channel"
msgstr "Empêche un bot d'être assigné à un canal"
msgid "Prevent a channel from being used preserving channel data and settings"
-msgstr "Suspend un canal pour ne pas qu'il soit utilisé tout en conservant les données et configurations."
+msgstr "Suspend un canal pour ne pas qu'il soit utilisé tout en conservant les données et configurations"
msgid "Prevent the channel from expiring"
msgstr "Empêche le canal d'expirer"
@@ -5511,8 +5566,8 @@ msgstr "Empêche le pseudo d'apparaître dans la commande LIST"
msgid "Prevent the nickname from expiring"
msgstr "Empêche le pseudo d'expirer"
-msgid "Prevents users being kicked by Services"
-msgstr "Empêche des utilisateurs d'être kickés par les services"
+msgid "Prevents users being kicked by services"
+msgstr "Empêche des utilisateurices d'être kickés par les services"
msgid "Private"
msgstr "Privé"
@@ -5575,7 +5630,7 @@ msgid ""
msgstr ""
"Inflige un AKILL à toutes les personnes qui sont sur le canal spécifié.\n"
"Ceci utilise le masque ident@host réel de tous les pseudos et\n"
-"applique le AKILL. "
+"applique le AKILL."
msgid "Quick protection"
msgstr "Protection rapide"
@@ -5627,11 +5682,11 @@ msgid ""
"GHOST command). If they are not identified they will be\n"
"forced off of the nick."
msgstr ""
-"Récupère votre pseudo pris par un autre utilisateur ou par\n"
+"Récupère votre pseudo pris par un(e) autre utilisateurice ou par\n"
"les services. Si les services détiennent votre pseudo, la\n"
-"détention sera annulée. Si un autre utilisateur détient votre\n"
-"pseudo et est identifié, il sera déconnecté du serveur (comme\n"
-"avec l'ancienne commande GHOST). S'il n'est pas identifié, son\n"
+"détention sera annulée. Si un(e) autre utilisateurice détient votre\n"
+"pseudo et est identifié, iel sera déconnecté du serveur (comme\n"
+"avec l'ancienne commande GHOST). Si iel n'est pas identifié(e), son\n"
"pseudo sera changé de force."
msgid "Redefine the meanings of access levels"
@@ -5669,20 +5724,20 @@ msgid "Registered"
msgstr "Enregistré"
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Canaux enregistrés : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Canaux enregistrés : %zu entrées, %zu paniers, plus longue chaîne : %zu"
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Groupe de pseudos enregistrés : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Groupe de pseudos enregistrés : %zu entrées, %zu paniers, plus longue chaîne : %zu"
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Pseudos enregistrés : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Pseudos enregistrés : %zu entrées, %zu paniers, plus longue chaîne : %zu"
#, c-format
msgid "Registered only enforced on %s."
-msgstr "Application sur %s de la restriction aux seuls pseudos enregistrés"
+msgstr "Application sur %s de la restriction aux seuls pseudos enregistrés."
#, c-format
msgid ""
@@ -5699,14 +5754,14 @@ msgid ""
"channel operator privileges when they enter the channel."
msgstr ""
"Enregistre un canal dans la base de données de %s. Pour utiliser\n"
-"cette commande, vous devez d'abord être opérateur du canal\n"
+"cette commande, vous devez d'abord être opérateurice du canal\n"
"que vous souhaitez enregistrer. La description, qui est facultative,\n"
"est une description générale de l'utilité du canal.\n"
" \n"
-"Lorsque vous enregistrez un canal, vous êtes défini en tant que \"fondateur\"\n"
-"du canal. Le fondateur est autorisé à changer tous les paramètres du canal.\n"
+"Lorsque vous enregistrez un canal, vous êtes défini en tant que \"fondateurice\"\n"
+"du canal. Le fondateurice est autorisé à changer tous les paramètres du canal.\n"
"%s lui donnera automatiquement les privilèges de propriétaire\n"
-"du canal lorsqu'il joindra le canal."
+"du canal lorsqu'iel joindra le canal."
#, c-format
msgid ""
@@ -5725,7 +5780,7 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
"Enregistre votre pseudo dans la base de données de %s.\n"
@@ -5746,7 +5801,7 @@ msgstr ""
"ne vous laissera pas faire.. De même, les mots de passe\n"
"courts sont vulnérables aux recherches méthodiques,\n"
"donc vous devez choisir un mot de passe d'au moins \n"
-"5 caractères. Le caractère espace ne peut pas être \n"
+"%u caractères. Le caractère espace ne peut pas être \n"
"utilisé dans les mots de passe."
msgid "Registration is currently disabled."
@@ -5755,11 +5810,11 @@ msgstr "L'enregistrement des pseudos est temporairement désactivé."
msgid "Regulate the use of critical commands"
msgstr "Régule l'utilisation de commandes sensibles"
-msgid "Reject the requested vHost for the given nick."
-msgstr "Refuse la demande de vHost par le pseudo indiqué."
+msgid "Reject the requested vhost for the given nick."
+msgstr "Refuse la demande de vhost par le pseudo indiqué."
-msgid "Reject the requested vHost of a user"
-msgstr "Refuse la demande de vhost d'un pseudo"
+msgid "Reject the requested vhost of a user"
+msgstr "Refuse la demande de vhost d'un(e) utilisateurice"
msgid "Releases a suspended channel"
msgstr "Libère un canal suspendu"
@@ -5776,16 +5831,16 @@ msgid "Reload a module"
msgstr "Recharge un module"
msgid "Reload services' configuration file"
-msgstr "Recharge le fichier de configuration des Services"
+msgstr "Recharge le fichier de configuration des services"
msgid "Remove a nick from a group"
msgstr "Enlève un pseudo d'un groupe"
msgid "Remove all bans preventing a user from entering a channel"
-msgstr "Supprime tous les bans qui empêche un utilisateur d'entrer sur un canal"
+msgstr "Supprime tous les bans qui empêche un(e) utilisateurice d'entrer sur un canal"
msgid "Remove all operators from a server remotely"
-msgstr "Supprime tous les Opérateurs d'un serveur"
+msgstr "Supprime toustes les Opérateurices d'un serveur"
#, c-format
msgid "Removed IP %s from %s."
@@ -5830,16 +5885,16 @@ msgstr "Supprime %s parce que %s le couvre."
msgid "Repeat kicker"
msgstr "Kicker de répétition"
-msgid "Request a vHost for your nick"
-msgstr "Fait une requête de vHost pour votre pseudo"
+msgid "Request a vhost for your nick"
+msgstr "Fait une requête de vhost pour votre pseudo"
msgid ""
-"Request the given vHost to be activated for your nick by the\n"
+"Request the given vhost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."
msgstr ""
"Demande que le vhost indiqué soit activé pour votre pseudo par les\n"
-"administrateurs du réseau. Merci d'être patient pendant que votre\n"
+"administrateurices du réseau. Merci d'être patient(e) pendant que votre\n"
"requête est examinée."
msgid "Resend registration confirmation email"
@@ -5861,7 +5916,7 @@ msgstr "L'option d'accès restreint pour %s est maintenant ACTIVE."
#, c-format
msgid "Restricted enforced on %s."
-msgstr "Restrictions d'accès appliquées sur %s"
+msgstr "Restrictions d'accès appliquées sur %s."
msgid "Retain modes when channel is not in use"
msgstr "Maintient les modes quand le canal n'est pas utilisé"
@@ -5869,9 +5924,6 @@ msgstr "Maintient les modes quand le canal n'est pas utilisé"
msgid "Retain topic when channel is not in use"
msgstr "Maintient le topic quand le canal n'est pas utilisé"
-msgid "Retrieve the password for a nickname"
-msgstr "Récupère le mot de passe d'un pseudo"
-
msgid "Retrieves the vhost requests"
msgstr "Récupère les requêtes de vhosts"
@@ -5879,61 +5931,11 @@ msgid "Returns the key of the given channel"
msgstr "Retourne la clé du canal spécifié"
msgid "Returns the key of the given channel."
-msgstr "Retourne la clé du canal spécifié"
+msgstr "Retourne la clé du canal spécifié."
msgid "Returns the matching accounts that used given email."
msgstr "Retourne les comptes utilisant l'adresse email indiquée."
-msgid "Returns the owner status of the given nickname"
-msgstr "Renvoie le niveau d'identification du pseudo donné"
-
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Retourne le mot de passe du pseudo donné.\n"
-"Note : Lorsque cette commande est utilisée, un message indiquant\n"
-"la personne qui a utilisé la commande et le pseudo recherché\n"
-"est ajouté dans les logs et envoyé en WALLOPS/GLOBOPS."
-
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
-msgstr ""
-"Retourne si l'utilisateur utilisant le pseudo donné est reconnu\n"
-"en tant que propriétaire du pseudo. La réponse est de ce format :\n"
-" \n"
-" pseudo code-statut compte\n"
-" \n"
-"Où pseudo est le pseudo concerné,\n"
-"code-statut est l'un des codes suivants, et compte\n"
-"le compte avec lequel il est connecté.\n"
-" \n"
-" 0 - aucun utilisateur connecté avec ce pseudo ou\n"
-" le pseudo n'est pas enregistré\n"
-" 1 - utilisateur non reconnu comme propriétaire\n"
-" 2 - utilisateur reconnu comme propriétaire uniquement via\n"
-" la liste d'accès\n"
-" 3 - utilisateur reconnu comme propriétaire via l'identification\n"
-" \n"
-"Si aucun pseudo n'est donné, votre propre statut sera retourné."
-
msgid "Reverses kicker"
msgstr "Kicker de reverses"
@@ -5955,27 +5957,27 @@ msgstr "Empreinte de certificat SSL acceptée, vous êtes maintenant identifié(
#, c-format
msgid "SSL only enforced on %s."
-msgstr "Application sur %s de la restriction aux seuls utilisateurs connectés en SSL."
+msgstr "Application sur %s de la restriction aux seuls utilisateurices connectés en SSL."
msgid "SSLONLY enforced by "
msgstr "SSLONLY appliqué par "
-msgid "Save databases and restart Services"
-msgstr "Sauvegarde les bases de données et relance les services."
+msgid "Save databases and restart services"
+msgstr "Sauvegarde les bases de données et relance les services"
msgid "Searches logs for a matching pattern"
-msgstr "Recherche les correspondances au modèle dans le fichier de logs."
+msgstr "Recherche les correspondances au modèle dans le fichier de logs"
msgid "Secure founder"
-msgstr "Sécurité du fondateur"
+msgstr "Sécurité de fondateurice"
#, c-format
msgid "Secure founder option for %s is now off."
-msgstr "L'option de sécurité du fondateur sur %s est INACTIVE."
+msgstr "L'option de sécurité de fondateurice sur %s est INACTIVE."
#, c-format
msgid "Secure founder option for %s is now on."
-msgstr "L'option de sécurité du fondateur sur %s est ACTIVE."
+msgstr "L'option de sécurité de fondateurice sur %s est ACTIVE."
msgid "Secure ops"
msgstr "Sécurité des OPs"
@@ -5989,58 +5991,42 @@ msgid "Secure ops option for %s is now on."
msgstr "La sécurité des OPs sur %s est maintenant ACTIVE."
#, c-format
-msgid "Secure option for %s is now off."
-msgstr "L'option de sécurité sur %s est INACTIVE."
-
-#, c-format
-msgid "Secure option for %s is now on."
-msgstr "L'option de sécurité sur %s est ACTIVE."
-
-#, c-format
-msgid "Secure option is now off for %s."
-msgstr "L'option de sécurité est maintenant INACTIVE pour %s."
-
-#, c-format
-msgid "Secure option is now on for %s."
-msgstr "L'option de sécurité est maintenant ACTIVE pour %s."
-
-#, c-format
msgid "Secureops enforced on %s."
msgstr "Application sur %s de la sécurité des OPs."
-msgid "Security"
-msgstr "Sécurité"
-
#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the access list."
msgstr ""
-"Tapez %s%s HELP %s pour plus d'informations sur\n"
+"Tapez %s HELP %s pour plus d'informations sur\n"
"la liste d'accès."
#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the flags system."
msgstr ""
-"Tapez %s%s HELP %s pour plus d'informations sur\n"
+"Tapez %s HELP %s pour plus d'informations sur\n"
"le système des flags."
msgid "Send a memo to a nick or channel"
msgstr "Envoie un mémo à un pseudo ou un canal"
msgid "Send a memo to all opers/admins"
-msgstr "Envoie un mémo à tous les opérateurs."
+msgstr "Envoie un mémo à toustes les opérateurices/admins"
msgid "Send a memo to all registered users"
msgstr "Envoie un mémo à tous les pseudos enregistrés"
msgid "Send a message to all users"
-msgstr "Envoie un message à tous les utilisateurs"
+msgstr "Envoie un message à tous les utilisateurices"
+
+msgid "Send a message to all users on a server"
+msgstr "Envoie un message à toustes les utilisateurices sur un serveur"
msgid "Sender"
-msgstr "Expéditeur"
+msgstr "Expéditeurice"
msgid "Sends a memo and requests a read receipt"
msgstr "Envoie un mémo et demande un accusé de réception"
@@ -6057,7 +6043,7 @@ msgid "Sends all registered users a memo containing memo-text."
msgstr "Envoie un mémo dont le message est texte à tous les pseudos enregistrés."
msgid "Sends all services staff a memo containing memo-text."
-msgstr "Envoie un mémo dont le message est texte à tous le staff des services."
+msgstr "Envoie un mémo dont le message est texte à tout le staff des services."
msgid ""
"Sends the named nick or channel a memo containing\n"
@@ -6066,8 +6052,8 @@ msgid ""
"nickname/channel must be registered."
msgstr ""
"Envoie un mémo dont le teste est texte au pseudo ou canal\n"
-"indiqué. En envoyant à un pseudo, le destinataire recevra une notice l'informant\n"
-"qu'il ou elle a reçu un nouveau mémo. Le destinataire doit être un pseudo ou\n"
+"indiqué. En envoyant à un pseudo, le/la destinataire recevra une notice l'informant\n"
+"qu'iel a reçu un nouveau mémo. Le/la destinataire doit être un pseudo ou\n"
"un canal enregistré."
msgid ""
@@ -6080,8 +6066,8 @@ msgid ""
"has been read."
msgstr ""
"Envoie un mémo dont le teste est texte au pseudo ou canal\n"
-"indiqué. En envoyant à un pseudo, le destinataire recevra une notice l'informant\n"
-"qu'il ou elle a reçu un nouveau mémo. Le destinataire doit être un pseudo ou\n"
+"indiqué. En envoyant à un pseudo, le/la destinataire recevra une notice l'informant\n"
+"qu'iel a reçu un nouveau mémo. Le/la destinataire doit être un pseudo ou\n"
"un canal enregistré.\n"
"Une fois le mémo lu, un accusé de réception vous est automatiquement\n"
"envoyé afin de vous prévenir que le mémo a été lu."
@@ -6111,6 +6097,10 @@ msgid "Server"
msgstr "Serveur"
#, c-format
+msgid "Server %s is not linked to the network."
+msgstr "Le serveur %s n'est pas connecté au réseau."
+
+#, c-format
msgid "Server %s added to zone %s."
msgstr "Serveur %s ajouté à la zone %s."
@@ -6128,7 +6118,7 @@ msgstr "Le serveur %s n'a pas d'adresse IP configurée."
#, c-format
msgid "Server %s is already in zone %s."
-msgstr "Le serveur %s est déjà dans la zone %s "
+msgstr "Le serveur %s est déjà dans la zone %s."
#, c-format
msgid "Server %s is already pooled."
@@ -6169,52 +6159,52 @@ msgid "Service's hold on %s has been released."
msgstr "La tutelle des Services sur %s a été enlevée."
msgid "Services Operator commands"
-msgstr "Commandes pour Opérateur des Services"
+msgstr "Commandes pour Opérateurice des Services"
msgid "Services are in DefCon mode, please try again later."
-msgstr "Les Services sont en mode DEFCON, veuillez réessayer ultérieurement."
-
-msgid "Services are in read-only mode!"
-msgstr "Les Services sont en mode lecture-seule !"
+msgstr "Les services sont en mode DEFCON, veuillez réessayer ultérieurement."
#, c-format
msgid "Services are now at DEFCON %d."
-msgstr "Les Services sont maintenant en alerte DEFCON %d."
+msgstr "Les services sont maintenant en alerte DEFCON %d."
#, c-format
msgid "Services are now in debug mode (level %d)."
-msgstr "Les Services sont maintenant en mode debug (niveau %d)."
+msgstr "Les services sont maintenant en mode debug (niveau %d)."
msgid "Services are now in debug mode."
-msgstr "Les Services sont maintenant en mode debug."
+msgstr "Les services sont maintenant en mode debug."
msgid "Services are now in expire mode."
-msgstr "Les Services sont maintenant en mode expiration."
+msgstr "Les services sont maintenant en mode expiration."
msgid "Services are now in no expire mode."
-msgstr "Les Services sont maintenant en mode sans expiration."
+msgstr "Les services sont maintenant en mode sans expiration."
msgid "Services are now in non-debug mode."
-msgstr "Les Services sont maintenant en mode normal (non debug)."
+msgstr "Les services sont maintenant en mode normal (non debug)."
msgid "Services are now in read-only mode."
-msgstr "Les Services sont maintenant en mode lecture-seule."
+msgstr "Les services sont maintenant en mode lecture-seule."
msgid "Services are now in read-write mode."
-msgstr "Les Services sont maintenant en mode lecture-écriture."
+msgstr "Les services sont maintenant en mode lecture-écriture."
+
+msgid "Services are temporarily in read-only mode."
+msgstr "Les services sont temporairement en mode lecture-seule."
msgid "Services have been configured to not send mail."
-msgstr "Les Services ont été configurés pour ne pas envoyer de mail."
+msgstr "Les services ont été configurés pour ne pas envoyer de mail."
msgid "Services ignore list:"
msgstr "Liste d'ignore des services :"
msgid "Services is unable to change modes. Are your servers' U:lines configured correctly?"
-msgstr "Les Services ne peuvent changer les modes. Les U:lines de vos serveurs sont-elles configurées correctement ?"
+msgstr "Les services ne peuvent changer les modes. Les U:lines de vos serveurs sont-elles configurées correctement ?"
#, c-format
msgid "Services up %s."
-msgstr "Services actifs depuis %s"
+msgstr "Services actifs depuis %s."
#, c-format
msgid "Services will from now on set status modes on %s in channels."
@@ -6222,7 +6212,7 @@ msgstr "Les services définiront désormais des modes de statuts pour %s sur les
#, c-format
msgid "Services will no longer automatically give modes to users in %s."
-msgstr "Les services n'appliqueront plus automatiquement de modes utilisateurs sur %s."
+msgstr "Les services n'appliqueront plus automatiquement de modes utilisateurices sur %s."
#, c-format
msgid "Services will no longer set status modes on %s in channels."
@@ -6230,7 +6220,7 @@ msgstr "Les services ne définiront plus des modes de statuts pour %s sur les
#, c-format
msgid "Services will now automatically give modes to users in %s."
-msgstr "Les services appliqueront automatiquement des modes utilisateurs sur %s."
+msgstr "Les services appliqueront automatiquement des modes utilisateurices sur %s."
#, c-format
msgid "Services will now reply to %s with messages."
@@ -6241,7 +6231,7 @@ msgid "Services will now reply to %s with notices."
msgstr "Les services répondront à %s par des notices."
msgid "Services' configuration has been reloaded."
-msgstr "Le fichier de configuration des Services a été rechargé."
+msgstr "Le fichier de configuration des services a été rechargé."
msgid "Session"
msgstr "Session"
@@ -6254,8 +6244,8 @@ msgid "Session limiting is disabled."
msgstr "La limitation de sessions est désactivée."
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Sessions : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Sessions : %zu entrées, %zu paniers, plus longue chaîne : %zu"
msgid "Set SET-options on another nickname"
msgstr "Configure des options sur d'autres pseudos"
@@ -6263,35 +6253,35 @@ msgstr "Configure des options sur d'autres pseudos"
msgid "Set channel options and information"
msgstr "Configure les options et informations du canal"
-msgid "Set how Services make bans on the channel"
-msgstr "Définit comment les Services mettent les bans sur le canal"
+msgid "Set how services make bans on the channel"
+msgstr "Définit comment les services mettent les bans sur le canal"
+
+msgid "Set nickname options and information"
+msgstr "Configure les options et informations du pseudo"
msgid "Set options related to memos"
msgstr "Définit des options relatives aux mémos"
-msgid "Set options, including kill protection"
-msgstr "Configure les options, protection comprise"
-
msgid "Set the channel as permanent"
msgstr "Définit le canal comme permanent"
msgid "Set the channel description"
msgstr "Définit la description du canal"
-msgid "Set the display of your group in Services"
+msgid "Set the display of your group in services"
msgstr "Change l'affichage de votre groupe dans les services"
msgid "Set the founder of a channel"
-msgstr "Définit le fondateur d'un canal"
+msgstr "Définit le/la fondateurice d'un canal"
-msgid "Set the language Services will use when messaging you"
-msgstr "Change la langue dans laquelle les Services vous envoient leurs messages"
+msgid "Set the language services will use when messaging you"
+msgstr "Change la langue dans laquelle les services vous envoient leurs messages"
msgid "Set the nickname password"
msgstr "Change le mot de passe du pseudo donné"
msgid "Set the successor for a channel"
-msgstr "Définit le successeur d'un canal"
+msgstr "Définit le/la successeur(e) d'un canal"
msgid "Set the vhost for all nicks in a group"
msgstr "Configure le vhost pour tous les pseudos d'un groupe"
@@ -6299,8 +6289,8 @@ msgstr "Configure le vhost pour tous les pseudos d'un groupe"
msgid "Set the vhost of another user"
msgstr "Configure le vhost d'un autre pseudo"
-msgid "Set various global Services options"
-msgstr "Configure des options globales des Services"
+msgid "Set various global services options"
+msgstr "Configure des options globales des services"
msgid "Set your nickname password"
msgstr "Change le mot de passe de votre pseudo"
@@ -6317,11 +6307,11 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les AMSG.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui envoient le même message à plusieurs\n"
+"utilisateurices qui envoient le même message à plusieurs\n"
"canaux où se trouvent des bots de %s.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
#, c-format
@@ -6330,7 +6320,7 @@ msgid ""
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
+"BADWORDS command. Type %s HELP BADWORDS for\n"
"more information.\n"
" \n"
"ttb is the number of times a user can be kicked\n"
@@ -6339,14 +6329,14 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les mots interdits.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui disent certains mots interdits \n"
+"utilisateurices qui disent certains mots interdits \n"
"sur le canal.\n"
"Vous pouvez définir les mots interdits pour votre\n"
"canal en utilisant la commande BADWORDS. Tapez\n"
-"%s%s HELP BADWORDS pour plus d'informations.\n"
+"%s HELP BADWORDS pour plus d'informations.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6380,10 +6370,10 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les caractères gras.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui utilisent des caractères gras.\n"
+"utilisateurices qui utilisent des caractères gras.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
#, c-format
@@ -6402,15 +6392,15 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les majuscules.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui parlent en MAJUSCULES.\n"
+"utilisateurices qui parlent en MAJUSCULES.\n"
"Le bot ne kicke que si il y a au moins min majuscules\n"
"et qu'elles constituent au moins pourcentage%% des\n"
"caractères de la ligne de texte. (Si elles ne sont pas\n"
"précisées, les valeurs par défaut sont 10 caractères et\n"
"25%%).\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6423,10 +6413,10 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les couleurs.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui utilisent des couleurs.\n"
+"utilisateurices qui utilisent des couleurs.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6448,13 +6438,13 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour le flood.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui floodent le canal, en envoyant\n"
+"utilisateurices qui floodent le canal, en envoyant\n"
"au moins ln lignes en secs secondes.\n"
"(Si elles ne sont pas précisées, les valeurs par défaut\n"
"sont 6 lignes en 10 secondes).\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6467,10 +6457,10 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour l'italique.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui utilisent des caractères italiques.\n"
+"utilisateurices qui utilisent des caractères italiques.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6485,11 +6475,11 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les répétitions.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui répètent le même message num fois.\n"
+"utilisateurices qui répètent le même message num fois.\n"
"(Si elle n'est pas précisée, la valeur par défaut est\n"
"3 fois).\n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6502,10 +6492,10 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les caractères inversés.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui utilisent des caractères inversés.\n"
+"utilisateurices qui utilisent des caractères inversés.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
@@ -6518,15 +6508,15 @@ msgid ""
msgstr ""
"Active ou désactive le kicker pour les caractères soulignés.\n"
"Lorsque cette option est active, le bot kickera les\n"
-"utilisateurs qui utilisent des caractères soulignés.\n"
+"utilisateurices qui utilisent des caractères soulignés.\n"
" \n"
-"ttb est le nombre de fois qu'un utilisateur peut\n"
-"se faire kicker avant d'être banni. N'indiquez pas ttb\n"
+"ttb est le nombre de fois qu'un(e) utilisateurice peut\n"
+"se faire kicker avant d'être banni(e). N'indiquez pas ttb\n"
"pour désactiver les bans."
msgid ""
"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
+"of the given nick. If your IRCD supports vidents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
@@ -6541,17 +6531,17 @@ msgstr ""
msgid ""
"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
+"hostmask. If your IRCD supports vidents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."
msgstr ""
"Configure le vhost du pseudo indiqué.\n"
-"Si le serveur IRC supporte la modification de l'ident, alors\n"
+"Si le serveur IRC supporte les vidents, alors\n"
"utiliser SET <pseudo> <ident>@<hostmask> modifiera aussi\n"
"l'ident en même temps que le vhost."
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -6559,7 +6549,7 @@ msgid ""
" SUPERADMIN Activate or deactivate super admin mode\n"
" LIST List the options"
msgstr ""
-"Contrôle différentes options globales des Services. \n"
+"Contrôle différentes options globales des services. \n"
"Les noms des options actuelles sont :\n"
" \n"
" READONLY Active ou désactive le mode lecture-seule.\n"
@@ -6577,17 +6567,17 @@ msgid ""
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
"Définit plusieurs options des mémos. option peut être :\n"
" \n"
-" NOTIFY Définit si vous serez notifié de vos nouveaux\n"
+" NOTIFY Définit si vous serez notifié(e) de vos nouveaux\n"
" mémos (seulement pour les pseudos)\n"
" LIMIT Définit le nombre de mémos maximum que \n"
" vous pouvez recevoir\n"
" \n"
-"Tapez %s%s HELP %s option pour plus \n"
+"Tapez %s HELP %s option pour plus \n"
"d'informations sur une option spécifique."
msgid "Sets various nickname options. option can be one of:"
@@ -6603,6 +6593,9 @@ msgstr ""
"Définit si le canal donné expirera. Mettre ceci sur ON\n"
"empêche le canal d'expirer."
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr "Définit si le pseudo donné peut être ajouté à une liste d'accès de canal."
+
#, c-format
msgid ""
"Sets whether the given nickname will be given its status modes\n"
@@ -6625,6 +6618,9 @@ msgstr ""
"Configurez ce paramètre sur ON pour que le \n"
"pseudo n'expire pas."
+msgid "Sets whether you can be added to a channel access list."
+msgstr "Définit si vous pouvez être ajouté(e) à une liste d'accès de canal."
+
#, c-format
msgid ""
"Sets whether you will be given your channel status modes automatically.\n"
@@ -6640,9 +6636,9 @@ msgstr ""
"pas être appliqués automatiquement."
#, c-format
-msgid "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
+msgid "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
msgstr ""
-"L'option %s est inconnue. Tapez %s%s HELP LEVELS pour une \n"
+"L'option %s est inconnue. Tapez %s HELP LEVELS pour une \n"
"liste d'options valides."
msgid "Setting for DEBUG must be ON, OFF, or a positive number."
@@ -6658,14 +6654,14 @@ msgid "Setting for super admin must be ON or OFF."
msgstr "La valeur pour SUPERADMIN doit être ON ou OFF."
msgid "Should services automatically give status to users"
-msgstr "Les services doivent-ils donner automatiquement les modes de statut ?"
+msgstr "Les services doivent-ils donner automatiquement les modes de statut"
-msgid "Show status of Services and network"
-msgstr "Affiche le statut des Services et du réseau"
+msgid "Show status of services and network"
+msgstr "Affiche le statut des services et du réseau"
#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr "%d/%d correspondances affichées pour %s."
+msgid "Showed %zu/%zu matches for %s."
+msgstr "%zu/%zu correspondances affichées pour %s."
msgid "Sign kicks that are done with the KICK command"
msgstr "Signe les kicks générés par la commande KICK"
@@ -6680,7 +6676,7 @@ msgid ""
"level of the user that is using the command."
msgstr ""
"Les kicks seront maintenant signés sur %s, en fonction du\n"
-"niveau d'accès de celui qui utilise la commande."
+"niveau d'accès de cellui qui utilise la commande."
#, c-format
msgid "Signed kick option for %s is now on."
@@ -6694,71 +6690,12 @@ msgid "Sorry, %s currently has too many memos and cannot receive more."
msgstr "Désolé, %s a trop de mémos et ne peut en recevoir plus."
#, c-format
-msgid "Sorry, I have not seen %s."
-msgstr "Désolé, je n'ai pas vu %s."
-
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr ""
-"Désolé, la modification de la liste des mots interdits\n"
-"est temporairement désactivée."
-
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr "Désolé, l'assignation du bot est temporairement désactivée."
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "Désolé, la modification des bots est temporairement désactivée."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr ""
-"Désolé, la configuration des options du bot est \n"
-"temporairement désactivée."
-
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr ""
-"Désolé, la configuration des options du bot est \n"
-"temporairement désactivée."
-
-#, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
-msgstr "Désolé, la modification des listes des %s des canaux est temporairement désactivée."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr "Désolé, la modification des listes d'accès des canaux est temporairement désactivée."
-
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr ""
-"Désolé, la modification de la liste de kicks automatiques du canal \n"
-"est temporairement désactivée."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr "Désolé, l'effacement de canaux est temporairement désactivé."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Désolé, l'enregistrement de canaux est temporairement désactivé."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
-msgstr ""
-"Désolé, la configuration des kickers est temporairement\n"
-"désactivée."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr "Désolé, la configuration des options est temporairement désactivée."
-
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr "Désolé, l'envoi de mémo est temporairement désactivé."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Désolé, l'effacement des pseudos est temporairement désactivé."
-
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Désolé, le regroupement de pseudos est temporairement désactivé."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Désolé, l'enregistrement de pseudos est temporairement désactivé."
+msgid "Sorry, %s is temporarily unavailable."
+msgstr "Désolé, %s est temporairement désactivé."
#, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
-msgstr "Désolé, vous ne pouvez avoir que %d entrées sur la liste d'accès."
+msgid "Sorry, I have not seen %s."
+msgstr "Désolé, je n'ai pas vu %s."
#, c-format
msgid "Sorry, the maximum of %d auto join entries has been reached."
@@ -6804,7 +6741,7 @@ msgid "State"
msgstr "État"
msgid "Statistics and maintenance for seen data"
-msgstr "Statistiques et maintenance pour les données 'seen'."
+msgstr "Statistiques et maintenance pour les données 'seen'"
msgid "Statistics reset."
msgstr "Statistiques réinitialisées."
@@ -6819,21 +6756,21 @@ msgid "Stop repeating yourself!"
msgstr "Arrêtez de vous répéter !"
msgid "Stricter control of channel founder status"
-msgstr "Contrôle plus strict du statut de fondateur du canal"
+msgstr "Contrôle plus strict du statut de fondateurice du canal"
msgid "Stricter control of chanop status"
-msgstr "Contrôle plus strict du statut d'opérateur du canal"
+msgstr "Contrôle plus strict du statut d'opérateurice du canal"
msgid "Successor"
-msgstr "Successeur"
+msgstr "Successeur(e)"
#, c-format
msgid "Successor for %s changed to %s."
-msgstr "Le successeur de %s est désormais %s."
+msgstr "Le successeur(e) de %s est désormais %s."
#, c-format
msgid "Successor for %s unset."
-msgstr "Il n'y a plus de successeur sur %s."
+msgstr "Il n'y a plus de successeur(e) sur %s."
msgid "Super admin can not be set because it is not enabled in the configuration."
msgstr "Le mode super-admin ne peut pas être utilisé, parce qu'il n'est pas activé dans la configuration."
@@ -6868,13 +6805,13 @@ msgid "Suspension expires"
msgstr "Expiration"
msgid "Sync users channel modes"
-msgstr "Synchronise les modes utilisateurs d'un canal"
+msgstr "Synchronise les modes utilisateurices d'un canal"
msgid ""
"Syncs all modes set on users on the channel with the modes\n"
"they should have based on their access."
msgstr ""
-"Synchronise tous les modes appliqués sur les utilisateurs du canal avec les modes\n"
+"Synchronise tous les modes appliqués sur les utilisateurices du canal avec les modes\n"
"qu'ils devraient avoir en se basant sur leurs accès."
msgid "Syncs the vhost for all nicks in a group"
@@ -6911,7 +6848,7 @@ msgstr ""
" \n"
"Avec un paramètre, liste tous les pseudos qui sont dans\n"
"le groupe du pseudo donné.\n"
-"Le paramètre est restreint aux Opérateurs des Services."
+"Le paramètre est restreint aux Opérateurices des Services."
msgid ""
"Syntax: DEBUG {ON | OFF}\n"
@@ -6966,23 +6903,23 @@ msgid ""
"remove their limit, may not set a limit above %d, and may\n"
"not set a hard limit."
msgstr ""
-"Syntaxe : SET LIMIT [utilisateur | canal] {limite | NONE} [HARD]\n"
+"Syntaxe : SET LIMIT [utilisateurice | canal] {limite | NONE} [HARD]\n"
" \n"
-"Définit le nombre maximum de mémos qu'un utilisateur ou\n"
+"Définit le nombre maximum de mémos qu'un(e) utilisateurice ou\n"
"un canal est autorisé à stocker. Définir la limite à 0\n"
-"empêche l'utilisateur de recevoir des mémos, définir ceci\n"
-"à NONE permet à l'utilisateur de recevoir et garder\n"
+"empêche l'utilisateurice de recevoir des mémos, définir ceci\n"
+"à NONE permet à l'utilisateurice de recevoir et garder\n"
"autant de mémos qu'il souhaite. Si vous ne donnez pas de\n"
"pseudo ou de canal, vous changez votre propre limite.\n"
" \n"
-"Ajouter HARD empêche l'utilisateur de changer cette limite.\n"
+"Ajouter HARD empêche l'utilisateurice de changer cette limite.\n"
"Ne pas ajouter HARD a l'effet inverse, permettant à \n"
-"l'utilisateur de changer cette limite (même si une limite\n"
+"l'utilisateurice de changer cette limite (même si une limite\n"
"antérieure a été définie avec HARD).\n"
" \n"
"Cette utilisation de la commande SET LIMIT est réservée aux\n"
-"Opérateurs des Services. Les autres utilisateurs peuvent uniquement\n"
-"entrer une limite pour eux-mêmes ou un canal sur lequel ils ont\n"
+"Opérateurices des Services. Les autres utilisateurices peuvent uniquement\n"
+"entrer une limite pour elleux-mêmes ou un canal sur lequel ils ont\n"
"les privilèges requis, ne peuvent indiquer une limite supérieur à %d, et\n"
"ne peuvent définir de limite stricte."
@@ -7038,17 +6975,17 @@ msgstr ""
" \n"
"Définit à quel moment vous serez notifié de vos nouveaux mémos:\n"
" \n"
-" ON Vous serez notifié lorsque vous vous connectez,\n"
+" ON Vous serez notifié(e) lorsque vous vous connectez,\n"
" lorsque vous enlevez /AWAY, et quand les mémos vous\n"
" sont envoyés.\n"
-" LOGON Vous serez uniquement notifié des mémos lorsque\n"
+" LOGON Vous serez uniquement notifié(e) des mémos lorsque\n"
" vous vous connectez ou quand vous enlevez\n"
" /AWAY.\n"
-" NEW Vous serez uniquement notifié des mémos \n"
+" NEW Vous serez uniquement notifié(e) des mémos \n"
" lorsqu'ils vous sont envoyés.\n"
" MAIL Vous serez prévenu pour les mémos par email,\n"
" en plus des autres paramètres.\n"
-" NOMAIL Vous ne serez pas prévenu par email.\n"
+" NOMAIL Vous ne serez pas prévenu(e) par email.\n"
" OFF Vous ne recevrez aucune notification.\n"
" \n"
"ON est la combinaison de LOGON et NEW."
@@ -7057,13 +6994,13 @@ msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"users will not be allowed to modify any services data,\n"
+"including channel access lists, etc. Server operators\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
@@ -7072,12 +7009,12 @@ msgstr ""
"Syntaxe : SET READONLY {ON | OFF}\n"
" \n"
"Active ou désactive le mode lecture seule. Dans le mode \n"
-"lecture-seule, les utilisateurs normaux ne seront pas \n"
-"autorisés à modifier les données des Services, notamment\n"
+"lecture-seule, les utilisateurices sans privilège ne seront pas \n"
+"autorisé(e)s à modifier les données des services, notamment\n"
"les listes d'accès des canaux et pseudos, etc.\n"
-"Les Opérateurs avec suffisamment de droits sur les Services\n"
+"Les Opérateurices avec suffisamment de droits sur les services\n"
"pourront modifier les listes d'AKILL, de SQLINE, de SNLINE\n"
-"et d'utilisateurs ignorés par les Services, ainsi que supprimer,\n"
+"et d'utilisateurices ignorés par les services, ainsi que supprimer,\n"
"suspendre ou interdire des pseudos et des canaux, et gérer les\n"
"news de connexion et d'oper et les DNS. Mais ces changements\n"
"ne seront pas sauvegardés, à moins que le mode lecture-seule ne\n"
@@ -7099,7 +7036,7 @@ msgstr ""
"Syntaxe : SET SUPERADMIN {ON | OFF}\n"
" \n"
"Vous permet d'avoir des privilèges supplémentaires comme le droit\n"
-"d'être reconnu \"fondateur\" de tous les canaux, etc ...\n"
+"d'être reconnu \"fondateurice\" de tous les canaux, etc ...\n"
" \n"
"Cette option n'est pas persistante et ne devrait être utilisée que lorsque\n"
"vraiment nécessaire, puis remise à OFF quand elle n'est plus nécessaire."
@@ -7129,7 +7066,7 @@ msgstr ""
"Demande à %s de vous inviter vous ou un pseudo indiqué\n"
"sur le canal donné. \n"
" \n"
-"Par défaut, limité aux AOPs ou à ceux ayant un niveau \n"
+"Par défaut, limité aux AOPs ou à celleux ayant un niveau \n"
"d'accès de 5 ou plus sur le canal."
#, c-format
@@ -7143,15 +7080,15 @@ msgid ""
"on the channel."
msgstr ""
"Demande à %s de supprimer les bans vous empêchant ou empêchant\n"
-"l'utilisateur désigné de rejoindre le canal fourni. Si aucun canal n'est fourni,\n"
+"l'utilisateurice désigné(e) de rejoindre le canal fourni. Si aucun canal n'est fourni,\n"
"tous les bans vous affectant sur les canaux auxquels vous avez accès seront supprimés.\n"
" \n"
-"Par défaut, limité aux AOPs, ou ceux qui ont un level supérieur ou égal à 5\n"
+"Par défaut, limité aux AOPs, ou celleux qui ont un level supérieur ou égal à 5\n"
"sur le canal."
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7159,8 +7096,8 @@ msgid ""
"text \"Juped by <nick>\", showing the nickname of the\n"
"person who jupitered the server."
msgstr ""
-"Demande aux Services de \"jupiter\" un serveur -- c'est à dire,\n"
-"créer un faux serveur connecté aux Services, ce qui empêche\n"
+"Demande aux services de \"jupiter\" un serveur -- c'est à dire,\n"
+"créer un faux serveur connecté aux services, ce qui empêche\n"
"le vrai serveur ayant ce nom de se connecter. Le jupe peut\n"
"être enlevé en utilisant un SQUIT normal. Si une raison\n"
"est donnée, elle est placée dans le champ d'information du\n"
@@ -7169,13 +7106,13 @@ msgstr ""
"de la personne qui a \"jupiter\" le serveur."
msgid "Tells you about the last time a user was seen"
-msgstr "Vous informe à propos de la dernière fois qu'un utilisateur a été vu."
+msgstr "Vous informe à propos de la dernière fois qu'un(e) utilisateurice a été vu(e)"
-msgid "Terminate Services WITHOUT saving"
-msgstr "Arrête les Services SANS sauvegarde"
+msgid "Terminate services WITHOUT saving"
+msgstr "Arrête les services SANS sauvegarde"
msgid "Terminate services with save"
-msgstr "Arrête les Services avec sauvegarde"
+msgstr "Arrête les services avec sauvegarde"
msgid "Text"
msgstr "Texte"
@@ -7194,7 +7131,7 @@ msgstr ""
"son niveau d'accès est changé en celui qui est spécifié dans la commande.\n"
"Le niveau spécifié doit être une valeur numérique représentant le level\n"
"ou le nom du privilège (ex. AUTOOP).\n"
-"Lorsqu'un utilisateur rejoint le canal, l'accès qu'il reçoit est le plus grand\n"
+"Lorsqu'un(e) utilisateurice rejoint le canal, l'accès qu'il reçoit est le plus grand\n"
"présent dans la liste d'accès."
msgid ""
@@ -7228,7 +7165,7 @@ msgstr ""
"La commande ACCESS LIST affiche la liste d'accès. Si\n"
"un masque avec joker est donné, seules les entrées\n"
"correspondantes sont affichées. Si une liste de numéros d'entrées\n"
-"est donnée, alors ceux-ci seront affichés ; par exemple :\n"
+"est donnée, alors celles-ci seront affichés ; par exemple :\n"
" ACCESS #channel LIST 2-5,7-9\n"
" Liste les entrées d'accès numérotées entre 2 et 5 puis entre\n"
" 7 et 9.\n"
@@ -7240,7 +7177,7 @@ msgstr ""
"d'accès."
msgid "The CLEAR command clears the channel access list. This requires channel founder access."
-msgstr "La commande CLEAR vide la liste d'accès du canal, ce qui requiert d'être fondateur du canal."
+msgstr "La commande CLEAR vide la liste d'accès du canal, ce qui requiert d'être fondateurice du canal."
#, c-format
msgid ""
@@ -7294,7 +7231,7 @@ msgid ""
"the channel."
msgstr ""
"La commande ENTRYMSG ADD ajoute le message donné\n"
-"à la liste des messages à montrer aux utilisateurs lorsqu'ils joignent\n"
+"à la liste des messages à montrer aux utilisateurices lorsqu'ils joignent\n"
"le canal."
msgid ""
@@ -7303,7 +7240,7 @@ msgid ""
"the channel, effectively disabling entry messages."
msgstr ""
"La commande ENTRYMSG CLEAR efface toutes les entrées\n"
-"de la liste des messages à montrer lorsque les utilisateurs joignent le canal,\n"
+"de la liste des messages à montrer lorsque les utilisateurices joignent le canal,\n"
"en désactivant ces messages."
msgid ""
@@ -7313,7 +7250,7 @@ msgid ""
"which you can get by listing the messages as explained below."
msgstr ""
"La commande ENTRYMSG DEL supprime le message donné de la liste\n"
-"des messages à montrer aux utilisateurs lorsqu'ils rejoignent le canal.\n"
+"des messages à montrer aux utilisateurices lorsqu'ils rejoignent le canal.\n"
"Vous pouvez supprimer le message en spécifiant son numéro, que vous pouvez\n"
"obtenir en listant les messages, comme c'est expliqué ci-dessous."
@@ -7322,7 +7259,7 @@ msgid ""
"shown to users when they join the channel."
msgstr ""
"La commande ENTRYMSG LIST affiche la liste des messages qui seront\n"
-"montrés aux utilisateurs lorsqu'ils joignent le canal."
+"montrés aux utilisateurices lorsqu'ils joignent le canal."
msgid "The IMMED option is not available on this network."
msgstr "L'option IMMED n'est pas disponible sur ce réseau."
@@ -7354,12 +7291,12 @@ msgstr ""
"Avec cette commande, vous pouvez définir les niveaux d'accès\n"
"requis pour la majorité des fonctions de %s. (Les commandes\n"
"SET FOUNDER, ainsi que cette commande,\n"
-"sont toujours réservées au fondateur du canal.)\n"
+"sont toujours réservées au fondateurice du canal.)\n"
" \n"
"LEVELS SET permet au niveau d'accès pour une fonction ou un\n"
"groupe de fonctions d'être changé. LEVELS DISABLE (ou DIS\n"
"en abrégé) désactive une fonction automatique ou empêche l'accès\n"
-"à une fonction par quiconque incluant le fondateur du canal (même si celui-ci\n"
+"à une fonction par quiconque incluant le/la fondateurice du canal (même si cellui-ci\n"
"peut toujours le ré-activer)\n"
" \n"
"LEVELS LIST montre les niveaux actuels pour chaque fonction\n"
@@ -7401,15 +7338,12 @@ msgstr "La commande STATS affiche des statistiques à propos des pseudos stock
msgid ""
"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
+"for your nick immediately. You may also wish to SET HIDE it\n"
"after registering if it isn't the default setting already."
msgstr ""
-"Le paramètre email est optionnel et rajoute cet email\n"
-"à votre pseudo immédiatement.\n"
-"Votre vie privée est respectée, cet email ne sera communiqué à\n"
-"aucune tierce personne. Si vous le souhaitez, vous pouvez utiliser SET HIDE\n"
+"Le paramètre email est optionnel et définit l'adresse email\n"
+"de votre pseudo immédiatement.\n"
+"Si vous le souhaitez, vous pouvez utiliser SET HIDE\n"
"après votre enregistrement si ce n'est pas déjà la configuration par défaut."
#, c-format
@@ -7434,7 +7368,7 @@ msgid ""
" Would message any channel operators whenever someone used the\n"
" ACCESS command on ChanServ on the channel."
msgstr ""
-"La commande %s permet aux utilisateurs de configurer les paramètres\n"
+"La commande %s permet aux utilisateurices de configurer les paramètres\n"
"de log pour leur canal. Si aucun paramètre n'est donné, cette commande\n"
"listera toutes les méthodes actuelles de log en place pour ce canal.\n"
" \n"
@@ -7452,7 +7386,7 @@ msgstr ""
" \n"
"Exemple :\n"
" %s #anope chanserv/access MESSAGE @\n"
-" Envoi un message à tous les opérateurs à chaque fois que quelqu'un\n"
+" Envoi un message à toustes les opérateurices à chaque fois que quelqu'un\n"
" utilise la commande ACCESS de ChanServ sur le canal."
#, c-format
@@ -7468,15 +7402,7 @@ msgstr "La liste d'AKILL a été vidée."
#, c-format
msgid "The Defcon level is now at: %d"
-msgstr "Le niveau d'alerte DEFCON est maintenant : %d."
-
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr "L'adresse email de %s sera désormais cachée dans la commande INFO de %s."
-
-#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr "L'adresse email de %s sera désormais affichée dans la commande INFO de %s."
+msgstr "Le niveau d'alerte DEFCON est maintenant : %d"
msgid "The available flags are:"
msgstr "Les flags disponibles sont :"
@@ -7492,11 +7418,19 @@ msgstr ""
#, c-format
msgid "The email address %s has reached its usage limit of %d users."
-msgstr "L'adresse email %s a atteint sa limite d'utilisation de %d utilisateurs."
+msgstr "L'adresse email %s a atteint sa limite d'utilisation de %d utilisateurices."
#, c-format
msgid "The email address %s has reached its usage limit of 1 user."
-msgstr "L'adresse email %s a atteint sa limite d'utilisation d'un utilisateur."
+msgstr "L'adresse email %s a atteint sa limite d'utilisation d'un(e) utilisateurice."
+
+#, c-format
+msgid "The email address of %s will now be hidden from %s INFO displays."
+msgstr "L'adresse email de %s sera désormais cachée dans la commande %s INFO."
+
+#, c-format
+msgid "The email address of %s will now be shown in %s INFO displays."
+msgstr "L'adresse email de %s sera désormais affichée dans la commande %s INFO."
#, c-format
msgid "The entry message list for %s is full."
@@ -7597,19 +7531,19 @@ msgid ""
"The user with your nick has been removed. Use this command again\n"
"to release services's hold on your nick."
msgstr ""
-"L'utilisateur utilisant votre pseudo a été déconnecté. Utilisez cette commande\n"
+"L'utilisateurice utilisant votre pseudo a été déconnecté. Utilisez cette commande\n"
"à nouveau pour relâcher la détention de votre pseudo par les services."
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "Il y a %d mémos sur le canal %s."
+msgid "There are %zu memos on channel %s."
+msgstr "Il y a %zu mémos sur le canal %s."
msgid ""
"There are no bots available at this time.\n"
"Ask a Services Operator to create one!"
msgstr ""
"Il n'y a aucun bot disponible actuellement.\n"
-"Demandez à un Opérateur des Services d'en créer un !"
+"Demandez à un(e) Opérateurice des Services d'en créer un !"
msgid "There are no configured servers."
msgstr "Il n'y a pas de serveur configuré."
@@ -7626,16 +7560,16 @@ msgid "There currently are no logging configurations for %s."
msgstr "Il n'y a actuellement pas de configuration de logging pour %s."
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "Il y a %d mémo sur le canal %s."
+msgid "There is %zu memo on channel %s."
+msgstr "Il y a %zu mémo sur le canal %s."
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
+"Type %s READ %s %zu to read it."
msgstr ""
"Il y a un nouveau mémo sur le canal %s.\n"
-"Tapez %s%s READ %s %d pour le lire."
+"Tapez %s READ %s %zu pour le lire."
#, c-format
msgid "There is no bot assigned to %s anymore."
@@ -7691,7 +7625,7 @@ msgid ""
"The POOL and DEPOOL commands actually add and remove servers to their given zones."
msgstr ""
"Cette commande permet de gérer les zones DNS utilisées pour contrôler sur quels\n"
-"serveurs les utilisateurs se connectent. Si vous ne mettez aucun paramètre, la\n"
+"serveurs les utilisateurices se connectent. Si vous ne mettez aucun paramètre, la\n"
"commande affiche le statut actuel de la zone DNS.\n"
" \n"
"ADDZONE crée une nouvelle zone, par exemple us.yournetwork.tld. Vous pouvez\n"
@@ -7712,7 +7646,7 @@ msgid ""
"CURRENT nick to be the vhost for all nicks in the same\n"
"group."
msgstr ""
-"Permet aux utilisateurs d'appliquer le vhost de leur pseudo\n"
+"Permet aux utilisateurices d'appliquer le vhost de leur pseudo\n"
"actuellement utilisé à tous les pseudos de leur groupe de pseudos."
msgid ""
@@ -7824,7 +7758,7 @@ msgstr ""
"non enregistré puisqu'il sera automatiquement enregistré\n"
"lorsque vous utiliserez cette commande. Vous pouvez l'utiliser\n"
"avec un pseudo enregistré (pour changer votre groupe) uniquement\n"
-"si vos administrateurs l'autorisent. \n"
+"si vos administrateurices l'autorisent. \n"
"Vous ne pouvez être que dans un groupe à la fois. La fusion\n"
"de groupes n'est pas possible.\n"
" \n"
@@ -7838,8 +7772,8 @@ msgid ""
msgstr ""
"Cette commande gère votre liste d'auto join. Lorsque vous vous identifiez,\n"
"vous joindrez automatiquement les canaux de votre liste d'auto join.\n"
-"Les Opérateurs des Services peuvent fournir un pseudo pour modifier\n"
-"la liste d'auto join d'autres utilisateurs."
+"Les Opérateurices des Services peuvent fournir un pseudo pour modifier\n"
+"la liste d'auto join d'autres utilisateurices."
msgid "This command may not be used on this network because nickname ownership is disabled."
msgstr "Cette commande ne peut pas être utilisée sur ce réseau parce que la possession de pseudo est désactivée."
@@ -7851,7 +7785,7 @@ msgid "This command retrieves the vhost requests."
msgstr "Cette commande récupère la liste des demandes de vhost."
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -7863,7 +7797,7 @@ msgid ""
" Searches the last 21 days worth of logs for messages\n"
" containing Anope and lists the most recent 500 of them."
msgstr ""
-"Cette commande cherche dans les fichiers de log des Services des\n"
+"Cette commande cherche dans les fichiers de log des services des\n"
"messages qui correspondent au modèle donné. Les paramètres jour et limite\n"
"peuvent être utilisés pour indiquer parmi combien de jours de logs chercher\n"
"et combien de messages afficher. Par défaut, cette commande cherche dans\n"
@@ -7881,10 +7815,10 @@ msgid ""
"this command is limited to users who have the ability to modify\n"
"access entries on the channel."
msgstr ""
-"Cette commande vous indique quels utilisateurs ont accès sur un canal,\n"
+"Cette commande vous indique quels utilisateurices ont accès sur un canal,\n"
"et quelles entrées correspondent. De plus, cela vous indique les kicks\n"
"automatiques qui correspondent, s'il y en a. L'utilisation de cette commande\n"
-"est limitée aux utilisateurs qui ont la possibilité de modifier les accès du canal."
+"est limitée aux utilisateurices qui ont la possibilité de modifier les accès du canal."
msgid ""
"This command ungroups your nick, or if given, the specified nick,\n"
@@ -7906,14 +7840,6 @@ msgid "This command will resend you the registration confirmation email."
msgstr "Cette commande vous renverra l'email de confirmation d'enregistrement."
#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
-msgstr ""
-"Ce pseudo appartient à quelqu'un d'autre. Merci d'en choisir un autre.\n"
-"(Si c'est votre pseudo, tapez %s%s IDENTIFY mot-de-passe.)"
-
-#, c-format
msgid "This nickname has been forbidden: %s"
msgstr "Ce pseudo a été interdit : %s"
@@ -7938,20 +7864,20 @@ msgstr "Ce pseudo est suspendu."
#, c-format
msgid ""
"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
+"nick, type %s IDENTIFY password. Otherwise,\n"
"please choose a different nick."
msgstr ""
-"Le pseudo est enregistré et protégé. Si c'est votre pseudo,\n"
-"tapez %s%s IDENTIFY mot-de-passe.\n"
+"Ce pseudo est enregistré et protégé. Si c'est votre pseudo,\n"
+"tapez %s IDENTIFY mot-de-passe.\n"
"Dans le cas contraire, merci de choisir un pseudo différent."
#, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr "Pour supprimer, tapez : %s%s %s %d"
+msgid "To delete, type: %s %s %d"
+msgstr "Pour supprimer, tapez : %s %s %d"
#, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr "Pour supprimer, tapez : %s%s %s %s %d"
+msgid "To delete, type: %s %s %s %d"
+msgstr "Pour supprimer, tapez : %s %s %s %d"
msgid "To protect ops against bot kicks"
msgstr "Pour protéger les ops des kicks du bot"
@@ -8006,10 +7932,7 @@ msgid "Turn caps lock OFF!"
msgstr "Cessez d'utiliser tant de majuscules !"
msgid "Turn chanstats statistics on or off"
-msgstr "Active ou désactive les statistiques de ChanStats."
-
-msgid "Turn nickname security on or off"
-msgstr "Active ou désactive la sécurité du pseudo"
+msgstr "Active ou désactive les statistiques de ChanStats"
msgid "Turn protection on or off"
msgstr "Active ou désactive la protection"
@@ -8044,25 +7967,8 @@ msgstr ""
"tout de même avoir des informations en utilisant la commande\n"
"INFO)."
-#, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Active ou désactive la sécurité de %s pour votre pseudo.\n"
-"Si SECURE est actif, vous devrez obligatoirement\n"
-"entrer votre mot de passe pour être reconnu en tant que \n"
-"propriétaire du pseudo, que votre masque soit dans la liste d'accès\n"
-"ou non. Cependant, si vous êtes sur la liste d'accès, %s n'utilisera pas\n"
-"d'auto-kill quelque soit l'état de l'option KILL."
-
msgid "Turns chanstats channel statistics ON or OFF for this user."
-msgstr "Active ou désactive les statistiques de canal de ChanStats pour cet utilisateur."
+msgstr "Active ou désactive les statistiques de canal de ChanStats pour cet(te) utilisateurice."
msgid "Turns chanstats statistics ON or OFF."
msgstr "Active ou désactive les statistiques de ChanStats."
@@ -8083,16 +7989,16 @@ msgid ""
"network's administrators may have disabled this option."
msgstr ""
"Active ou désactive la protection automatique pour le pseudo donné.\n"
-"Avec la protection activée, si un autre utilisateur essaie de \n"
-"prendre son pseudo, il aura une minute pour changer de pseudo,\n"
+"Avec la protection activée, si un(e) autre utilisateurice essaie de \n"
+"prendre son pseudo, iel aura une minute pour changer de pseudo,\n"
"après quoi son pseudo sera changé de force par %s.\n"
" \n"
-"Si vous sélectionnez QUICK, l'utilisateur aura seulement 20\n"
+"Si vous sélectionnez QUICK, l'utilisateurice aura seulement 20\n"
"secondes pour changer de pseudo au lieu des 60 habituelles. Si\n"
-"vous sélectionnez IMMED, l'utilisateur verra son pseudo changé\n"
-"immédiatement sans être prévenu et sans avoir de chance\n"
+"vous sélectionnez IMMED, l'utilisateurice verra son pseudo changé\n"
+"immédiatement sans être prévenu(e) et sans avoir de chance\n"
"de changer son pseudo, n'utilisez cette option que si nécessaire.\n"
-"Les administrateurs de votre réseau peuvent avoir désactivé cette option."
+"Les administrateurices de votre réseau peuvent avoir désactivé cette option."
#, c-format
msgid ""
@@ -8110,68 +8016,62 @@ msgid ""
"network's administrators may have disabled this option."
msgstr ""
"Active ou désactive la protection automatique pour votre pseudo.\n"
-"Avec la protection activée, si un autre utilisateur essaie de prendre\n"
-"votre pseudo, il aura une minute pour changer de pseudo, après quoi\n"
+"Avec la protection activée, si un(e) autre utilisateurice essaie de prendre\n"
+"votre pseudo, iel aura une minute pour changer de pseudo, après quoi\n"
"son pseudo sera changé de force par %s.\n"
" \n"
-"Si vous sélectionnez QUICK, l'utilisateur aura seulement 20\n"
+"Si vous sélectionnez QUICK, l'utilisateurice aura seulement 20\n"
"secondes pour changer de pseudo au lieu des 60 habituelles. Si\n"
-"vous sélectionnez IMMED, l'utilisateur verra son pseudo changé\n"
-"immédiatement sans être prévenu et sans avoir de chance\n"
+"vous sélectionnez IMMED, l'utilisateurice verra son pseudo changé\n"
+"immédiatement sans être prévenu(e) et sans avoir de chance\n"
"de changer son pseudo, n'utilisez cette option que si nécessaire.\n"
-"Les administrateurs de votre réseau peuvent avoir désactivé cette option."
+"Les administrateurices de votre réseau peuvent avoir désactivé cette option."
msgid "Type"
msgstr "Type"
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
-"Tapez %s%s HELP %s option pour plus d'informations sur\n"
+"Tapez %s HELP %s option pour plus d'informations sur\n"
"une option particulière."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
"level SET."
msgstr ""
-"Tapez %s%s HELP %s option pour plus d'informations\n"
+"Tapez %s HELP %s option pour plus d'informations\n"
"sur une option particulière.\n"
" \n"
"Note : l'accès à cette commande est contrôlé par le niveau SET."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option. The options will be set on the given\n"
"nickname."
msgstr ""
-"Tapez %s%s HELP %s option pour plus d'informations\n"
+"Tapez %s HELP %s option pour plus d'informations\n"
"sur une option particulière. Les options seront définies pour le\n"
"pseudo indiqué."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information on a\n"
+"Type %s HELP %s option for more information on a\n"
"particular option."
msgstr ""
-"Tapez %s%s HELP %s option pour plus d'informations sur\n"
+"Tapez %s HELP %s option pour plus d'informations sur\n"
"une option particulière."
#, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
-msgstr ""
-"Tapez %s%s SET EMAIL email pour définir votre email.\n"
-"Votre vie privée est respectée, cet email ne sera pas divulguée\n"
-"à des tierces personnes."
+msgid "Type %s SET EMAIL email in order to set your email."
+msgstr "Tapez %s SET EMAIL email pour définir votre adresse email."
msgid "Un-Load a module"
msgstr "Décharge un module"
@@ -8212,15 +8112,23 @@ msgstr "Option SET inconnue."
#, c-format
msgid "Unknown STATS option: %s"
-msgstr "Option STATS inconnue : %s."
+msgstr "Option STATS inconnue : %s"
#, c-format
msgid "Unknown command %s."
msgstr "Commande %s inconnue."
#, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Commande %s inconnue. Tapez \"%s%s HELP\" pour obtenir de l'aide."
+msgid "Unknown command %s. \"%s HELP\" for help."
+msgstr "Commande %s inconnue. Tapez \"%s HELP\" pour obtenir de l'aide."
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s?"
+msgstr "Commande %s inconnue. Voulez-vous dire%s ?"
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
+msgstr "Commande %s inconnue. Voulez-vous dire%s ? Tapez \"%s HELP\" pour obtenir de l'aide."
#, c-format
msgid "Unknown mode character %c ignored."
@@ -8230,22 +8138,26 @@ msgstr "Mode %c ignoré car inconnu."
msgid "Unknown parameter: %s"
msgstr "Paramètre inconnu : %s"
+#, c-format
+msgid "Unknown passwords: %zu"
+msgstr "Mots de passe inconnus : %zu"
+
msgid "Unpooled"
-msgstr "Retiré de la pool."
+msgstr "Retiré de la pool"
msgid ""
"Unregisters the named channel. Can only be used by\n"
"the channel founder."
msgstr ""
"Efface le canal indiqué. Peut uniquement être utilisé par\n"
-"le fondateur du canal."
+"le fondateurice du canal."
msgid ""
"Unregisters the specified channel. Only Services Operators\n"
"can drop a channel of which they are not the founder of."
msgstr ""
-"Efface le canal indiqué. Seuls les Opérateurs des Services\n"
-"peuvent effacer un canal duquel ils ne sont pas le fondateur."
+"Efface le canal indiqué. Seuls les Opérateurices des Services\n"
+"peuvent effacer un canal duquel ils ne sont pas le/la fondateurice."
msgid "Unsuspend a given nick"
msgstr "Relâche un pseudo suspendu"
@@ -8263,7 +8175,7 @@ msgstr ""
"statut de canal est mis à jour sur tous les canaux sur lesquels vous vous trouvez."
msgid "Updates a selected nicks status on a channel"
-msgstr "Met à jour le statut des pseudos sur un canal."
+msgstr "Met à jour le statut des pseudos sur un canal"
msgid "Updates your current status, i.e. it checks for new memos"
msgstr "Met à jour votre statut, ex : vérification de nouveaux mémos"
@@ -8300,54 +8212,66 @@ msgid "Used to manage channels"
msgstr "Permet de gérer les canaux"
msgid "Used to manage the list of privileged users"
-msgstr "Permet de modifier la liste des utilisateurs privilégiés"
+msgstr "Permet de modifier la liste des utilisateurices privilégiés"
msgid "Used to modify the channel status of you or other users"
-msgstr "Permet de modifier votre statut sur le canal ou celui des autres utilisateurs"
+msgstr "Permet de modifier votre statut sur le canal ou celui des autres utilisateurices"
+
+#, c-format
+msgid "User %s isn't currently logged in to an account."
+msgstr "Le pseudo %s n'est pas utilisé actuellement."
msgid "User has been banned from the channel"
-msgstr "L'utilisateur a été banni du canal."
+msgstr "L'utilisateurice a été banni(e) du canal"
#, c-format
msgid "User limit for %s removed."
-msgstr "Limite d'utilisateurs pour %s supprimée."
+msgstr "Limite d'utilisateurices pour %s supprimée."
#, c-format
msgid "User limit for %s set to %d."
-msgstr "Limite d'utilisateurs pour %s fixée à %d utilisateurs."
+msgstr "Limite d'utilisateurices pour %s fixée à %d utilisateurices."
msgid "Users"
-msgstr "Utilisateurs"
+msgstr "Utilisateurices"
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Utilisateurs (pseudos) : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Utilisateurices (pseudos) : %lu entrées, %lu paniers, plus longue chaîne : %zu"
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Utilisateurs (uid) : %lu entrées, %lu paniers, plus longue chaîne : %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Utilisateurices (uid) : %lu entrées, %lu paniers, plus longue chaîne : %zu"
msgid "Users list:"
-msgstr "Liste des utilisateurs :"
+msgstr "Liste des utilisateurices :"
msgid "VHost"
msgstr "VHost"
#, c-format
+msgid "VHost for %s removed."
+msgstr "Le vhost de %s a été supprimé."
+
+#, c-format
msgid "VHost for %s set to %s."
msgstr "Le vhost pour %s fixé à %s."
#, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "Le vhost pour %s fixé à %s@%s."
+msgid "VHost for %s has been activated."
+msgstr "Le vhost de %s a été activé."
+
+#, c-format
+msgid "VHost for %s has been rejected."
+msgstr "Le vhost de %s a été rejeté."
#, c-format
msgid "VHost for group %s set to %s."
msgstr "Le vhost pour le groupe %s fixé à %s."
#, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "Le vhost pour le groupe %s fixé à %s@%s."
+msgid "VHosts for group %s have been removed."
+msgstr "Le vhost du groupe %s a été supprimé."
msgid "VIEW host"
msgstr "VIEW host"
@@ -8365,15 +8289,8 @@ msgstr "Valeur"
msgid "Value of %s:%s changed to %s"
msgstr "Valeur de %s:%s changée en %s"
-msgid "Vhost"
-msgstr "Vhost"
-
-#, c-format
-msgid "Vhost for %s removed."
-msgstr "Le vhost pour %s a été supprimé."
-
msgid "View and change Services Operators"
-msgstr "Affiche et modifie les Opérateurs des Services"
+msgstr "Affiche et modifie les Opérateurices des Services"
msgid "View and change configuration file settings"
msgstr "Voir et modifier les paramètres de configuration"
@@ -8415,7 +8332,7 @@ msgstr ""
"pour le canal.\n"
" \n"
"Si un pseudo est indiqué, affiche les mêmes informations pour \n"
-"le pseudo donné. Ceci est restreint aux Opérateurs des Services."
+"le pseudo donné. Ceci est restreint aux Opérateurices des Services."
msgid ""
"Without a parameter, reverses the effect of the IDENTIFY\n"
@@ -8424,7 +8341,7 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
"Sans paramètre, inverse l'effet de la commande IDENTIFY,\n"
@@ -8433,14 +8350,14 @@ msgstr ""
"cependant que l'on ne vous demandera pas de vous réidentifier.\n"
" \n"
"Avec un paramètre, fait la même chose avec le pseudo donné. Si\n"
-"vous spécifiez également REVALIDATE, les Services demanderont\n"
+"vous spécifiez également REVALIDATE, les services demanderont\n"
"au pseudo donné de se ré-identifier. Cette utilisation est \n"
-"réservée aux Opérateurs des Services."
+"réservée aux Opérateurices des Services."
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -8448,6 +8365,9 @@ msgid ""
"The RESET option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
+"The PASSWORD option displays the encryption algorithms used\n"
+"for user passwords.\n"
+" \n"
"The UPLINK option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
" \n"
@@ -8455,21 +8375,21 @@ msgid ""
" \n"
"The ALL option displays all of the above statistics."
msgstr ""
-"Sans option, affiche le nombre d'utilisateurs actuellement en ligne,\n"
-"le plus grand nombre d'utilisateurs connectés depuis que les\n"
-"Services ont été démarrés, et la période pendant laquelle les services\n"
+"Sans option, affiche le nombre d'utilisateurices actuellement en ligne,\n"
+"le plus grand nombre d'utilisateurices connectés depuis que les\n"
+"services ont été démarrés, et la période pendant laquelle les services\n"
"sont en état de marche.\n"
" \n"
"Avec l'option AKILL, affiche la taille actuelle de la liste\n"
"d'AKILL et le temps d'échéance par défaut.\n"
" \n"
-"L'option RESET réinitialise le nombre maximum d'utilisateurs\n"
-"au nombre courant d'utilisateurs sur le réseau.\n"
+"L'option RESET réinitialise le nombre maximum d'utilisateurices\n"
+"au nombre courant d'utilisateurices sur le réseau.\n"
" \n"
"L'option UPLINK affiche les informations sur le serveur qui est\n"
"utilisé pour linker Anope au réseau.\n"
" \n"
-"L'option HASH affiche des informations sur les hashmaps (la mémoire). \n"
+"L'option HASH affiche des informations sur les hashmaps. \n"
" \n"
"L'option ALL affiche toutes les statistiques citées."
@@ -8481,35 +8401,32 @@ msgid "You are already a member of the group of %s."
msgstr "Vous êtes déjà membre du groupe de %s."
msgid "You are already identified."
-msgstr "Vous êtes déjà identifié."
+msgstr "Vous êtes déjà identifié(e)."
#, c-format
msgid "You are already in %s!"
-msgstr "Vous êtes déjà sur %s ! "
+msgstr "Vous êtes déjà sur %s !"
msgid "You are no longer a super admin."
-msgstr "Vous n'êtes plus super-administrateur."
+msgstr "Vous n'êtes plus super-administrateurice."
msgid "You are not identified."
-msgstr "Vous n'êtes pas identifié."
+msgstr "Vous n'êtes pas identifié(e)."
msgid "You are not permitted to be on this channel."
-msgstr "Vous n'êtes pas autorisé à être sur ce canal."
+msgstr "Vous n'êtes pas autorisé(e) à être sur ce canal."
msgid "You are not permitted to change your memo limit."
-msgstr "Vous n'êtes pas autorisé à changer votre limite de mémos."
+msgstr "Vous n'êtes pas autorisé(e) à changer votre limite de mémos."
msgid "You are not using a client certificate."
msgstr "Vous n'utilisez pas de certificat client."
msgid "You are now a super admin."
-msgstr "Vous êtes maintenant super-administrateur."
-
-msgid "You are now an IRC Operator."
-msgstr "Vous êtes maintenant un Opérateur IRC."
+msgstr "Vous êtes maintenant super-administrateurice."
msgid "You are now identified for your nick. Change your password now."
-msgstr "Vous êtes désormais identifié pour votre pseudo. Vous pouvez changer de mot de passe maintenant."
+msgstr "Vous êtes désormais identifié(e) pour votre pseudo. Vous pouvez changer de mot de passe maintenant."
#, c-format
msgid "You are now in the group of %s."
@@ -8517,19 +8434,22 @@ msgstr "Vous êtes maintenant dans le groupe de %s."
#, c-format
msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
-msgstr "Vous avez dépassé votre nombre maximum de mémos (%d). Vous ne pourrez plus recevoir de nouveaux mémos sauf si vous supprimez quelques-uns de vos mémos actuels. "
+msgstr "Vous avez dépassé votre nombre maximum de mémos (%d). Vous ne pourrez plus recevoir de nouveaux mémos sauf si vous supprimez quelques-uns de vos mémos actuels."
-msgid "You can not NOOP Services."
-msgstr "Vous ne pouvez pas NOOP les Services."
+msgid "You can not NOOP services."
+msgstr "Vous ne pouvez pas NOOP les services."
msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
-msgstr "Vous ne pouvez pas désactiver les privilèges de fondateur puisqu'il serait impossible de les réactiver plus tard."
+msgstr "Vous ne pouvez pas désactiver les privilèges de fondateurice puisqu'il serait impossible de les réactiver plus tard."
msgid "You can not jupe an already juped server."
msgstr "Vous ne pouvez pas jupe un serveur déjà jupé."
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "Vous ne pouvez pas jupe le pseudo-serveur des Services ou le serveur auquel sont connectés les Services."
+msgid "You can not jupe your services' pseudoserver or your uplink server."
+msgstr "Vous ne pouvez pas jupe le pseudo-serveur des services ou le serveur auquel sont connectés les services."
+
+msgid "You can not queue any more messages."
+msgstr "Vous ne pouvez pas ajouter d'autres messages à la file d'attente."
#, c-format
msgid "You can not reload this module directly, instead reload %s."
@@ -8540,6 +8460,9 @@ msgstr ""
"Vous ne pouvez pas recevoir d'accusé de réception quand vous vous\n"
"êtes envoyé un message à vous-même."
+msgid "You can not send a single message while you have messages queued."
+msgstr "Vous ne pouvez pas envoyer un unique message tant que vous avez des messages dans la file d'attente."
+
#, c-format
msgid "You can't %s yourself!"
msgstr "Vous ne pouvez pas utiliser %s sur vous-même !"
@@ -8549,11 +8472,7 @@ msgstr "Vous ne pouvez pas ajouter un canal dans sa propre liste d'accès."
#, c-format
msgid "You can't logout %s, they are a Services Operator."
-msgstr "Vous ne pouvez pas déconnecter %s, car il est Opérateur des Services."
-
-#, c-format
-msgid "You cannot %s on this network."
-msgstr "Vous ne pouvez pas utiliser %s sur ce réseau."
+msgstr "Vous ne pouvez pas déconnecter %s, car iel est Opérateurice des Services."
#, c-format
msgid "You cannot set the %c flag."
@@ -8570,27 +8489,27 @@ msgstr "Vous ne pouvez mettre votre limite de mémos à plus de %d."
msgid "You cannot unassign bots while persist is set on the channel."
msgstr "Vous ne pouvez pas assigner de bot lorsque persist est actif pour ce canal."
-msgid "You cannot unset the e-mail on this network."
+msgid "You cannot unset the email on this network."
msgstr "Vous ne pouvez pas effacer votre email sur ce réseau."
msgid "You cannot use this command."
msgstr "Vous ne pouvez pas utiliser cette commande."
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Vous avez actuellement %d mémos, dont %d n'ont pas été lus."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr "Vous avez actuellement %zu mémos, dont %zu n'ont pas été lus."
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Vous avez actuellement %d mémos, dont 1 n'a pas été lu."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr "Vous avez actuellement %zu mémos, dont 1 n'a pas été lu."
#, c-format
-msgid "You currently have %d memos."
-msgstr "Vous avez actuellement %d mémos."
+msgid "You currently have %zu memos."
+msgstr "Vous avez actuellement %zu mémos."
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Vous avez actuellement %d mémos, dont aucun n'a été lu."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr "Vous avez actuellement %zu mémos, dont aucun n'a été lu."
msgid "You currently have 1 memo, and it has not yet been read."
msgstr "Vous avez actuellement 1 mémo, qui n'a pas encore été lu."
@@ -8605,6 +8524,12 @@ msgstr "Vous n'avez aucun mémo actuellement."
msgid "You do not have access to set mode %c."
msgstr "Vous n'avez pas les accès pour définir le mode %c."
+msgid "You do not have any messages queued and did not specify a message to send."
+msgstr "Vous n'avez pas de messages dans la file d'attente, et n'avez pas indiqué de message à envoyer."
+
+msgid "You do not have any queued messages."
+msgstr "Vous n'avez pas de messages dans la file d'attente."
+
#, c-format
msgid "You do not have the access to change %s's modes."
msgstr "Vous n'avez pas les accès pour changer les modes de %s."
@@ -8614,42 +8539,41 @@ msgid "You found me, %s!"
msgstr "Vous m'avez trouvé, %s !"
#, c-format
-msgid "You have %d new memos."
-msgstr "Vous avez %d nouveaux mémos."
-
-msgid "You have 1 new memo."
-msgstr "Vous avez 1 nouveau mémo."
+msgid "You have %d new memo."
+msgid_plural "You have %d new memos."
+msgstr[0] "Vous avez %d nouveau mémo."
+msgstr[1] "Vous avez %d nouveaux mémos."
#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
+"Type %s READ %zu to read it."
msgstr ""
"Vous avez un nouveau mémo de %s,\n"
-"Tapez %s%s READ %d pour le lire."
+"Tapez %s READ %zu pour le lire."
#, c-format
msgid "You have been invited to %s by %s."
-msgstr "Vous avez été invité à rejoindre %s par %s."
+msgstr "Vous avez été invité(e) à rejoindre %s par %s."
#, c-format
msgid "You have been invited to %s."
-msgstr "Vous avez été invité à rejoindre %s."
+msgstr "Vous avez été invité(e) à rejoindre %s."
#, c-format
msgid "You have been logged in as %s."
-msgstr "Vous vous êtes identifié en tant que %s."
+msgstr "Vous vous êtes identifié(e) en tant que %s."
msgid "You have been logged out."
-msgstr "Vous n'êtes plus identifié."
+msgstr "Vous n'êtes plus identifié(e)."
#, c-format
msgid "You have been unbanned from %s."
-msgstr "Vous avez été débanni de %s."
+msgstr "Vous avez été débanni(e) de %s."
#, c-format
msgid "You have been unbanned from %d channels."
-msgstr "Vous avez été débanni de %d canaux."
+msgstr "Vous avez été débanni(e) de %d canaux."
msgid "You have no limit on the number of memos you may keep."
msgstr "Vous n'avez aucune limite sur le nombre de mémos que vous pouvez garder."
@@ -8657,12 +8581,15 @@ msgstr "Vous n'avez aucune limite sur le nombre de mémos que vous pouvez garder
msgid "You have no memos."
msgstr "Vous n'avez pas de mémo."
+msgid "You have no messages queued."
+msgstr "Vous n'avez pas de messages dans la file d'attente."
+
msgid "You have no new memos."
msgstr "Vous n'avez pas de nouveau mémo."
#, c-format
msgid "You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
-msgstr "Vous avez atteint votre nombre maximum de mémos (%d). Vous ne pourrez plus recevoir de nouveaux mémos sauf si vous supprimez quelques-uns de vos mémos actuels. "
+msgstr "Vous avez atteint votre nombre maximum de mémos (%d). Vous ne pourrez plus recevoir de nouveaux mémos sauf si vous supprimez quelques-uns de vos mémos actuels."
#, c-format
msgid "You have regained control of %s."
@@ -8675,29 +8602,27 @@ msgstr "Vous pouvez supprimer n'importe quel pseudo de votre groupe."
msgid "You may not (un)lock mode %c."
msgstr "Vous ne pouvez pas (dé)verrouiller le mode %c."
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "Vous ne pouvez pas changer l'adresse email d'autres Opérateurs des Services."
-
msgid "You may not change the email of an unconfirmed account."
msgstr "Vous ne pouvez pas changer l'adresse email d'un compte non confirmé."
+msgid "You may not change the email of other Services Operators."
+msgstr "Vous ne pouvez pas changer l'adresse email d'autres Opérateurices des Services."
+
msgid "You may not change the password of other Services Operators."
-msgstr "Vous ne pouvez pas changer le mot de passe d'autres Opérateurs des Services."
+msgstr "Vous ne pouvez pas changer le mot de passe d'autres Opérateurices des Services."
-msgid "You may not drop other Services Operators' nicknames."
-msgstr "Vous ne pouvez pas supprimer le pseudo d'autres Opérateurs des Services."
+#, c-format
+msgid "You may not drop %s as it is the display nick for the account."
+msgstr "Vous ne pouvez pas supprimer %s car c'est le nom d'affichage du compte."
-msgid "You may not get the password of other Services Operators."
-msgstr "Vous ne pouvez pas obtenir le mot de passe d'autres Opérateurs des Services."
+msgid "You may not drop other Services Operators' nicknames."
+msgstr "Vous ne pouvez pas supprimer le pseudo d'autres Opérateurices des Services."
msgid "You may not suspend other Services Operators' nicknames."
-msgstr "Vous ne pouvez pas suspendre le pseudo d'autres Opérateurs des Services."
-
-msgid "You may view but not modify the access list of other Services Operators."
-msgstr "Vous pouvez voir mais pas modifier la liste d'accès d'autres Opérateurs des Services."
+msgstr "Vous ne pouvez pas suspendre le pseudo d'autres Opérateurices des Services."
msgid "You may view but not modify the certificate list of other Services Operators."
-msgstr "Vous pouvez voir mais pas modifier la liste de certificats d'autres Opérateurs des Services."
+msgstr "Vous pouvez voir mais pas modifier la liste de certificats d'autres Opérateurices des Services."
#, c-format
msgid "You might see yourself in the mirror, %s."
@@ -8707,7 +8632,7 @@ msgid "You must assign a bot to the channel before using this command."
msgstr "Vous devez assigner un bot au canal avant d'utiliser cette commande."
msgid "You must be a channel operator to register the channel."
-msgstr "Vous devez être un opérateur du canal pour l'enregistrer."
+msgstr "Vous devez être opérateurice du canal pour l'enregistrer."
#, c-format
msgid "You must be in %s to use this command."
@@ -8726,46 +8651,42 @@ msgid "You must confirm your account before you may send a memo."
msgstr "Vous devez confirmer votre compte avant de pouvoir envoyer un mémo."
#, c-format
-msgid "You must enter the channel name twice as a confirmation that you wish to drop %s."
-msgstr "Vous devez entrer le nom du canal deux fois pour confirmer que vous voulez vraiment effacer %s."
-
-#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr "Vous devez rester connecté plus de %d secondes avant d'enregistrer votre pseudo."
-
-#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
msgstr "Vous devez avoir le privilège %s(ME) sur le canal pour utiliser cette commande."
msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
+"You must now supply an email for your nick.\n"
+"This email will allow you to retrieve your password in\n"
"case you forget it."
msgstr ""
"Vous devez maintenant fournir un email pour votre pseudo.\n"
"Cet email vous permettra de retrouver votre mot de passe\n"
"au cas où vous le perdriez."
+#, c-format
+msgid "You must wait %s before registering your nick."
+msgstr "Vous devez attendre %s avant d'enregistrer votre pseudo."
+
msgid "You need to be identified to use this command."
-msgstr "Vous devez être identifié pour utiliser cette commande."
+msgstr "Vous devez être identifié(e) pour utiliser cette commande."
msgid "You will be notified by message and by mail when new memos arrive."
-msgstr "Vous serez notifié par message et par email quand vous recevrez de nouveaux mémos."
+msgstr "Vous serez notifié(e) par message et par email quand vous recevrez de nouveaux mémos."
msgid "You will be notified of new memos at logon and when they arrive, and by mail when they arrive."
-msgstr "Vous serez notifié par message et par email quand vous recevrez de nouveaux mémos, et par message à votre connexion."
+msgstr "Vous serez notifié(e) par message et par email quand vous recevrez de nouveaux mémos, et par message à votre connexion."
msgid "You will be notified of new memos at logon and when they arrive."
-msgstr "Vous serez notifié pour les nouveaux mémos à la connexion et quand ils arrivent."
+msgstr "Vous serez notifié(e) pour les nouveaux mémos à la connexion et quand ils arrivent."
msgid "You will be notified of new memos at logon, and by mail when they arrive."
-msgstr "Vous serez notifié par email quand vous recevrez de nouveaux mémos, et par message à votre connexion."
+msgstr "Vous serez notifié(e) par email quand vous recevrez de nouveaux mémos, et par message à votre connexion."
msgid "You will be notified of new memos at logon."
-msgstr "Vous serez notifié pour les nouveaux mémos à la connexion."
+msgstr "Vous serez notifié(e) pour les nouveaux mémos à la connexion."
msgid "You will be notified when new memos arrive."
-msgstr "Vous serez notifié quand de nouveaux mémos arrivent."
+msgstr "Vous serez notifié(e) quand de nouveaux mémos arrivent."
msgid "You will no longer be able to receive memos."
msgstr "Vous ne pourrez désormais plus recevoir de mémos."
@@ -8774,10 +8695,10 @@ msgid "You will no longer be informed via email."
msgstr "Vous ne serez plus averti par mail de l'arrivée de nouveau mémo."
msgid "You will not be notified of new memos."
-msgstr "Vous ne serez plus notifié pour les nouveaux mémos."
+msgstr "Vous ne serez plus notifié(e) pour les nouveaux mémos."
msgid "You will now be informed about new memos via email."
-msgstr "Vous serez maintenant averti par mail de l'arrivée de nouveaux mémos."
+msgstr "Vous serez maintenant averti(e) par mail de l'arrivée de nouveaux mémos."
msgid "Your IRCd does not support SVSJOIN."
msgstr "Votre IRCd ne supporte pas SVSJOIN."
@@ -8788,8 +8709,12 @@ msgstr "Votre IRCd ne supporte pas SVSNICK."
msgid "Your IRCd does not support SVSPART."
msgstr "Votre IRCd ne supporte pas SVSPART."
-msgid "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
-msgstr "Votre IRCd ne supporte pas les vIdent. Si ceci est incorrect, merci de le reporter, il s'agit peut être d'un bug."
+msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
+msgstr "Votre IRCd ne supporte pas les vident. Si ceci est incorrect, merci de le reporter, il s'agit peut être d'un bug."
+
+#, c-format
+msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
+msgstr "Votre empreinte de certificat SSL %s a été automatiquement ajoutée à votre liste de certificants."
#, c-format
msgid "Your account %s has been successfully created."
@@ -8818,7 +8743,7 @@ msgstr "Votre adresse email pour %s a été confirmée."
#, c-format
msgid "Your email has been updated to %s"
-msgstr "Votre adresse email a été changée en %s."
+msgstr "Votre adresse email a été changée en %s"
#, c-format
msgid "Your email has been updated to %s."
@@ -8845,6 +8770,12 @@ msgstr "Votre limite de mémos est de 0, vous ne recevrez aucun nouveau mémo.
msgid "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
msgstr "Votre limite de mémos est de 0, vous ne recevrez aucun nouveau mémo. Vous ne pouvez pas changer cette limite."
+msgid "Your message has been queued."
+msgstr "Votre message a été ajouté à la file d'attente."
+
+msgid "Your message queue has been cleared."
+msgstr "Votre file d'attente de messages a été vidée."
+
msgid "Your nick has been logged out."
msgstr "Votre pseudo n'est plus identifié."
@@ -8859,7 +8790,7 @@ msgstr "Votre pseudo n'est pas enregistré."
#, c-format
msgid "Your nickname is now being changed to %s"
-msgstr "Votre pseudo est maintenant changé en %s."
+msgstr "Votre pseudo est maintenant changé en %s"
msgid "Your oper block doesn't require logging in."
msgstr "Votre bloc oper ne nécessite pas de s'authentifier."
@@ -8869,27 +8800,23 @@ msgid "Your passcode has been re-sent to %s."
msgstr "Votre mot-code a été renvoyé à %s."
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Votre mot de passe est %s - notez-le pour une utilisation ultérieure."
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr "Votre mot de passe est trop long. Il ne doit pas dépasser %u caractères."
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr "Votre mot de passe est trop long. Il ne doit pas dépasser %u caractères."
+msgid "Your password is too short. It must be longer than %u characters."
+msgstr "Votre mot de passe est trop court. Il doit faire au moins %u caractères."
msgid "Your password reset request has expired."
msgstr "Votre demande de réinitialisation de mot de passe a expiré."
-msgid "Your vHost has been requested."
-msgstr "Votre demande de vHost a été enregistrée."
+msgid "Your vhost has been requested."
+msgstr "Votre demande de vhost a été enregistrée."
#, c-format
msgid "Your vhost of %s is now activated."
msgstr "Votre vhost %s est activé."
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "Votre vhost %s@%s est activé."
-
msgid "Your vhost was removed and the normal cloaking restored."
msgstr "Votre vhost a été supprimé et le masquage normal a été restauré."
@@ -8953,6 +8880,9 @@ msgstr "[canal] {num | liste | LAST | NEW | ALL}"
msgid "[key|#X-Y]"
msgstr "[clé|#X-Y]"
+msgid "[message]"
+msgstr "[message]"
+
msgid "[nick | channel]"
msgstr "{pseudo | canal}"
@@ -8983,19 +8913,19 @@ msgstr "[Suspendu]"
msgid "[Unconfirmed]"
msgstr "[Non confirmé]"
-msgid "[auto memo] Your requested vHost has been approved."
-msgstr "[auto memo] Votre requête de vHost a été approuvée."
+#, c-format
+msgid "[auto memo] VHost %s has been requested by %s."
+msgstr "[auto memo] Le vhost %s a été demandé par %s."
-msgid "[auto memo] Your requested vHost has been rejected."
-msgstr "[auto memo] Votre requête de vHost a été rejetée."
+msgid "[auto memo] Your requested vhost has been approved."
+msgstr "[auto memo] Votre demande de vhost a été approuvée."
-#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr "[auto memo] Votre requête de vHost a été rejetée. Raison : %s"
+msgid "[auto memo] Your requested vhost has been rejected."
+msgstr "[auto memo] Votre demande de vHost a été rejetée."
#, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "[auto memo] Le vHost %s a été demandé par %s."
+msgid "[auto memo] Your requested vhost has been rejected. Reason: %s"
+msgstr "[auto memo] Votre demande de vHost a été rejetée. Raison : %s"
msgid "[{pattern | channel} [INVISIBLE]]"
msgstr "[{modèle | canal} [INVISIBLE]]"
@@ -9003,96 +8933,26 @@ msgstr "[{modèle | canal} [INVISIBLE]]"
msgid "[{pattern | nick} [SECRET]]"
msgstr "[{modèle | pseudo} [SECRET]]"
-msgid "day"
-msgstr "jour"
-
-msgid "days"
-msgstr "jours"
-
msgid "does not expire"
msgstr "n'expire pas"
#, c-format
-msgid "expires in %d day"
-msgstr "expire dans %d jour"
-
-#, c-format
-msgid "expires in %d days"
-msgstr "expire dans %d jours"
-
-#, c-format
-msgid "expires in %d hour, %d minute"
-msgstr "expire dans %d heure, %d minute"
-
-#, c-format
-msgid "expires in %d hour, %d minutes"
-msgstr "expire dans %d heure, %d minutes"
-
-#, c-format
-msgid "expires in %d hours, %d minute"
-msgstr "expire dans %d heures, %d minute"
-
-#, c-format
-msgid "expires in %d hours, %d minutes"
-msgstr "expire dans %d heures, %d minutes"
-
-#, c-format
-msgid "expires in %d minute"
-msgstr "expire dans %d minute"
-
-#, c-format
-msgid "expires in %d minutes"
-msgstr "expire dans %d minutes"
+msgid "expires in %s"
+msgstr "expire dans %s"
msgid "expires momentarily"
msgstr "expire d'un instant à l'autre"
-msgid "hour"
-msgstr "heure"
-
-msgid "hours"
-msgstr "heures"
-
#, c-format
msgid "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
msgstr "lettres : %s, mots : %s, lignes : %s, smileys : %s, actions : %s"
-msgid "minute"
-msgstr "minute"
-
-msgid "minutes"
-msgstr "minutes"
-
msgid "not assigned yet"
msgstr "pas encore assigné"
-msgid "second"
-msgstr "seconde"
-
-msgid "seconds"
-msgstr "secondes"
-
-#, c-format
-msgid "vHost for %s has been activated."
-msgstr "Le vHost pour %s a été activé."
-
-#, c-format
-msgid "vHost for %s has been rejected."
-msgstr "Le vHost pour %s a été rejeté."
-
msgid "vhost"
msgstr "vhost"
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "Le vhost pour le groupe %s a été supprimé."
-
-msgid "year"
-msgstr "année"
-
-msgid "years"
-msgstr "années"
-
msgid "{MODIFY|VIEW} [block name item name item value]"
msgstr "{MODIFY|VIEW} [nom bloc nom item item valeur]"
@@ -9104,6 +8964,3 @@ msgstr "{pseudo | canal}"
msgid "{nick | channel} memo-text"
msgstr "{pseudo | canal} texte"
-
-#~ msgid "Password authentication required for that command."
-#~ msgstr "Authentification par mot de passe requise pour cette commande."
diff --git a/language/anope.hu_HU.po b/language/anope.hu_HU.po
deleted file mode 100644
index 91d07c2c7..000000000
--- a/language/anope.hu_HU.po
+++ /dev/null
@@ -1,9966 +0,0 @@
-# Anope IRC Services language file
-# Copyright (C) 2011
-# This file is distributed under the same license as the Anope IRC Services package.
-# Adam <adam@anope.org>, 2011.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Anope\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-01-06 18:19+0100\n"
-"PO-Revision-Date: 2010-09-19 20:37-0400\n"
-"Last-Translator: Adam <adam@anope.org>\n"
-"Language-Team: Hungarian\n"
-"Language: hu_HU\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-
-#, c-format
-msgid "%d channel(s) cleared, and %d channel(s) dropped."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%d nickname(s) dropped."
-msgstr "A nickneved dropolva lett,"
-
-#, fuzzy, c-format
-msgid "%s added to %s %s list."
-msgstr "%s hozzáadva az AKILL listához."
-
-#, c-format
-msgid "%s added to %s access list at level %d."
-msgstr ""
-"%s hozzáadva a %s hozzáférési listájához.\n"
-"A hozzáférési szintje a ChanServ parancsokhoz: %d."
-
-#, fuzzy, c-format
-msgid "%s added to %s access list at privilege %s (level %d)"
-msgstr ""
-"%s hozzáadva a %s hozzáférési listájához.\n"
-"A hozzáférési szintje a ChanServ parancsokhoz: %d."
-
-#, c-format
-msgid "%s added to %s autokick list."
-msgstr "%s hozzáadva a (%s) csatorna autokick listájához"
-
-#, c-format
-msgid "%s added to %s bad words list."
-msgstr "A %s szó hozzáadva a %s tiltott szavak listájához."
-
-#, fuzzy, c-format
-msgid "%s added to %s's access list."
-msgstr "%s hozzáadva a hozzáférési listádhoz."
-
-#, fuzzy, c-format
-msgid "%s added to %s's certificate list."
-msgstr "%s hozzáadva a hozzáférési listádhoz."
-
-#, fuzzy, c-format
-msgid "%s added to ignore list."
-msgstr "%s hozzáadva a hozzáférési listádhoz."
-
-#, fuzzy, c-format
-msgid "%s added to the %s list."
-msgstr "%s hozzáadva az AKILL listához."
-
-#, c-format
-msgid "%s added to the AKILL list."
-msgstr "%s hozzáadva az AKILL listához."
-
-#, c-format
-msgid ""
-"%s allows you to execute \"fantasy\" commands in the channel.\n"
-"Fantasy commands are commands that can be executed from messaging a\n"
-"channel, and provide a more convenient way to execute commands. Commands "
-"that\n"
-"require a channel as a parameter will automatically have that parameter\n"
-"given.\n"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to have a bot on your own channel.\n"
-"It has been created for users that can't host or\n"
-"configure a bot, or for use on networks that don't\n"
-"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
-"more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s lehetővé teszi, hogy botod legyen a csatornádon.\n"
-"Ezt olyan felhasználók számára készítették, akik\n"
-"nem tudnak saját botot futtatni, vagy a hálózaton nem\n"
-"engedélyezik ezt. Az elérhető parancsok listája alább \n"
-"található; használatukhoz írd be /msg %s parancs.\n"
-"Bővebb információt így kaphatsz az adott parancsról:\n"
-"/msg %s HELP parancs."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register a nickname and\n"
-"prevent others from using it. The following\n"
-"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s lehetőséget nyújt a \"register\" parancs használatával\n"
-"a nickneved regisztrálására, ezzel megelőzi, hogy más is\n"
-"használhassa a nicked. A NickServ parancsokkal\n"
-"írányítható. Az adott parancs szintaktikáját megkapod, ha\n"
-"beírod, hogy: /msg %s parancs, lásd még a\n"
-"/msg %s HELP parancs."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register an account.\n"
-"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s lehetőséget nyújt a \"register\" parancs használatával\n"
-"a nickneved regisztrálására, ezzel megelőzi, hogy más is\n"
-"használhassa a nicked. A NickServ parancsokkal\n"
-"írányítható. Az adott parancs szintaktikáját megkapod, ha\n"
-"beírod, hogy: /msg %s parancs, lásd még a\n"
-"/msg %s HELP parancs."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register and control various\n"
-"aspects of channels. %s can often prevent\n"
-"malicious users from \"taking over\" channels by limiting\n"
-"who is allowed channel operator privileges. Available\n"
-"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
-msgstr ""
-"%s lehetőséget ad arra, hogy regisztráld a csatornádat.\n"
-"%s használatával elkerülhető a \"take over\" jelenség,\n"
-"amit az opjoggal visszaélő userek okozhatnak. Még pedig\n"
-"úgy, hogy meghatározható az, hogy ki kapjon a csatornán\n"
-"operátori kiváltságokat. A parancsok használatához írd be:\n"
-"/msg %s parancs, ha több információ kell a paranccsal\n"
-"kapcsolatban, akkor írd be: /msg %s HELP parancs.\n"
-" "
-
-#, c-format
-msgid "%s already exists in %s bad words list."
-msgstr "A %s szót már tartalmazza a %s tiltott szavak listája"
-
-#, c-format
-msgid "%s already exists on %s autokick list."
-msgstr "%s már szerepel a (%s) csatorna autokick listáján."
-
-#, c-format
-msgid "%s already exists on the EXCEPTION list."
-msgstr "%s already exists on the EXCEPTION list."
-
-#, c-format
-msgid "%s cannot be taken as times to ban."
-msgstr "%s nem fogadható el banolási időnek."
-
-#, fuzzy, c-format
-msgid "%s changed your usermodes to %s."
-msgstr "%s váltóztatott a módodon."
-
-#, fuzzy, c-format
-msgid "%s channel list:"
-msgstr "Vége a szoba listának."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s %s list."
-msgstr "%s törölve lett a %s AOP listáról."
-
-#, c-format
-msgid "%s deleted from %s access list."
-msgstr "%s törölve lett a (%s) csatorna hozzáférési listájáról."
-
-#, c-format
-msgid "%s deleted from %s autokick list."
-msgstr "%s törölve a (%s) csatorna autokick listájáról."
-
-#, c-format
-msgid "%s deleted from %s bad words list."
-msgstr "A %s szó törölve %s tiltott szavak listájából."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s's access list."
-msgstr "%s törölve lett a (%s) csatorna hozzáférési listájáról."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s's certificate list."
-msgstr "%s törölve a hozzáférési listádról."
-
-#, c-format
-msgid "%s deleted from session-limit exception list."
-msgstr "%s törölve a session-korlát kivétel listáról."
-
-#, fuzzy, c-format
-msgid "%s deleted from the %s list."
-msgstr "%s törölve lett a %s AOP listáról."
-
-#, c-format
-msgid "%s deleted from the AKILL list."
-msgstr "%s törölve az AKILL listáról."
-
-#, c-format
-msgid "%s disabled on channel %s."
-msgstr "%s letiltva a (%s) csatornán."
-
-#, c-format
-msgid "%s has been invited to %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "%s has been joined to %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "%s has been parted from %s."
-msgstr "%s has been unbanned from %s."
-
-#, c-format
-msgid "%s has been unbanned from %s."
-msgstr "%s has been unbanned from %s."
-
-#, fuzzy, c-format
-msgid "%s has no access in any channels."
-msgstr "%s letiltva a (%s) csatornán."
-
-#, fuzzy, c-format
-msgid "%s has no access on %s."
-msgstr "%s has been invited to %s."
-
-#, c-format
-msgid "%s has too many channels registered."
-msgstr "%s részére túl sok csatorna van regisztrálva."
-
-#, fuzzy, c-format
-msgid "%s is a super administrator."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy, c-format
-msgid ""
-"%s is a utility allowing IRC users to send short\n"
-"messages to other IRC users, whether they are online at\n"
-"the time or not, or to channels(*). Both the sender's\n"
-"nickname and the target nickname or channel must be\n"
-"registered in order to send a memo.\n"
-"%s's commands include:"
-msgstr ""
-"%s lehetőséget nyújt az IRC felhasználókank, hogy rövid\n"
-"üzeneteket küldjenek más IRC felhasználók részére,\n"
-"akkor is, ha a fogadó fél nem online, és csatornákra (*).\n"
-"Ahhoz, hogy üzenetet lehessen küldeni, mind a küldő és a\n"
-"fogadó fél nicknevének regisztráltnak kell lennie.\n"
-"\t\n"
-"%s parancsok a következőket tartalmazzák:"
-
-#, fuzzy, c-format
-msgid "%s is already in %s!"
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is already in %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is already on the ignore list."
-msgstr "%s hozzáadva a hozzáférési listádhoz."
-
-#, fuzzy, c-format
-msgid "%s is already suspended."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is not a registered unforbidden nick or channel."
-msgstr "%s nem érvényes bot vagy regisztrált szoba."
-
-#, c-format
-msgid "%s is not a valid ban type."
-msgstr "%s nem érvényes ban típus."
-
-#, c-format
-msgid "%s is not a valid bot or registered channel."
-msgstr "%s nem érvényes bot vagy regisztrált szoba."
-
-#, fuzzy, c-format
-msgid "%s is not a valid e-mail address."
-msgstr "%s nem érvényes ban típus."
-
-#, fuzzy, c-format
-msgid "%s is not currently on channel %s."
-msgstr "%s letiltva a (%s) csatornán."
-
-#, fuzzy, c-format
-msgid "%s is not in %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is not on the ignore list."
-msgstr "%s nick nem található a mellőzöttek listáján."
-
-#, fuzzy, c-format
-msgid "%s is on the auto kick list of %s (%s)."
-msgstr "%s hozzáadva a (%s) csatorna autokick listájához"
-
-#, fuzzy, c-format
-msgid "%s is the founder of %s."
-msgstr "%s letiltva a (%s) csatornán."
-
-#, c-format
-msgid "%s matches access entry %s (from entry %s), which has privilege %s."
-msgstr ""
-
-#, c-format
-msgid "%s matches access entry %s, which has privilege %s."
-msgstr ""
-
-#, c-format
-msgid ""
-"%s matches an except on %s and cannot be banned until the except has been "
-"removed."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s matches auto kick entry %s on %s (%s)."
-msgstr "%s hozzáadva a (%s) csatorna autokick listájához"
-
-#, fuzzy, c-format
-msgid "%s not found on %s %s list."
-msgstr "%s nem találatható a %s AOP listán."
-
-#, c-format
-msgid "%s not found on %s access list."
-msgstr "%s nem található a (%s) csatorna hozzáférési listáján."
-
-#, c-format
-msgid "%s not found on %s autokick list."
-msgstr "%s nem szerepel a (%s) csatorna autokick listáján."
-
-#, c-format
-msgid "%s not found on %s bad words list."
-msgstr "A %s szó nem található a %s tiltott szavak listáján."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's access list."
-msgstr "%s nem található a (%s) csatorna hozzáférési listáján."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's certificate list."
-msgstr "%s nem található a hozzáférési listádon."
-
-#, fuzzy, c-format
-msgid "%s not found on ignore list."
-msgstr "%s nick nem található a mellőzöttek listáján."
-
-#, c-format
-msgid ""
-"%s not found on session list, but has a limit of %d because it matches entry:"
-" %s."
-msgstr ""
-
-#, c-format
-msgid "%s not found on session-limit exception list."
-msgstr "%s nem található a session-korlát kivétel listán."
-
-#, fuzzy, c-format
-msgid "%s not found on the %s list."
-msgstr "%s nem találatható a %s AOP listán."
-
-#, c-format
-msgid "%s not found on the AKILL list."
-msgstr "%s nem található az AKILL listán."
-
-#, fuzzy, c-format
-msgid "%s removed from the %s access list."
-msgstr "%s törölve lett a (%s) csatorna hozzáférési listájáról."
-
-#, fuzzy, c-format
-msgid "%s removed from the ignore list."
-msgstr "%s törölve a hozzáférési listádról."
-
-#, fuzzy, c-format
-msgid "%s users list:"
-msgstr "Vége a felhasználó listának."
-
-#, c-format
-msgid "%s will no longer be ignored."
-msgstr "%s nick most már nics mellőzve."
-
-#, c-format
-msgid "%s will now be ignored for %s."
-msgstr "%s nick most mellőzte %s nicket."
-
-#, c-format
-msgid "%s will now permanently be ignored."
-msgstr "%s nick most véglegesen mellőzve van."
-
-#, fuzzy, c-format
-msgid "%s%s HELP %s for more information."
-msgstr ""
-"Írd be: /msg %s HELP SET opció bővebb információért az\n"
-"adott opcióról."
-
-msgid "ADD nick user host real"
-msgstr ""
-
-#, fuzzy
-msgid "CHANGE oldnick newnick [user [host [real]]]"
-msgstr ""
-"BOT ADD nick user hoszt valósnév\n"
-"BOT CHANGE réginickújnick [user [hoszt [valósnév]]]\n"
-"BOT DEL nick"
-
-#, fuzzy
-msgid "DEL nick"
-msgstr "DEL <nick>."
-
-#, fuzzy
-msgid ""
-"EXCEPTION ADD adds the given host mask to the exception list.\n"
-"Note that nick!user@host and user@host masks are invalid!\n"
-"Only real host masks, such as box.host.dom and *.host.dom,\n"
-"are allowed because sessions limiting does not take nick or\n"
-"user names into account. limit must be a number greater than\n"
-"or equal to zero. This determines how many sessions this host\n"
-"may carry at a time. A value of zero means the host has an\n"
-"unlimited session limit. See the AKILL help for details about\n"
-"the format of the optional expiry parameter.\n"
-" \n"
-"EXCEPTION DEL removes the given mask from the exception list.\n"
-" \n"
-"EXCEPTION LIST and EXCEPTION VIEW show all current\n"
-"sessions if the optional mask is given, the list is limited\n"
-"to those sessions matching the mask. The difference is that\n"
-"EXCEPTION VIEW is more verbose, displaying the name of the\n"
-"person who added the exception, its session limit, reason,\n"
-"host mask and the expiry date and time.\n"
-" \n"
-"Note that a connecting client will \"use\" the first exception\n"
-"their host matches."
-msgstr ""
-"Syntax: EXCEPTION ADD [+lejárat] maszkkorlátindok\n"
-" EXCEPTION DEL {maszk| list}\n"
-" EXCEPTION MOVE szám helyzet\n"
-" EXCEPTION LIST [maszk | lista]\n"
-" EXCEPTION VIEW [maszk | lista]\n"
-"\n"
-"Lehetőséget nyújt a szervíz adminnak, hogy karbantartsák\n"
-"azon hostok listáját, amelyeknek korlátozásuk van,\n"
-"engedélyezve bizonyos gépeket,úgymint a shell szervereket,\n"
-"hogy egyidőben felvigyenek klienseket alapértelmezettnél\n"
-"nagyobb számban. Amennyiben a gép eléri a korlátot, minden\n"
-"csatlakozni próbáló kliens killelve lesz.Mielőtt a kill\n"
-"megtörténne, figyelmeztetést kapnak %s /NOTICE üzeneten \n"
-"keresztül. Az üzenet tartalma a konfigurációtól függ.\n"
-"\n"
-"EXCEPTION ADD hozzáadja a hostmaszkot a kivétellistához.\n"
-"Vedd figyelembe, hogy a nick!user@host és user@host\n"
-"maszkok érvénytelenek! Csak valós hostmaszkok, mint pl.\n"
-"box.host.dom és *.host.dom, megengedettek, a session\n"
-"korlátozásmaszkja nem vesz fel nicknevet/felhasználónevet.\n"
-"A korlátlegyen egy nullával egyenlő vagy nagyobb szám.\n"
-"Ez határozza meg, hogy hány sessiont vihet magával a host\n"
-"egyidőben. A nulla azt jelenti, hogy a hostnak korlátlan\n"
-"számú sessionja lehet. Lásd az AKILL helpet a részletek\n"
-"felöl a formáról a szükséges lejárati parameterről.\n"
-"EXCEPTION DEL Törli a megadott maszkot a kivétel litáról\t\n"
-"EXCEPTION MOVE módisítja a kivétel poziciószámát. A \n"
-"kivételek fel-le mozgatja, az üres helyekre is.\n"
-"EXCEPTION LIST és EXCEPTION VIEW Mutatja az összes\n"
-"aktuális kivételt; ha megadsz egy tetszőleges maszkot,\n"
-"korlátozza azokat a kivételeket, melyekre ráillik a maszk.\n"
-"A különbség a két parancs között az, hogy az\n"
-"EXCEPTION VIEW sokkal részletesebb, megjeleníti a\n"
-"kivételt felrakó nevét a session korlátot, indokot, \n"
-"hostmaszkot és a lejárati időt,éa a kivétel legutolsó\n"
-"\"használati\" idejét.\n"
-"\n"
-"Vedd figyelembe, a csatlakozó kliens a ráillő kivételek\n"
-"közül mindig az elsőt használja. Hatalmas kivétellisták\n"
-"és széleskörű kivételmaszkok csökkenthetik a Szervíz \n"
-"teljesítményét.\n"
-"\n"
-"Korlátozva Szervíz adminnak."
-
-msgid ""
-"SET kills all operators from the given\n"
-"server and prevents operators from opering\n"
-"up on the given server. REVOKE removes this\n"
-"restriction."
-msgstr ""
-
-#, c-format
-msgid ""
-"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
-"information."
-msgstr ""
-
-#, c-format
-msgid "[auto-memo] The memo you sent to %s has been viewed."
-msgstr "[auto-memo] A memo, amit %s számára küldtél meg lett tekintve."
-
-#, fuzzy
-msgid "[target] [password]"
-msgstr "GROUP célnick jelszó"
-
-msgid "address"
-msgstr ""
-
-#, fuzzy
-msgid "botname {ON|OFF}"
-msgstr "SASET nickname AUTOOP {ON | OFF}"
-
-#, fuzzy
-msgid "channel"
-msgstr "DROP #szoba"
-
-#, fuzzy
-msgid "channel bantype"
-msgstr "ACT #szoba szöveg"
-
-#, fuzzy
-msgid "channel channel"
-msgstr "TOPIC #szoba [topic]"
-
-#, fuzzy
-msgid "channel command method [status]"
-msgstr "KICK #szoba opció {ON|OFF} [beállítások]"
-
-#, fuzzy
-msgid "channel mask [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel modes"
-msgstr "MODE szoba mód"
-
-#, fuzzy
-msgid "channel nick"
-msgstr "UNBAN #szoba [nick]"
-
-#, fuzzy
-msgid "channel nick [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel target [what]"
-msgstr "CLEAR #szoba mit?"
-
-#, fuzzy
-msgid "channel text"
-msgstr "ACT #szoba szöveg"
-
-#, fuzzy
-msgid "channel time"
-msgstr "ACT #szoba szöveg"
-
-#, fuzzy
-msgid "channel user reason"
-msgstr "KICK #szoba user indok"
-
-#, fuzzy
-msgid "channel what"
-msgstr "TOPIC #szoba [topic]"
-
-#, fuzzy
-msgid "channel ADD mask"
-msgstr "MODE szoba mód"
-
-msgid "channel ADD mask level"
-msgstr ""
-
-#, fuzzy
-msgid "channel ADD message"
-msgstr "MODE szoba mód"
-
-msgid "channel ADD word [SINGLE | START | END]"
-msgstr ""
-
-#, fuzzy
-msgid "channel ADD {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel APPEND topic"
-msgstr "TOPIC #szoba [topic]"
-
-#, fuzzy
-msgid "channel CLEAR"
-msgstr "DROP #szoba"
-
-#, fuzzy
-msgid "channel CLEAR [what]"
-msgstr "TOPIC #szoba [topic]"
-
-#, fuzzy
-msgid "channel CLEAR [ALL]"
-msgstr "DROP #szoba"
-
-#, fuzzy
-msgid "channel DEL num"
-msgstr "MODE szoba mód"
-
-#, fuzzy
-msgid "channel DEL {mask | entry-num | list}"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-#, fuzzy
-msgid "channel DEL {nick | mask | entry-num | list}"
-msgstr "AOP #szoba { ADD | DEL | LIST | CLEAR } [ nick | sorszám ]"
-
-#, fuzzy
-msgid "channel DEL {word | entry-num | list}"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-msgid "channel ENFORCE"
-msgstr ""
-
-#, fuzzy
-msgid "channel LIST"
-msgstr "DROP #szoba"
-
-#, fuzzy
-msgid "channel LIST [mask | entry-num | list]"
-msgstr "AOP #szoba { ADD | DEL | LIST | CLEAR } [ nick | sorszám ]"
-
-#, fuzzy
-msgid "channel LIST [mask | list]"
-msgstr "AOP #szoba { ADD | DEL | LIST | CLEAR } [ nick | sorszám ]"
-
-msgid "channel LIST [mask | +flags]"
-msgstr ""
-
-#, fuzzy
-msgid "channel LOCK {ADD|DEL|SET|LIST} [what]"
-msgstr "AOP #szoba { ADD | DEL | LIST | CLEAR } [ nick | sorszám ]"
-
-#, fuzzy
-msgid "channel RESET"
-msgstr "SET szoba GREET {ON|OFF}"
-
-#, fuzzy
-msgid "channel SET modes"
-msgstr "MODE szoba mód"
-
-msgid "channel SET type level"
-msgstr ""
-
-#, fuzzy
-msgid "channel VIEW [mask | entry-num | list]"
-msgstr "AOP #szoba { ADD | DEL | LIST | CLEAR } [ nick | sorszám ]"
-
-#, fuzzy
-msgid "channel VIEW [mask | list]"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-#, fuzzy
-msgid "channel [description]"
-msgstr "REGISTER #szoba leírás"
-
-#, fuzzy
-msgid "channel [nick]"
-msgstr "UNBAN #szoba [nick]"
-
-#, fuzzy
-msgid "channel [parameters]"
-msgstr "CLEAR #szoba mit?"
-
-#, fuzzy
-msgid "channel [user]"
-msgstr "UNBAN #szoba [nick]"
-
-#, fuzzy
-msgid "channel [+expiry] [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [+expiry] {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [MODIFY] mask changes"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [SET] [topic]"
-msgstr "TOPIC #szoba [topic]"
-
-#, fuzzy
-msgid "channel [UNLOCK|LOCK]"
-msgstr "DROP #szoba"
-
-#, fuzzy
-msgid "channel {ON|OFF}"
-msgstr "SET #szoba XOP {ON | OFF}"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [ln [secs]]]"
-msgstr "KICK #szoba opció {ON|OFF} [beállítások]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [min [percent]]]"
-msgstr "KICK #szoba opció {ON|OFF} [beállítások]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [num]]"
-msgstr "KICK #szoba opció {ON|OFF} [beállítások]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb]"
-msgstr "SET #szoba XOP {ON | OFF}"
-
-msgid "channel {DIS | DISABLE} type"
-msgstr ""
-
-#, fuzzy
-msgid "channel {ON | LEVEL | OFF}"
-msgstr "SET #szoba SIGNKICK {ON | LEVEL | OFF}"
-
-#, fuzzy
-msgid "channel {ON | OFF}"
-msgstr "SET #szoba XOP {ON | OFF}"
-
-msgid "email"
-msgstr ""
-
-#, fuzzy
-msgid "language"
-msgstr "SET LANGUAGE szám"
-
-#, fuzzy
-msgid "memo-text"
-msgstr "STAFF memo-text"
-
-#, fuzzy
-msgid "message"
-msgstr "GLOBAL üzenet"
-
-msgid "modname"
-msgstr ""
-
-msgid "new-display"
-msgstr ""
-
-#, fuzzy
-msgid "new-password"
-msgstr "GROUP célnick jelszó"
-
-#, fuzzy
-msgid "nick"
-msgstr "INFO nick"
-
-#, fuzzy
-msgid "nick channel"
-msgstr "CANCEL {nick | #szoba}"
-
-#, fuzzy
-msgid "nick channel [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "nick flags"
-msgstr "OLINE nick flagek"
-
-#, fuzzy
-msgid "nick hostmask"
-msgstr "SET <nick> <hosztmaszk>."
-
-#, fuzzy
-msgid "nick newnick"
-msgstr "SVSNICK nick újnick "
-
-#, fuzzy
-msgid "nick [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "nickname"
-msgstr "CHECK nicknév "
-
-#, fuzzy
-msgid "nickname address"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "nickname email"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "nickname language"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "nickname message"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "nickname new-display"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "nickname new-password"
-msgstr "GHOST nicknév [jelszó]"
-
-#, fuzzy
-msgid "nickname [parameter]"
-msgstr "GHOST nicknév [jelszó]"
-
-#, fuzzy
-msgid "nickname [password]"
-msgstr "GHOST nicknév [jelszó]"
-
-#, fuzzy
-msgid "nickname [+expiry] [reason]"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-msgstr "SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-
-#, fuzzy
-msgid "nickname {ON | OFF}"
-msgstr "SASET nickname AUTOOP {ON | OFF}"
-
-#, fuzzy
-msgid "nickname {ON | QUICK | IMMED | OFF}"
-msgstr "SASET nickname KILL {ON | QUICK | IMMED | OFF}"
-
-#, fuzzy
-msgid "option (channel | bot) settings"
-msgstr "SET #szoba opció beállítások"
-
-#, fuzzy
-msgid "option channel parameters"
-msgstr "SEND {nick | #szoba} memo-szöveg"
-
-#, fuzzy
-msgid "option channel {ON|OFF} [settings]"
-msgstr "KICK #szoba opció {ON|OFF} [beállítások]"
-
-msgid "option nickname parameters"
-msgstr ""
-
-#, fuzzy
-msgid "option parameters"
-msgstr "SET opció beállítás"
-
-#, fuzzy
-msgid "option setting"
-msgstr "SET opció beállítás"
-
-#, fuzzy
-msgid "passcode"
-msgstr "REGISTER jelszó email"
-
-#, fuzzy
-msgid "password"
-msgstr "GROUP célnick jelszó"
-
-#, fuzzy
-msgid "password [email]"
-msgstr "REGISTER jelszó email"
-
-#, fuzzy
-msgid "password email"
-msgstr "REGISTER jelszó email"
-
-#, fuzzy
-msgid "pattern [SUSPENDED] [NOEXPIRE]"
-msgstr "LIST pattern [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-
-#, fuzzy
-msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-msgstr "LIST pattern [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-
-#, fuzzy
-msgid "server [reason]"
-msgstr "JUPE szervernév [leírás]"
-
-#, fuzzy
-msgid "user modes"
-msgstr "MODE szoba mód"
-
-#, fuzzy
-msgid "user [reason]"
-msgstr "JUPE szervernév [leírás]"
-
-#, fuzzy
-msgid ""
-" \n"
-"SNLINE ADD adds the given realname mask to the SNLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SNLINE which does not expire, use +0. If the\n"
-"realname mask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current SNLINE default expiry time can be found with the\n"
-"STATS AKILL command.\n"
-" \n"
-"Note: because the realname mask may contain spaces, the\n"
-"separator between it and the reason is a colon."
-msgstr ""
-"Syntax: AKILL ADD [ +lejárat] maszk indok\n"
-" AKILL DEL {maszk | sor-szám | list}\n"
-" AKILL LIST [maszk | list]\n"
-" AKILL VIEW [maszk | list]\n"
-" AKILL CLEAR\n"
-"\n"
-"Lehetőséget ad a szervíz opoknak, hogy karbantartsák az\n"
-"AKILL listát. Ha egy felhasználó az AKILL maszkkal egyező\n"
-"cimről próbál csatlakozni , akkor szervíz kiad egy KILL \n"
-"parancsot a nickre, és a támogatott szervertípusokon arra\n"
-"utasít minden szervert, hogy adjon K-linet a maszknak.\n"
-"\n"
-"AKILL ADD hozzáadja a megadott user@host/ip maszkot az\n"
-"AKILL listára a megadott indokkal (amit meg kell adnod).\n"
-"Az elévülést egész számmot kovet egy időparaméter d (nap),\n"
-"h (óra), m (perc).Ezek kombinálása nem lehetséges(1h30m).\n"
-"ha nem adsz meg időegységet akkor önmagában napot jelent.\n"
-"(+30 az 30 napot jelent).Ha +0-át adsz meg akkor nem \n"
-"elévülő lesz.Ha a usermaszk + -al kezdődik akkor elévülést\n"
-"meg kell adni akkor is ha megegyezik az alapértelmezéssel.\n"
-"Az AKILL jelenlegi alapértelmezett elévüólési ideje \n"
-"megnézhető a STATS AKILL paranccsal.\n"
-"AKILL DEL törli a maszkot az AKILL listáról, ha rajta\n"
-"van. Ha bejegyzés sorszámot adsz meg akkor azok fognak\n"
-"törlődni.(lásd a példát alább)\n"
-"AKILL LIST kiirja a jelenlegi AKILL listát. Ha egy \n"
-"\"*\" karakteres maszk van megadva, akkor csak azokat az\n"
-"AKILL-eket listázza, amelyek ráillenek a megadott maszkra.\n"
-"Ha sorszámot adsz meg akkor azok fognak törlődni. Példa:\n"
-"\tAKILL LIST 2-5,7-9\n"
-" Listázza az AKILL-en lévoket 2-től 5-ig és 7-től 9-ig\n"
-" az AKILL listából\n"
-"AKILL VIEW részletesebb verziója az AKILL LIST-nek,\n"
-"amely megmutatja, hogy ki vette fel az AKILL-t,\tmikor lett\n"
-"felvéve és mikor jár le, éppúgy, felhasználó@gazdanév \n"
-"maszkot és indokot.\n"
-"\t\n"
-"AKILL CLEAR töröli az összes AKILL bejegyzést.\n"
-"\n"
-"Korlátozva Szervíz operatornak."
-
-#, fuzzy
-msgid ""
-" \n"
-"SQLINE ADD adds the given (nick's) mask to the SQLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SQLINE which does not expire, use +0.\n"
-"If the mask to be added starts with a +, an expiry time\n"
-"must be given, even if it is the same as the default. The\n"
-"current SQLINE default expiry time can be found with the\n"
-"STATS AKILL command."
-msgstr ""
-"Syntax: AKILL ADD [ +lejárat] maszk indok\n"
-" AKILL DEL {maszk | sor-szám | list}\n"
-" AKILL LIST [maszk | list]\n"
-" AKILL VIEW [maszk | list]\n"
-" AKILL CLEAR\n"
-"\n"
-"Lehetőséget ad a szervíz opoknak, hogy karbantartsák az\n"
-"AKILL listát. Ha egy felhasználó az AKILL maszkkal egyező\n"
-"cimről próbál csatlakozni , akkor szervíz kiad egy KILL \n"
-"parancsot a nickre, és a támogatott szervertípusokon arra\n"
-"utasít minden szervert, hogy adjon K-linet a maszknak.\n"
-"\n"
-"AKILL ADD hozzáadja a megadott user@host/ip maszkot az\n"
-"AKILL listára a megadott indokkal (amit meg kell adnod).\n"
-"Az elévülést egész számmot kovet egy időparaméter d (nap),\n"
-"h (óra), m (perc).Ezek kombinálása nem lehetséges(1h30m).\n"
-"ha nem adsz meg időegységet akkor önmagában napot jelent.\n"
-"(+30 az 30 napot jelent).Ha +0-át adsz meg akkor nem \n"
-"elévülő lesz.Ha a usermaszk + -al kezdődik akkor elévülést\n"
-"meg kell adni akkor is ha megegyezik az alapértelmezéssel.\n"
-"Az AKILL jelenlegi alapértelmezett elévüólési ideje \n"
-"megnézhető a STATS AKILL paranccsal.\n"
-"AKILL DEL törli a maszkot az AKILL listáról, ha rajta\n"
-"van. Ha bejegyzés sorszámot adsz meg akkor azok fognak\n"
-"törlődni.(lásd a példát alább)\n"
-"AKILL LIST kiirja a jelenlegi AKILL listát. Ha egy \n"
-"\"*\" karakteres maszk van megadva, akkor csak azokat az\n"
-"AKILL-eket listázza, amelyek ráillenek a megadott maszkra.\n"
-"Ha sorszámot adsz meg akkor azok fognak törlődni. Példa:\n"
-"\tAKILL LIST 2-5,7-9\n"
-" Listázza az AKILL-en lévoket 2-től 5-ig és 7-től 9-ig\n"
-" az AKILL listából\n"
-"AKILL VIEW részletesebb verziója az AKILL LIST-nek,\n"
-"amely megmutatja, hogy ki vette fel az AKILL-t,\tmikor lett\n"
-"felvéve és mikor jár le, éppúgy, felhasználó@gazdanév \n"
-"maszkot és indokot.\n"
-"\t\n"
-"AKILL CLEAR töröli az összes AKILL bejegyzést.\n"
-"\n"
-"Korlátozva Szervíz operatornak."
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Accounts that are not used anymore are subject to\n"
-"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
-msgstr ""
-"Ha egy regisztrált nicknevet %d napig nem használnak, akkor\n"
-"a regisztrációja elévül, a nicknevet bárki regisztrálhatja,\n"
-"és használhatja."
-
-#, fuzzy
-msgid ""
-" \n"
-"Available commands are:"
-msgstr "Nincs ezzel kapcsolatban segítség: %s."
-
-#, c-format
-msgid ""
-" \n"
-"Bot will join a channel whenever there is at least\n"
-"%d user(s) on it."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Enables or disables fantasy mode on a channel.\n"
-"When it is enabled, users will be able to use\n"
-"fantasy commands on a channel when prefixed\n"
-"with one of the following fantasy characters: %s\n"
-" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
-msgstr ""
-"Syntax: SET #szoba FANTASY { ON|OFF }\n"
-"\n"
-"Engedélyezi vagy tiltja fantasy módot a csatornán.\n"
-"Ha engedélyezve van, akkor a következő parancsok\n"
-"használhatók a csatornán: !op, !deop, !voice, !devoice,\n"
-"!kick, !kb, !unban, !seen (találd ki hogyan kell\n"
-"használni őket; próbáld meg nick megadásával, a nélkül\n"
-"is)\n"
-"\n"
-"Azoknak akik ezeket a parancsokat akarják használni\n"
-"rendelkezniük KELL a szükség szinttel mind a FANTASIA\n"
-"mind pedig az egyéb szintekkel, ami a parancshoz\n"
-"szükséges. (például, az !op használatához, meg kell\n"
-"legyen a megfelelő szintjük az OPDEOP parancsokhoz.)."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables greet mode on a channel.\n"
-"When it is enabled, the bot will display greet\n"
-"messages of users joining the channel, provided\n"
-"they have enough access to the channel."
-msgstr ""
-"Syntax: SET #szoba GREET { ON|OFF }\n"
-"\n"
-"Engedélyezi vagy tiltja Köszöntő módot a csatornán.\n"
-"Ha engedélyezve van, akkor a bot megjeleníti azoknak\n"
-"a köszöntő üzenetét, akiknek a szintjük megfelelő ehhez."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables ops protection mode on a channel.\n"
-"When it is enabled, ops won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
-msgstr ""
-"Syntax: SET #szoba DONTKICKOPS {ON|OFF}\n"
-"\n"
-"Engedélyezi vagy tiltja opok védelmét a csatornán.\n"
-"Ha engedélyezve van, akkor az opokat nem fogja a bot\n"
-"kirúgni, akkor se, ha nem egyeznek meg a NOKICK szinttel\n"
-"\t"
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables voices protection mode on a channel.\n"
-"When it is enabled, voices won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
-msgstr ""
-"Syntax: SET #szoba DONTKICKVOICES { ON|OFF }\n"
-"\n"
-"Engedélyezi vagy tiltja hangadók védelmét a csatornán.\n"
-"Ha engedélyezve van, akkor a hangadókat nem fogja a bot\n"
-"kirúgni, akkor se, ha nem egyeznek meg a NOKICK szinttel"
-
-#, c-format
-msgid ""
-" \n"
-"Fantasy commands may be prefixed with one of the following characters: %s\n"
-msgstr ""
-
-msgid ""
-" \n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Note that any channel which is not used for %d days\n"
-"(i.e. which no user on the channel's access list enters\n"
-"for that period of time) will be automatically dropped."
-msgstr ""
-"Megjegyzés: azok a csatornák, amelyeket nem használnak %d\n"
-"napig, automatikusan elvesztik regisztrációjukat.\n"
-"Automatikusan dropolásra kerülnek."
-
-#, c-format
-msgid ""
-" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-msgstr ""
-
-#, fuzzy
-msgid ""
-" \n"
-"Services Operators can also drop any nickname without needing\n"
-"to identify for the nick, and may view the access list for\n"
-"any nickname."
-msgstr ""
-"Szervíz adminok is droppolhatnak nickeket, akkor ha\n"
-"beazonosíttotak a nicknevükre, és megnézhetik a nickek\n"
-"hozzáférési listáját. (/msg %s ACCESS LIST nick)"
-
-#, fuzzy
-msgid ""
-" \n"
-"Services Operators can also, depending on their access drop\n"
-"any channel, view (and modify) the access, levels and akick\n"
-"lists and settings for any channel."
-msgstr ""
-" \n"
-"Szervíz adminok tudják droppolni a csatornákat anélkül, \n"
-"hogy a szoba jelszót használnának, és megnézhetika az\n"
-"access, AKICK, és beállitási szint listát a csatornán."
-
-msgid ""
-" \n"
-"Sets the time bot bans expire in. If enabled, any bans placed by\n"
-"bots, such as flood kicker, badwords kicker, etc. will automatically\n"
-"be removed after the given time. Set to 0 to disable bans from\n"
-"automatically expiring."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"The %s ADD command adds the given nickname to the\n"
-"%s list.\n"
-" \n"
-"The %s DEL command removes the given nick from the\n"
-"%s list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The %s LIST command displays the %s list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" %s #channel LIST 2-5,7-9\n"
-" Lists %s entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The %s CLEAR command clears all entries of the\n"
-"%s list."
-msgstr ""
-"Syntax: HOP #szoba ADD nick\n"
-" HOP #szoba DEL { nick | sorszám | lista}\n"
-" HOP #szoba LIST [ maszk | lista ]\n"
-" HOP #szoba CLEAR\n"
-"\n"
-"Karbantartja az HOP (HALFOP) listát a csatornán. A HOP\n"
-"listán szereplő userek automatikusan megkapják belépéskor\n"
-"a féloperátor státuszt.\n"
-"\n"
-"HOP ADD paranccsal hozzáadhatsz egy nickenevet csatornád\n"
-"HOP listájához.\n"
-"\n"
-"HOP DEL paranccsal eltávolíthatsz egy megadott nicknevet\n"
-"a csatornád HOP listájáról. Ha sorszámokat intervallumban\n"
-"adunk meg (lásd a listázásnál),akkor a megadott bejegyzések\n"
-"kerülnek törlésre.\n"
-"\n"
-"Az HOP LIST parancs megadja az HOP listát. Ha nem vagy \n"
-"kiváncsi a teljes listára akkor a listában szereplő HOP \n"
-"sorszámát megadva is megtudhatjuk a nevét, megadhatunk \n"
-"intervallumot is.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tHOP #szoba LIST 2-5,7-9\n"
-"\tListázza az HOP-okat 2 és 5 között és\n"
-"\t7-tol 9-ig.\n"
-" \n"
-"Az HOP CLEAR parancs kiüriti a szoba HOP listáját.\n"
-"\n"
-"Az HOP ADD és HOP DEL parancsokat csak AOP / magasabb\n"
-"szinttel rendelkező userek használhatják,de az HOP CLEAR\n"
-"parancsot csak a szoba foundere adhatja ki.\n"
-"Habár, minden HOP listán szereplo user használhatja az\n"
-"HOP LIST parancsot.\n"
-"\n"
-"Ezt a parancsot letilthatod a csatornádon, és helyette \n"
-"használhatod az access lista rendszert. Nézd meg: /msg \n"
-"%s HELP ACCESS bővebb információért az access listáról,\n"
-"és írd be: /msg %s HELP SET XOP hogy megnézd, hogyan \n"
-"tudsz váltani az xOP rendszerről access lista rendszerre."
-
-#, c-format
-msgid ""
-" \n"
-"The AKICK DEL command removes the given nick or mask\n"
-"from the AutoKick list. It does not, however, remove any\n"
-"bans placed by an AutoKick; those must be removed\n"
-"manually.\n"
-" \n"
-"The AKICK LIST command displays the AutoKick list, or\n"
-"optionally only those AutoKick entries which match the\n"
-"given mask.\n"
-" \n"
-"The AKICK VIEW command is a more verbose version of the\n"
-"AKICK LIST command.\n"
-" \n"
-"The AKICK ENFORCE command causes %s to enforce the\n"
-"current AKICK list by removing those users who match an\n"
-"AKICK mask.\n"
-" \n"
-"The AKICK CLEAR command clears all entries of the\n"
-"akick list."
-msgstr ""
-
-#, fuzzy
-msgid ""
-" \n"
-"The AKILL DEL command removes the given mask from the\n"
-"AKILL list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The AKILL LIST command displays the AKILL list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" AKILL LIST 2-5,7-9\n"
-" Lists AKILL entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"AKILL VIEW is a more verbose version of AKILL LIST, and\n"
-"will show who added an AKILL, the date it was added, and when\n"
-"it expires, as well as the user@host/ip mask and reason.\n"
-" \n"
-"AKILL CLEAR clears all entries of the AKILL list."
-msgstr ""
-"Syntax: HOP #szoba ADD nick\n"
-" HOP #szoba DEL { nick | sorszám | lista}\n"
-" HOP #szoba LIST [ maszk | lista ]\n"
-" HOP #szoba CLEAR\n"
-"\n"
-"Karbantartja az HOP (HALFOP) listát a csatornán. A HOP\n"
-"listán szereplő userek automatikusan megkapják belépéskor\n"
-"a féloperátor státuszt.\n"
-"\n"
-"HOP ADD paranccsal hozzáadhatsz egy nickenevet csatornád\n"
-"HOP listájához.\n"
-"\n"
-"HOP DEL paranccsal eltávolíthatsz egy megadott nicknevet\n"
-"a csatornád HOP listájáról. Ha sorszámokat intervallumban\n"
-"adunk meg (lásd a listázásnál),akkor a megadott bejegyzések\n"
-"kerülnek törlésre.\n"
-"\n"
-"Az HOP LIST parancs megadja az HOP listát. Ha nem vagy \n"
-"kiváncsi a teljes listára akkor a listában szereplő HOP \n"
-"sorszámát megadva is megtudhatjuk a nevét, megadhatunk \n"
-"intervallumot is.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tHOP #szoba LIST 2-5,7-9\n"
-"\tListázza az HOP-okat 2 és 5 között és\n"
-"\t7-tol 9-ig.\n"
-" \n"
-"Az HOP CLEAR parancs kiüriti a szoba HOP listáját.\n"
-"\n"
-"Az HOP ADD és HOP DEL parancsokat csak AOP / magasabb\n"
-"szinttel rendelkező userek használhatják,de az HOP CLEAR\n"
-"parancsot csak a szoba foundere adhatja ki.\n"
-"Habár, minden HOP listán szereplo user használhatja az\n"
-"HOP LIST parancsot.\n"
-"\n"
-"Ezt a parancsot letilthatod a csatornádon, és helyette \n"
-"használhatod az access lista rendszert. Nézd meg: /msg \n"
-"%s HELP ACCESS bővebb információért az access listáról,\n"
-"és írd be: /msg %s HELP SET XOP hogy megnézd, hogyan \n"
-"tudsz váltani az xOP rendszerről access lista rendszerre."
-
-#, fuzzy
-msgid ""
-" \n"
-"The SNLINE DEL command removes the given mask from the\n"
-"SNLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SNLINE LIST command displays the SNLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SNLINE LIST 2-5,7-9\n"
-" Lists SNLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SNLINE VIEW is a more verbose version of SNLINE LIST, and\n"
-"will show who added an SNLINE, the date it was added, and when\n"
-"it expires, as well as the realname mask and reason.\n"
-" \n"
-"SNLINE CLEAR clears all entries of the SNLINE list."
-msgstr ""
-"Syntax: HOP #szoba ADD nick\n"
-" HOP #szoba DEL { nick | sorszám | lista}\n"
-" HOP #szoba LIST [ maszk | lista ]\n"
-" HOP #szoba CLEAR\n"
-"\n"
-"Karbantartja az HOP (HALFOP) listát a csatornán. A HOP\n"
-"listán szereplő userek automatikusan megkapják belépéskor\n"
-"a féloperátor státuszt.\n"
-"\n"
-"HOP ADD paranccsal hozzáadhatsz egy nickenevet csatornád\n"
-"HOP listájához.\n"
-"\n"
-"HOP DEL paranccsal eltávolíthatsz egy megadott nicknevet\n"
-"a csatornád HOP listájáról. Ha sorszámokat intervallumban\n"
-"adunk meg (lásd a listázásnál),akkor a megadott bejegyzések\n"
-"kerülnek törlésre.\n"
-"\n"
-"Az HOP LIST parancs megadja az HOP listát. Ha nem vagy \n"
-"kiváncsi a teljes listára akkor a listában szereplő HOP \n"
-"sorszámát megadva is megtudhatjuk a nevét, megadhatunk \n"
-"intervallumot is.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tHOP #szoba LIST 2-5,7-9\n"
-"\tListázza az HOP-okat 2 és 5 között és\n"
-"\t7-tol 9-ig.\n"
-" \n"
-"Az HOP CLEAR parancs kiüriti a szoba HOP listáját.\n"
-"\n"
-"Az HOP ADD és HOP DEL parancsokat csak AOP / magasabb\n"
-"szinttel rendelkező userek használhatják,de az HOP CLEAR\n"
-"parancsot csak a szoba foundere adhatja ki.\n"
-"Habár, minden HOP listán szereplo user használhatja az\n"
-"HOP LIST parancsot.\n"
-"\n"
-"Ezt a parancsot letilthatod a csatornádon, és helyette \n"
-"használhatod az access lista rendszert. Nézd meg: /msg \n"
-"%s HELP ACCESS bővebb információért az access listáról,\n"
-"és írd be: /msg %s HELP SET XOP hogy megnézd, hogyan \n"
-"tudsz váltani az xOP rendszerről access lista rendszerre."
-
-#, fuzzy
-msgid ""
-" \n"
-"The SQLINE DEL command removes the given mask from the\n"
-"SQLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SQLINE LIST command displays the SQLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SQLINE LIST 2-5,7-9\n"
-" Lists SQLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SQLINE VIEW is a more verbose version of SQLINE LIST, and\n"
-"will show who added an SQLINE, the date it was added, and when\n"
-"it expires, as well as the mask and reason.\n"
-" \n"
-"SQLINE CLEAR clears all entries of the SQLINE list."
-msgstr ""
-"Syntax: HOP #szoba ADD nick\n"
-" HOP #szoba DEL { nick | sorszám | lista}\n"
-" HOP #szoba LIST [ maszk | lista ]\n"
-" HOP #szoba CLEAR\n"
-"\n"
-"Karbantartja az HOP (HALFOP) listát a csatornán. A HOP\n"
-"listán szereplő userek automatikusan megkapják belépéskor\n"
-"a féloperátor státuszt.\n"
-"\n"
-"HOP ADD paranccsal hozzáadhatsz egy nickenevet csatornád\n"
-"HOP listájához.\n"
-"\n"
-"HOP DEL paranccsal eltávolíthatsz egy megadott nicknevet\n"
-"a csatornád HOP listájáról. Ha sorszámokat intervallumban\n"
-"adunk meg (lásd a listázásnál),akkor a megadott bejegyzések\n"
-"kerülnek törlésre.\n"
-"\n"
-"Az HOP LIST parancs megadja az HOP listát. Ha nem vagy \n"
-"kiváncsi a teljes listára akkor a listában szereplő HOP \n"
-"sorszámát megadva is megtudhatjuk a nevét, megadhatunk \n"
-"intervallumot is.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tHOP #szoba LIST 2-5,7-9\n"
-"\tListázza az HOP-okat 2 és 5 között és\n"
-"\t7-tol 9-ig.\n"
-" \n"
-"Az HOP CLEAR parancs kiüriti a szoba HOP listáját.\n"
-"\n"
-"Az HOP ADD és HOP DEL parancsokat csak AOP / magasabb\n"
-"szinttel rendelkező userek használhatják,de az HOP CLEAR\n"
-"parancsot csak a szoba foundere adhatja ki.\n"
-"Habár, minden HOP listán szereplo user használhatja az\n"
-"HOP LIST parancsot.\n"
-"\n"
-"Ezt a parancsot letilthatod a csatornádon, és helyette \n"
-"használhatod az access lista rendszert. Nézd meg: /msg \n"
-"%s HELP ACCESS bővebb információért az access listáról,\n"
-"és írd be: /msg %s HELP SET XOP hogy megnézd, hogyan \n"
-"tudsz váltani az xOP rendszerről access lista rendszerre."
-
-#, fuzzy
-msgid ""
-" \n"
-"This option makes a channel unassignable. If a bot\n"
-"is already assigned to the channel, it is unassigned\n"
-"automatically when you enable it."
-msgstr ""
-"Syntax: SET #szoba NOBOT {ON|OFF}\n"
-"\n"
-"Ez az opció a botot szobához társíthatatlanná teszi.\n"
-"Ha egy bot már társítva van egy csatornához\n"
-"akkor törlödik onnan, ha ezt az opciót bekapcsolod.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-#, fuzzy
-msgid ""
-" \n"
-"This option prevents a bot from being assigned to a\n"
-"channel by users that aren't IRC Operators."
-msgstr ""
-"Syntax: SET bot-nick PRIVATE {ON|OFF}\n"
-"\n"
-"Ez az opció megelőzi, hogy az adott botot a csatornához\n"
-"nem IRC operátor személyek társíthassák.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-#, c-format
-msgid ""
-" \n"
-"Type %s%s HELP command for help on any of the\n"
-"above commands."
-msgstr ""
-
-#, c-format
-msgid " %s is online using this oper block."
-msgstr ""
-
-#, c-format
-msgid " Command %s on %s is linked to %s"
-msgstr ""
-
-#, fuzzy, c-format
-msgid " Providing service: %s"
-msgstr "Modul parancsai: /msg %s %s"
-
-msgid " This oper is configured in the configuration file."
-msgstr ""
-
-#, c-format
-msgid " Loaded at: %p"
-msgstr ""
-
-#, c-format
-msgid " but %s mysteriously dematerialized."
-msgstr ""
-
-#, c-format
-msgid ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-
-#, fuzzy
-msgid "\"Jupiter\" a server"
-msgstr " JUPE Létrehoz egy \"Jupiter\" álszervert."
-
-#, fuzzy, c-format
-msgid "%-8s %s"
-msgstr "%-20s %s@%s"
-
-#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
-
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr ""
-
-#, c-format
-msgid "%c is an unknown status mode."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%c%c is not locked on %s."
-msgstr "%s nem kért értesítést az üzeneteiről."
-
-#, fuzzy, c-format
-msgid "%c%c%s has been unlocked from %s."
-msgstr "Nick %s has been ungrouped from %s."
-
-#, fuzzy, c-format
-msgid "%d access entries from %s have been cloned to %s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s lett"
-
-#, c-format
-msgid "%d bots available."
-msgstr "%d botok rendelkezésre állnak."
-
-#, fuzzy, c-format
-msgid "%d modules loaded."
-msgstr "%d Modul betöltve."
-
-#, fuzzy, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nicknév van a csoportban."
-
-#, c-format
-msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s %s list is empty."
-msgstr "%s AOP listája üres."
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban)"
-msgstr "\tFélkövér betűkért kirúgás: %s (%d kirúgás után kitiltás)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; %d lines in %ds)"
-msgstr "\tFloodért kirúgás: %s (%d kirúgás után kitiltás; %d sor %ds mp alatt)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; %d times)"
-msgstr "\tIsmétlésért kirúgás: %s (%d kirúgás után kitiltás; %d időre)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; minimum %d/%d%%)"
-msgstr "\tCaps Lockért kirúgás: %s (%d kirúgás után kitiltás; min. %d/%d%%)"
-
-#, fuzzy, c-format
-msgid "%s (%d lines in %ds)"
-msgstr " %s (expires in %s)"
-
-#, c-format
-msgid "%s (%d times)"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was kicked from %s (\"%s\") %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was kicked from a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen changing nick from %s to %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen changing nick to %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen connecting %s ago (%s)%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen joining %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen joining a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen parting %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen parting a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s (minimum %d/%d%%)"
-msgstr "\tCaps Lockért kirúgás: %s (minimum %d/%d%%)"
-
-#, c-format
-msgid "%s access list is empty."
-msgstr "%s hozzáférési listája üres."
-
-#, fuzzy, c-format
-msgid "%s added to %s's auto join list."
-msgstr "%s hozzáadva a (%s) csatorna autokick listájához"
-
-#, fuzzy, c-format
-msgid "%s already exists."
-msgstr "%s nevű bot már létezik."
-
-#, c-format
-msgid "%s autokick list is empty."
-msgstr "%s autokick listája üres."
-
-#, c-format
-msgid "%s bad words list is empty."
-msgstr "%s tiltott szavak listája üres."
-
-#, fuzzy, c-format
-msgid "%s cannot be the successor on channel %s as they are the founder."
-msgstr "%s nem lehet a %s csatorna successora, mert ő a founder is."
-
-#, c-format
-msgid "%s commands:"
-msgstr "%s parancsok:"
-
-#, c-format
-msgid "%s coverage is too wide; Please use a more specific mask."
-msgstr ""
-
-#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s számára %d üzenet érkezett, ebből %d olvasatlan."
-
-#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s számára %d üzenet érkezett, ebből 1 olvasatlan."
-
-#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s számára %d üzenet érkezett."
-
-#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s számára %d üzenet érkezett, és mind olvasatlan."
-
-#, c-format
-msgid "%s currently has 1 memo, and it has not yet been read."
-msgstr "%s listáján van 1 olvasatlan üzenet."
-
-#, c-format
-msgid "%s currently has 1 memo."
-msgstr "%s listáján van 1 üzenet."
-
-#, c-format
-msgid "%s currently has no memos."
-msgstr "%s üzenetlistája üres."
-
-#, fuzzy, c-format
-msgid "%s deleted from the %s forbid list."
-msgstr "A %s szó törölve %s tiltott szavak listájából."
-
-#, fuzzy, c-format
-msgid "%s for %s set to %s."
-msgstr "%s vhostja erre változott: %s."
-
-#, fuzzy, c-format
-msgid "%s for %s unset."
-msgstr "A megadott csatorna %s successora törölve."
-
-#, c-format
-msgid "%s had an invalid key specified, and was thus ignored."
-msgstr ""
-
-#, c-format
-msgid "%s has no memo limit."
-msgstr "%s korlátlan számú üzenetet fogadhat."
-
-#, fuzzy, c-format
-msgid "%s has no memos."
-msgstr "%s korlátlan számú üzenetet fogadhat."
-
-#, fuzzy, c-format
-msgid "%s has no new memos."
-msgstr "%s korlátlan számú üzenetet fogadhat."
-
-#, c-format
-msgid "%s is %s"
-msgstr "%s az %s"
-
-#, fuzzy, c-format
-msgid "%s is a Services Operator of type %s."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy, c-format
-msgid "%s is a client on services."
-msgstr "%s jelenleg online."
-
-#, fuzzy, c-format
-msgid "%s is a network service."
-msgstr "%s jelenleg online."
-
-#, fuzzy, c-format
-msgid "%s is already covered by %s."
-msgstr "%s van már %s ilyen bejegyzés."
-
-#, fuzzy, c-format
-msgid "%s is already on %s's auto join list."
-msgstr "%s hozzáadva a hozzáférési listádhoz."
-
-#, fuzzy, c-format
-msgid "%s is an unconfirmed nickname."
-msgstr "Ez a nicknév nem fog elévülni."
-
-#, c-format
-msgid ""
-"%s is another way to modify the channel access list, similar to\n"
-"the XOP and ACCESS methods."
-msgstr ""
-
-#, c-format
-msgid "%s is currently online."
-msgstr "%s jelenleg online."
-
-#, c-format
-msgid "%s is disabled"
-msgstr "%s is disabled"
-
-#, c-format
-msgid "%s is enabled"
-msgstr "%s is enable"
-
-#, fuzzy, c-format
-msgid "%s is not a valid IP address."
-msgstr "%s nem érvényes ban típus."
-
-#, fuzzy, c-format
-msgid "%s is not a valid command."
-msgstr "%s nem érvényes ban típus."
-
-#, fuzzy, c-format
-msgid "%s is not a valid logging method."
-msgstr "%s nem érvényes ban típus."
-
-#, c-format
-msgid "%s is not notified of new memos."
-msgstr "%s nem kért értesítést az üzeneteiről."
-
-#, c-format
-msgid "%s is notified of new memos at logon and when they arrive."
-msgstr "%s értesítést kért csatlakozáskor,és ha új üzenete van,"
-
-#, c-format
-msgid "%s is notified of new memos at logon."
-msgstr "%s kérte, csatlakozáskor értesítést kapjon,üzeneteiről."
-
-#, c-format
-msgid "%s is notified when new memos arrive."
-msgstr "%s értesítést kért, ha új üzenete érkezik."
-
-#, c-format
-msgid "%s is on the channel right now (as %s)!"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s is on the channel right now!"
-msgstr "%s letiltva a (%s) csatornán."
-
-#, fuzzy, c-format
-msgid "%s list for %s"
-msgstr "%s hozzáférési listája:"
-
-#, fuzzy, c-format
-msgid "%s list is empty."
-msgstr "%s AOP listája üres."
-
-#, fuzzy, c-format
-msgid "%s locked on %s."
-msgstr "%s nem kért értesítést az üzeneteiről."
-
-#, fuzzy, c-format
-msgid "%s not found."
-msgstr "%s nem találatható a %s AOP listán."
-
-#, c-format
-msgid "%s settings:"
-msgstr ""
-
-#, c-format
-msgid "%s was last seen here %s ago."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s was not found on %s's auto join list."
-msgstr "%s nem szerepel a (%s) csatorna autokick listáján."
-
-#, fuzzy, c-format
-msgid "%s was removed from %s's auto join list."
-msgstr "%s törölve a (%s) csatorna autokick listájáról."
-
-#, c-format
-msgid "%s will not send you any notification of memos."
-msgstr "%s mostmár nem fog értestíteni, ha új üzeneted érkezik."
-
-#, c-format
-msgid "%s will now notify you of memos when they are sent to you."
-msgstr "%s mostmár értesíteni fog, ha új üzeneted érkezik."
-
-#, c-format
-msgid ""
-"%s will now notify you of memos when you log on and when they are sent to "
-"you."
-msgstr "%s értesíteni fog az üzenetekről csatlakozáskor."
-
-#, c-format
-msgid "%s will now notify you of memos when you log on or unset /AWAY."
-msgstr "%s értesít az üzenetekről csatlakozáskor/AWAY OFF-kor."
-
-#, c-format
-msgid "%s!%s@%s (%s) added to the bot list."
-msgstr "%s!%s@%s (%s) hozzáadva a bot listához."
-
-#, fuzzy, c-format
-msgid "%s's access list is empty."
-msgstr "%s hozzáférési listája üres."
-
-#, fuzzy, c-format
-msgid "%s's auto join list is empty."
-msgstr "%s autokick listája üres."
-
-#, fuzzy, c-format
-msgid "%s's auto join list:"
-msgstr " AKICK AutoKirúgás listára teheted a \"rossz\" usereket"
-
-#, fuzzy, c-format
-msgid "%s's certificate list is empty."
-msgstr "Your access list is empty."
-
-#, c-format
-msgid "%s's memo limit is %d, and may not be changed."
-msgstr "%s max. fogadható üzenteinek száma: %d, és ez fix érték."
-
-#, c-format
-msgid "%s's memo limit is %d."
-msgstr "%s maximálisan fogadható üzeneteinek száma: %d."
-
-#, c-format
-msgid "(%s ago)"
-msgstr ""
-
-#, c-format
-msgid "(%s from now)"
-msgstr ""
-
-msgid "(Split)"
-msgstr ""
-
-#, c-format
-msgid "(by %s on %s) %s"
-msgstr ""
-
-#, fuzzy
-msgid "(disabled)"
-msgstr "%s is enable"
-
-msgid "(founder only)"
-msgstr ""
-
-msgid "(now)"
-msgstr ""
-
-msgid "* AKILL any new clients connecting"
-msgstr "* AKILL minden új kliensre csatlakozáskor."
-
-#, fuzzy, c-format
-msgid "* Force channel modes (%s) to be set on all channels"
-msgstr "* Beállítja a következő módokat: (%s) az összes csatornán."
-
-#, fuzzy
-msgid "* Ignore non-opers with a message"
-msgstr "* Mellőzve minden nem operátortól jövő üzenet"
-
-#, fuzzy
-msgid "* Kill any new clients connecting"
-msgstr "* Killelve lesz minden új felhasználó csatlakozásnál. "
-
-#, fuzzy
-msgid "* No mode lock changes"
-msgstr "* Nincs MLOCK módosítás"
-
-msgid "* No new channel registrations"
-msgstr "* Nem lehet új csatornát regisztrálni."
-
-msgid "* No new memos sent"
-msgstr "* Nem lehet új memot küldeni"
-
-msgid "* No new nick registrations"
-msgstr "* Nem lehet új nicket regisztrálni."
-
-msgid "* Silently ignore non-opers"
-msgstr "* Csendes mellőzés, csak operátorok"
-
-#, c-format
-msgid "* Use the reduced session limit of %d"
-msgstr "* Használva a csökkentett session korlát: %d."
-
-#, c-format
-msgid ", but %s mysteriously dematerialized."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ". %s is still online."
-msgstr "%s jelenleg online."
-
-msgid "<unknown>"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"A confirmation e-mail has been sent to %s. Follow the instructions in it to "
-"change your e-mail address."
-msgstr ""
-"A kód a %s címre lett küldve, írd be /msg %s confirm <kód> a regisztráció "
-"befejezéséhez."
-
-msgid "A massmemo has been sent to all registered users."
-msgstr "Egy massmemo elküldve minden regisztrált felhasználónak."
-
-msgid ""
-"A memo informing the user will also be sent, which includes the reason for "
-"the rejection if supplied."
-msgstr ""
-
-msgid "A memo informing the user will also be sent."
-msgstr ""
-
-#, c-format
-msgid ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
-msgstr ""
-"Az értesítő üzenet %s részére el lett küldve, informálva\n"
-"őt arról, hogy elolvastad a memoját."
-
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr ""
-
-msgid "A vHost must be in the format of a valid hostname."
-msgstr ""
-
-#, fuzzy
-msgid "ADD expiry {nick|mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-msgid "ADD oper type"
-msgstr ""
-
-#, fuzzy
-msgid "ADD target info"
-msgstr "GROUP célnick jelszó"
-
-msgid "ADD text"
-msgstr ""
-
-#, fuzzy
-msgid "ADD [+expiry] mask limit reason"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-#, fuzzy
-msgid "ADD [nickname] channel [key]"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-#, fuzzy
-msgid "ADD [nickname] mask"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-#, fuzzy
-msgid "ADD [nickname] [fingerprint]"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "ADD [+expiry] mask reason"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-#, fuzzy
-msgid "ADD [+expiry] mask:reason"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-#, fuzzy
-msgid "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiry] entry reason"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-msgid "ADDIP server.name ip"
-msgstr ""
-
-msgid "ADDSERVER server.name [zone.name]"
-msgstr ""
-
-msgid "ADDZONE zone.name"
-msgstr ""
-
-#, c-format
-msgid "AKICK ENFORCE for %s complete; %d users were affected."
-msgstr ""
-"Az AKICK ENFORCE a(z) %s csatornán teljesítve;\n"
-"%d user eltávolítva."
-
-#, fuzzy
-msgid "AKILL all users on a specific channel"
-msgstr " CHANKILL AKILL az összes usert a csatornáról"
-
-msgid "AKILL list is empty."
-msgstr "AKILL lista üres."
-
-#, fuzzy
-msgid "AMSG kicker"
-msgstr "\tCaps Lockért kirúgás : %s"
-
-#, fuzzy
-msgid "Access"
-msgstr "Hozzáférési lista:"
-
-#, fuzzy
-msgid "Access denied."
-msgstr "Hozzáférési lista:"
-
-#, fuzzy, c-format
-msgid "Access for %s on %s:"
-msgstr "%s hozzáférése a (%s) csatornán változott: %d."
-
-#, fuzzy, c-format
-msgid "Access level must be between %d and %d inclusive."
-msgstr "A szintnek kizárólag %d és %d között kell lennie."
-
-msgid "Access level must be non-zero."
-msgstr "A hozzáférési szint nem lehet nulla."
-
-#, c-format
-msgid "Access level settings for channel %s:"
-msgstr "%s hozzáférési szintjeinek beállításai:"
-
-#, c-format
-msgid "Access levels for %s reset to defaults."
-msgstr "%s szintjei visszaállítva az alapértékekre."
-
-#, fuzzy, c-format
-msgid "Access list for %s:"
-msgstr "%s hozzáférési listája:"
-
-#, c-format
-msgid ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-msgstr ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-
-#, c-format
-msgid ""
-"Account %s has already reached the maximum number of simultaneous logins "
-"(%u)."
-msgstr ""
-
-#, fuzzy
-msgid "Activate security features"
-msgstr " SECURE Aktiválja a %s biztonsági lehetőségeit"
-
-msgid "Activate the requested vHost for the given nick."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Activates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see the vhost instead of your real host/IP address."
-msgstr ""
-"Syntax: ON\n"
-"Aktiválja a vhostodat, ami a nickhez lett társítva.\n"
-"Ha valaki csinál egy /whois parancsot a nickeden,\n"
-"akkor a vhostodat fogja látni a valódi IP címed vagy\n"
-"hosztneved helyett."
-
-#, fuzzy
-msgid "Activates your assigned vhost"
-msgstr " ON Aktiválja a társított vhostot"
-
-msgid ""
-"Add or delete oper information for a given nick or channel.\n"
-"This will show to opers in the respective info command for\n"
-"the nick or channel."
-msgstr ""
-
-#, c-format
-msgid "Added IP %s to %s."
-msgstr ""
-
-#, c-format
-msgid "Added a forbid on %s of type %s to expire on %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Added info to %s."
-msgstr "Üzenet elküldve %s részére."
-
-#, fuzzy
-msgid "Added new logon news item."
-msgstr "Hozzáadva az új fellépési hír: (#%d)."
-
-#, fuzzy
-msgid "Added new oper news item."
-msgstr "Hozzáadva az új oper hír:(#%d)."
-
-#, fuzzy
-msgid "Added new random news item."
-msgstr "Hozzáadva az új random news tétel (#%d)."
-
-#, fuzzy, c-format
-msgid "Added server %s."
-msgstr "Uplink server: %s"
-
-#, c-format
-msgid "Added zone %s."
-msgstr ""
-
-msgid ""
-"Adding, deleting, or clearing entry messages requires the\n"
-"SET permission."
-msgstr ""
-
-msgid ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
-msgstr ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
-
-#, c-format
-msgid ""
-"Additionally, if fantasy is enabled fantasy commands\n"
-"can be executed by prefixing the command name with\n"
-"one of the following characters: %s"
-msgstr ""
-
-#, c-format
-msgid "All O:lines of %s have been reset."
-msgstr "Összes O:lines %s újra aktív."
-
-#, fuzzy, c-format
-msgid "All akick entries from %s have been cloned to %s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s lett"
-
-#, fuzzy, c-format
-msgid "All available commands for %s:"
-msgstr "Nincs ezzel kapcsolatban segítség: %s."
-
-#, fuzzy, c-format
-msgid "All badword entries from %s have been cloned to %s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s lett"
-
-#, fuzzy, c-format
-msgid "All level entries from %s have been cloned into %s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s lett"
-
-msgid "All logon news items deleted."
-msgstr "Összes fellépési hír tétel törölve."
-
-#, c-format
-msgid "All memos for channel %s have been deleted."
-msgstr "Minden üzenetet töröltem a %s csatornán."
-
-#, c-format
-msgid "All modes cleared on %s."
-msgstr ""
-
-msgid ""
-"All new accounts must be validated by an administrator. Please wait for your "
-"registration to be confirmed."
-msgstr ""
-
-msgid "All of your memos have been deleted."
-msgstr "Minden üzenetet töröltem."
-
-msgid "All oper news items deleted."
-msgstr "Összes oper hír törölve."
-
-#, fuzzy, c-format
-msgid "All operators from %s have been removed."
-msgstr "Összes O:lines %s módosítva."
-
-msgid "All random news items deleted."
-msgstr "Összes random news tétel törölve."
-
-#, fuzzy, c-format
-msgid "All settings from %s have been cloned to %s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s lett"
-
-#, fuzzy, c-format
-msgid "All user modes on %s have been synced."
-msgstr "Összes O:lines %s újra aktív."
-
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s lett"
-
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "Az összes user vhosztja a(z) %s csoportba %s@%s lett"
-
-msgid "Allowed to (de)halfop him/herself"
-msgstr ""
-
-msgid "Allowed to (de)halfop users"
-msgstr ""
-
-msgid "Allowed to (de)op him/herself"
-msgstr ""
-
-msgid "Allowed to (de)op users"
-msgstr ""
-
-msgid "Allowed to (de)owner him/herself"
-msgstr ""
-
-msgid "Allowed to (de)owner users"
-msgstr ""
-
-msgid "Allowed to (de)protect him/herself"
-msgstr ""
-
-msgid "Allowed to (de)protect users"
-msgstr ""
-
-msgid "Allowed to (de)voice him/herself"
-msgstr ""
-
-msgid "Allowed to (de)voice users"
-msgstr ""
-
-msgid "Allowed to assign/unassign a bot"
-msgstr ""
-
-msgid "Allowed to ban users"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to change channel topics"
-msgstr "%s váltóztatott a módodon."
-
-msgid "Allowed to get full INFO output"
-msgstr ""
-
-msgid "Allowed to issue commands restricted to channel founders"
-msgstr ""
-
-msgid "Allowed to modify channel badwords list"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to modify the access list"
-msgstr "%s törölve lett a (%s) csatorna hozzáférési listájáról."
-
-msgid "Allowed to read channel memos"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to set channel settings"
-msgstr "* Nem lehet új csatornát regisztrálni."
-
-msgid "Allowed to unban users"
-msgstr ""
-
-msgid "Allowed to use GETKEY command"
-msgstr ""
-
-msgid "Allowed to use SAY and ACT commands"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to use fantasy commands"
-msgstr " PEACE Szabályozza a kritikus parancsok használatát"
-
-#, fuzzy
-msgid "Allowed to use the AKICK command"
-msgstr "You cannot use this command."
-
-msgid "Allowed to use the INVITE command"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to use the KICK command"
-msgstr "You cannot use this command."
-
-#, fuzzy
-msgid "Allowed to use the MODE command"
-msgstr "You cannot use this command."
-
-#, fuzzy
-msgid "Allowed to view the access list"
-msgstr "%s törölve lett a (%s) csatorna hozzáférési listájáról."
-
-#, fuzzy, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
-msgstr ""
-"Syntax: GLOBAL üzenet\n"
-"\n"
-"Megengedi, hogy az IRCopok üzenetet küldjenek az összes \n"
-"felhasználónak a hálózaton. Üzenetet a %s nickről küldi."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to change modes for any channel.\n"
-"Parameters are the same as for the standard /MODE command.\n"
-"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
-"If CLEAR ALL is given then all modes, including user status, is removed."
-msgstr ""
-"Syntax: MODE #szoba módok\n"
-"\n"
-"Megengedi a szervíz operátornak, hogy szoba módokat \n"
-"állítson. Parameterek ugyanazok mint a szabvány\n"
-"/MODE parancsnál\n"
-"\t\n"
-"Korlátozva Szervíz operatornak."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to change modes for any user.\n"
-"Parameters are the same as for the standard /MODE command."
-msgstr ""
-"Syntax: MODE #szoba módok\n"
-"\n"
-"Megengedi a szervíz operátornak, hogy szoba módokat \n"
-"állítson. Parameterek ugyanazok mint a szabvány\n"
-"/MODE parancsnál\n"
-"\t\n"
-"Korlátozva Szervíz operatornak."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to create, modify, and delete\n"
-"bots that users will be able to use on their own\n"
-"channels.\n"
-" \n"
-"BOT ADD adds a bot with the given nickname, username,\n"
-"hostname and realname. Since no integrity checks are done\n"
-"for these settings, be really careful.\n"
-" \n"
-"BOT CHANGE allows you to change the nickname, username, hostname\n"
-"or realname of a bot without deleting it (and\n"
-"all the data associated with it).\n"
-" \n"
-"BOT DEL removes the given bot from the bot list.\n"
-" \n"
-"Note: You cannot create a bot with a nick that is\n"
-"currently registered. If an unregistered user is currently\n"
-"using the nick, they will be killed."
-msgstr ""
-"Syntax:\tBOT ADD nick user hoszt valós\n"
-"\t\tBOT CHANGE réginick újnick [user [ hoszt [ valós ]]]\n"
-"\t\tBOT DEL nick\n"
-"\n"
-"Lehetővé teszi a Services Operatoroknak, hogy létrehozzanak\n"
-"töröljenek, módosítsanak botokat, amiket a userek\n"
-"használhatnak a csatornáikon.\n"
-"\n"
-"BOT ADD hozzáad egy botot a megadott nick, usernév,\n"
-"hostnév és valósnév használatával. Amióta nincs ellenőrzés\n"
-"kérlek óvatósan használd ezt a parancsot.\n"
-"BOT CHANGE megváltoztatja egy bot nickjét, usernevét,\n"
-"hostnevét, valósnevét, anélkül hogy törölni kellene\n"
-"(minden adat, beállítás megmarad benne.)\n"
-"BOT DEL törli a megadott botot a listából. \n"
-"\n"
-"Megjegyzés: ha létrehozol egy botot, egy már regisztrált\n"
-"nickkel, akkor a nick dropolva lesz. Akkor is, ha a user\n"
-"éppen használja a nicket; killelve lesz."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Syntax: OLINE user flagek\n"
-"\n"
-"Lehetőséget ad a szervíz adminnak, hogy egy usernek \n"
-"operflaget adjon. Előjelként \"+\" vagy \"-\" adható meg.\n"
-"Ha csak a \"-\" paraméter adod meg akkor mindent eltávolít."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes,\n"
-"h for hours and d for days.\n"
-"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format nick!user@host,\n"
-"everything else will be considered a nick. Wildcards are permitted.\n"
-" \n"
-"Ignores will not be enforced on IRC Operators."
-msgstr ""
-"Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask]\n"
-"\n"
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes, \n"
-"h for hours and d for days. \n"
-"Combinations of these units are not permitted. To make\n"
-"Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format user@host\n"
-"or nick!user@host, everything else will be considered a nick.\n"
-"Wildcards are permitted.\n"
-"\n"
-"Ignores will not be enforced on IRC Operators.\n"
-"\t"
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
-"will issue a KILL for that user and, on supported server\n"
-"types, will instruct all servers to add a ban for the mask\n"
-"which the user matched.\n"
-" \n"
-"AKILL ADD adds the given mask to the AKILL\n"
-"list for the given reason, which must be given.\n"
-"Mask should be in the format of nick!user@host#real name,\n"
-"though all that is required is user@host. If a real name is specified,\n"
-"the reason must be prepended with a :.\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an AKILL which does not expire, use +0. If the\n"
-"usermask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current AKILL default expiry time can be found with the\n"
-"STATS AKILL command."
-msgstr ""
-"Syntax: AKILL ADD [ +lejárat] maszk indok\n"
-" AKILL DEL {maszk | sor-szám | list}\n"
-" AKILL LIST [maszk | list]\n"
-" AKILL VIEW [maszk | list]\n"
-" AKILL CLEAR\n"
-"\n"
-"Lehetőséget ad a szervíz opoknak, hogy karbantartsák az\n"
-"AKILL listát. Ha egy felhasználó az AKILL maszkkal egyező\n"
-"cimről próbál csatlakozni , akkor szervíz kiad egy KILL \n"
-"parancsot a nickre, és a támogatott szervertípusokon arra\n"
-"utasít minden szervert, hogy adjon K-linet a maszknak.\n"
-"\n"
-"AKILL ADD hozzáadja a megadott user@host/ip maszkot az\n"
-"AKILL listára a megadott indokkal (amit meg kell adnod).\n"
-"Az elévülést egész számmot kovet egy időparaméter d (nap),\n"
-"h (óra), m (perc).Ezek kombinálása nem lehetséges(1h30m).\n"
-"ha nem adsz meg időegységet akkor önmagában napot jelent.\n"
-"(+30 az 30 napot jelent).Ha +0-át adsz meg akkor nem \n"
-"elévülő lesz.Ha a usermaszk + -al kezdődik akkor elévülést\n"
-"meg kell adni akkor is ha megegyezik az alapértelmezéssel.\n"
-"Az AKILL jelenlegi alapértelmezett elévüólési ideje \n"
-"megnézhető a STATS AKILL paranccsal.\n"
-"AKILL DEL törli a maszkot az AKILL listáról, ha rajta\n"
-"van. Ha bejegyzés sorszámot adsz meg akkor azok fognak\n"
-"törlődni.(lásd a példát alább)\n"
-"AKILL LIST kiirja a jelenlegi AKILL listát. Ha egy \n"
-"\"*\" karakteres maszk van megadva, akkor csak azokat az\n"
-"AKILL-eket listázza, amelyek ráillenek a megadott maszkra.\n"
-"Ha sorszámot adsz meg akkor azok fognak törlődni. Példa:\n"
-"\tAKILL LIST 2-5,7-9\n"
-" Listázza az AKILL-en lévoket 2-től 5-ig és 7-től 9-ig\n"
-" az AKILL listából\n"
-"AKILL VIEW részletesebb verziója az AKILL LIST-nek,\n"
-"amely megmutatja, hogy ki vette fel az AKILL-t,\tmikor lett\n"
-"felvéve és mikor jár le, éppúgy, felhasználó@gazdanév \n"
-"maszkot és indokot.\n"
-"\t\n"
-"AKILL CLEAR töröli az összes AKILL bejegyzést.\n"
-"\n"
-"Korlátozva Szervíz operatornak."
-
-msgid ""
-"Allows Services Operators to manipulate the SNLINE list. If\n"
-"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
-"session."
-msgstr ""
-
-msgid ""
-"Allows Services Operators to manipulate the SQLINE list. If\n"
-"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
-"session.\n"
-"If the first character of the mask is #, services will\n"
-"prevent the use of matching channels. If the mask is a\n"
-"regular expression, the expression will be matched against\n"
-"channels too."
-msgstr ""
-
-msgid ""
-"Allows Services Operators to manipulate the list of hosts that\n"
-"have specific session limits - allowing certain machines,\n"
-"such as shell servers, to carry more than the default number\n"
-"of clients at a time. Once a host reaches its session limit,\n"
-"all clients attempting to connect from that host will be\n"
-"killed. Before the user is killed, they are notified, of a\n"
-"source of help regarding session limiting. The content of\n"
-"this notice is a config setting."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to view the session list.\n"
-" \n"
-"SESSION LIST lists hosts with at least threshold sessions.\n"
-"The threshold must be a number greater than 1. This is to\n"
-"prevent accidental listing of the large number of single\n"
-"session hosts.\n"
-" \n"
-"SESSION VIEW displays detailed information about a specific\n"
-"host - including the current session count and session limit.\n"
-"The host value may not include wildcards.\n"
-" \n"
-"See the EXCEPTION help for more information about session\n"
-"limiting and how to set session limits specific to certain\n"
-"hosts and groups thereof."
-msgstr ""
-"Syntax: SESSION LIST threshold\n"
-" SESSION VIEW host\n"
-"\n"
-"Megengedi a Szervíz adminoknak, hogy megtekintsék a \n"
-"session listát.\n"
-"SESSION LIST kilistázza azokat a hostokat, amelyeknek\n"
-"legalább határértéksessionjuk van. Érték legyen 1-nél\n"
-"nagyobb szám,hogy megelőzze az egy sessionúak kilistázását\n"
-"SESSION VIEWmegjeleníti a host részletes információit,\n"
-"tartalmazva a jelenlegi session számot, session korlátot.\n"
-"A host értéke nem tartalmazhat maszkkaraktereket.\n"
-"\n"
-"Lásd az EXCEPTION helpjét további információért a \n"
-"session-korlátozással és azzal kapcsolatban,hogyan állíts\n"
-"be különleges korlátokat bizonyos hostokra és csoportokra.\n"
-"\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-msgid ""
-"Allows manipulating the topic of the specified channel.\n"
-"The SET command changes the topic of the channel to the given topic\n"
-"or unsets the topic if no topic is given. The APPEND command appends\n"
-"the given topic to the existing topic.\n"
-" \n"
-"LOCK and UNLOCK may be used to enable and disable topic lock. When\n"
-"topic lock is set, the channel topic will be unchangeable by users who do "
-"not have\n"
-"the TOPIC privilege."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Allows staff to kick a user from any channel.\n"
-"Parameters are the same as for the standard /KICK\n"
-"command. The kick message will have the nickname of the\n"
-"IRCop sending the KICK command prepended; for example:\n"
-" \n"
-"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
-msgstr ""
-"Syntax: KICK #szoba user indok\n"
-"\n"
-"Lehetoséget nyújt az IRCopoknak, hogy bármelyik szobából\n"
-"kirúgjanak egy felhasználót. A paraméterek ugyanazok,\n"
-"mint a szabványos /KICK parancsnál. A kirúgási üzenetben\n"
-"benne lesz a KIK parancsot küldő IRCop nickneve; például:\n"
-"\n"
-"***xy ki lett rúgva a #csatornáról %s által.(op(csak))\n"
-"\n"
-"Korlátozva Szervíz operatornak."
-
-#, fuzzy
-msgid ""
-"Allows the channel founder to set various channel options\n"
-"and other information.\n"
-" \n"
-"Available options:"
-msgstr ""
-"Syntax: SET #szoba opció paraméterek\n"
-"\n"
-"Lehetőséget ad a foundernek, hogy a beállításokat\n"
-"és információkat megváltoztassa.\n"
-"\n"
-"Elérhető opciók:"
-
-msgid ""
-"Allows you to change and view Services Operators.\n"
-"Note that operators removed by this command but are still set in\n"
-"the configuration file are not permanently affected by this."
-msgstr ""
-
-msgid ""
-"Allows you to change and view configuration settings.\n"
-"Settings changed by this command are temporary and will not be reflected\n"
-"back into the configuration file, and will be lost if Anope is shut down,\n"
-"restarted, or the configuration is reloaded.\n"
-" \n"
-"Example:\n"
-" MODIFY nickserv forcemail no"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
-msgstr ""
-"Syntax: SASET nickname MSG {ON | OFF}\n"
-"\n"
-"Allows you to choose the way Services are communicating with \n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
-"use notices."
-msgstr ""
-"Syntax: SET MSG {ON | OFF}\n"
-"\n"
-"Lehetőséget nyújt arra, hogy megválaszd azt, hogy a szervíz\n"
-"hogyan kommunikáljon veled.\n"
-"Az MSG beállítással, a szervíz, privát üzeneteket fog\n"
-"használni, egyébként pedig noticeokat."
-
-msgid ""
-"Allows you to ignore users by nick or host from memoing\n"
-"you or a channel. If someone on the memo ignore list tries\n"
-"to memo you or a channel, they will not be told that you have\n"
-"them ignored."
-msgstr ""
-
-msgid ""
-"Allows you to kill a user from the network.\n"
-"Parameters are the same as for the standard /KILL\n"
-"command."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-msgstr ""
-"Syntax: SASET nickname HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), your services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-msgstr ""
-"Syntax: SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Lehetőséget nyújt arra, hogy megelőzd néhány adatnak a\n"
-"szerepelését a %s INFO parancs használatakor .\n"
-"Elrejtheted az E-mail címed (EMAIL), az utoljára használt\n"
-"user@host maszkod (USERMASK), és az utolsó kilépő \n"
-"üzeneted(QUIT).\tA második paraméter meghatározza, hogy \n"
-"az opció ki legyen kapcsolva(OFF)\tvagy el legyen rejtve\n"
-"az információ(ON)."
-
-#, fuzzy, c-format
-msgid "Allows you to see %s information about a channel or a bot"
-msgstr ""
-"INFO Allows you to see BotServ information about a channel or "
-"a bot"
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to see %s information about a channel or a bot.\n"
-"If the parameter is a channel, then you'll get information\n"
-"such as enabled kickers. If the parameter is a nick,\n"
-"you'll get information about a bot, such as creation\n"
-"time or number of channels it is on."
-msgstr ""
-"Syntax: INFO {#szoba | nick}\n"
-"\n"
-"Lehetővé teszi, hogy megnézd a %s információkat egy\n"
-"csatornával vagy bottal kapcsolatban. Ha a paraméter\n"
-"szobanév, akkor megkapod a szobára vonatkozó bot\n"
-"beállításokat. Ha a paraméter nick, akkor a botról\n"
-"kapsz információkat, például létrehozás ideje, csatornák\n"
-"száma."
-
-msgid ""
-"Alternative methods of modifying channel access lists are\n"
-"available."
-msgstr ""
-
-#, fuzzy
-msgid "Approve the requested vHost of a user"
-msgstr " DEL Törli egy felhasználónak a vhostját"
-
-#, fuzzy
-msgid "As a Services Operator, you may drop any nick."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "Assigns a bot to a channel"
-msgstr "ASSIGN Társít egy botot a csatornához"
-
-#, fuzzy
-msgid ""
-"Assigns the specified bot to a channel. You\n"
-"can then configure the bot for the channel so it fits\n"
-"your needs."
-msgstr ""
-"Syntax: ASSIGN #szoba nick\n"
-"\n"
-"Társítja a megnevezett botot a szobához. Beállíthatod a\n"
-"botodat a csatornád igényeidnek megfelelően.\n"
-"Kellemes botozást! :-)"
-
-#, fuzzy
-msgid "Associate a URL with the channel"
-msgstr "ASSIGN Társít egy botot a csatornához"
-
-msgid "Associate a URL with this account"
-msgstr ""
-
-#, fuzzy
-msgid "Associate a URL with your account"
-msgstr " GREET Köszöntő üzenet társítása a nicknevedhez"
-
-#, fuzzy
-msgid "Associate a greet message with your nickname"
-msgstr " GREET Köszöntő üzenet társítása a nicknevedhez"
-
-#, fuzzy
-msgid "Associate an E-mail address with the channel"
-msgstr " EMAIL Egy E-mail cím társítása a nicknevedhez"
-
-#, fuzzy
-msgid "Associate an E-mail address with your nickname"
-msgstr " EMAIL Egy E-mail cím társítása a nicknevedhez"
-
-#, fuzzy
-msgid "Associate oper info with a nick or channel"
-msgstr "ASSIGN Társít egy botot a csatornához"
-
-#, fuzzy
-msgid "Associates the given E-mail address with the nickname."
-msgstr " EMAIL Egy E-mail cím társítása a nicknevedhez"
-
-#, fuzzy
-msgid ""
-"Associates the given E-mail address with your nickname.\n"
-"This address will be displayed whenever someone requests\n"
-"information on the nickname with the INFO command."
-msgstr ""
-"Syntax: SET EMAIL cím\n"
-"\n"
-"Egy E-mail cím társítása a nicknevedhez.\n"
-"Ez az E-mail cím szerepelni fog az INFO-id között,\n"
-"amit bárki lekérhet az INFO paranccsal."
-
-msgid "Auto-op"
-msgstr "Auto-op"
-
-#, c-format
-msgid "Autokick list for %s:"
-msgstr "%s autokick listája:"
-
-msgid "Automatic channel operator status upon join"
-msgstr ""
-
-msgid "Automatic halfop upon join"
-msgstr ""
-
-msgid "Automatic owner upon join"
-msgstr ""
-
-msgid "Automatic protect upon join"
-msgstr ""
-
-msgid "Automatic voice on join"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Available commands for %s:"
-msgstr "Nincs ezzel kapcsolatban segítség: %s."
-
-#, fuzzy
-msgid "Available opertypes:"
-msgstr "Nincs ezzel kapcsolatban segítség: %s."
-
-#, c-format
-msgid "Available privileges for %s:"
-msgstr ""
-
-msgid "BANS enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "Bad words kicker"
-msgstr "\tCsúnya szavakért kirúgás: %s"
-
-#, fuzzy, c-format
-msgid "Bad words list for %s:"
-msgstr "%s hozzáférési listája:"
-
-msgid "Bad words list is now empty."
-msgstr "Tiltott szó lista üres."
-
-msgid "Ban expiry may not be longer than 1 day."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Ban on %s expires in %s."
-msgstr "%s nevű bot már létezik."
-
-msgid "Ban type"
-msgstr ""
-
-#, c-format
-msgid "Ban type for channel %s is now #%d."
-msgstr "A megadott csatorna (%s) új ban típusa: #%d."
-
-#, fuzzy
-msgid "Bans a given nick or mask on a channel"
-msgstr " BAN Bans a selected nick on a channel"
-
-#, fuzzy
-msgid ""
-"Bans a given nick or mask on a channel. An optional expiry may\n"
-"be given to cause services to remove the ban after a set amount\n"
-"of time.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders may ban masks."
-msgstr ""
-"Syntax: BAN #szoba nick [indok]\n"
-"\n"
-"Kitilt egy kiválaszott nicket a csatornáról.\n"
-"\n"
-"Alapbeállítás szerint, minimum AOP vagy 5-ös access \n"
-"szinttel kell rendelkezned a csatornán, hogy használhasd."
-
-#, fuzzy, c-format
-msgid "Bans enforced on %s."
-msgstr "%s nem kért értesítést az üzeneteiről."
-
-#, fuzzy
-msgid "Bolds kicker"
-msgstr "\tFélkövér betűkért kirúgás: %s"
-
-#, c-format
-msgid "Bot %s already exists."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy, c-format
-msgid "Bot %s does not exist."
-msgstr "%s nevű bot már létezik."
-
-#, c-format
-msgid "Bot %s has been assigned to %s."
-msgstr "A %s nevű bot társítva a %s szobához."
-
-#, fuzzy, c-format
-msgid "Bot %s has been changed to %s!%s@%s (%s)."
-msgstr "A %s nevű bot megváltoztatva %s!%s@%s (%s)"
-
-#, c-format
-msgid "Bot %s has been deleted."
-msgstr "A %s nevű bot törölve."
-
-#, c-format
-msgid "Bot %s is already assigned to channel %s."
-msgstr "A %s nevű bot már társítva van a %s szobához."
-
-#, c-format
-msgid "Bot will kick ops on channel %s."
-msgstr "A Bot most már opot is kirúg a %s szobából."
-
-#, c-format
-msgid "Bot will kick voices on channel %s."
-msgstr "A Bot most már a hangadókat is kirúgja a %s szobában."
-
-#, c-format
-msgid "Bot won't kick ops on channel %s."
-msgstr "A Bot nem fog opot kirúgni a %s szobából."
-
-#, c-format
-msgid "Bot won't kick voices on channel %s."
-msgstr "A Bot nem fogja a hangadókat kirúgni a %s szobában."
-
-#, fuzzy, c-format
-msgid "Bot %s is not changeable."
-msgstr "Nincs Bot mód most ONa %s szobán."
-
-#, fuzzy, c-format
-msgid "Bot %s is not deletable."
-msgstr "A %s nevű bot törölve."
-
-#, c-format
-msgid "Bot bans will automatically expire after %s."
-msgstr ""
-
-#, fuzzy
-msgid "Bot bans will no longer automatically expire."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Bot Hosts may only contain %d characters."
-
-#, fuzzy
-msgid "Bot hosts may only contain valid host characters."
-msgstr "Bot Hoszt csak érvényes karaktereket tartalmazhat."
-
-#, fuzzy, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Bot Idents may only contain %d characters."
-
-#, fuzzy
-msgid "Bot idents may only contain valid ident characters."
-msgstr "Bot Ident csak érvényes karaktereket tartalmazhat."
-
-#, fuzzy, c-format
-msgid "Bot is not on channel %s."
-msgstr "A Bot most már opot is kirúg a %s szobából."
-
-msgid "Bot list:"
-msgstr "Botok listája:"
-
-msgid "Bot nick"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Bot Idents may only contain %d characters."
-
-#, fuzzy
-msgid "Bot nicks may only contain valid nick characters."
-msgstr "Bot Nick csak érvényes karaktereket tartalmazhat."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for %s, and will place a ban\n"
-"after %d kicks for the same user."
-msgstr ""
-"Bot will now kick italics, and will place a ban after %d\n"
-"kicks for the same user."
-
-#, fuzzy, c-format
-msgid "Bot will now kick for %s."
-msgstr "A Bot kirúgja félkövér betű használat miatt a usert."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message), and will\n"
-"place a ban after %d kicks for the same user."
-msgstr ""
-"Bot most már kirúgja caps lock miatt, (legalább\n"
-"%d karakter és ennek %d%%-a nagybetű), kitiltja \n"
-"%d kirúgás után a usert."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message)."
-msgstr ""
-"Bot most már kirúgja caps lock miatt a usert (legalább\n"
-"%d karakter és ennek %d%%-a nagybetű)."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for flood (%d lines in %d seconds\n"
-"and will place a ban after %d kicks for the same user."
-msgstr ""
-"A Bot kirúgja flood miatt (%d sor %d mp alatt),\n"
-"és kitiltja %d kirúgás után a usert."
-
-#, fuzzy, c-format
-msgid "Bot will now kick for flood (%d lines in %d seconds)."
-msgstr "Bot kirúgja flood miatt a usert. (%d sor %d mp alatt)"
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time), and will place a ban after %d\n"
-"kicks for the same user."
-msgstr ""
-"A Bot kirúgja ismétlés miatt (ha %d alkalommal ismétli\n"
-"ugyanazt a sort), és kitiltja %d kirúgás után a usert."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time)."
-msgstr ""
-"A Bot kirúgja ismétlés miatt a usert (ha %d alkalommal\n"
-"ismétli ugyanazt a sort)."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times), and will place a ban after %d\n"
-"kicks for the same user."
-msgstr ""
-"A Bot kirúgja ismétlés miatt (ha %d alkalommal ismétli\n"
-"ugyanazt a sort), és kitiltja %d kirúgás után a usert."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times)."
-msgstr ""
-"A Bot kirúgja ismétlés miatt a usert (ha %d alkalommal\n"
-"ismétli ugyanazt a sort)."
-
-#, fuzzy, c-format
-msgid "Bot won't kick for %s anymore."
-msgstr "Bot nem fog kirúgni caps lock miatt."
-
-#, fuzzy
-msgid "Bot won't kick for caps anymore."
-msgstr "Bot nem fog kirúgni caps lock miatt."
-
-#, fuzzy
-msgid "Bot won't kick for flood anymore."
-msgstr "A Bot nem fog kirúgni flood miatt."
-
-#, fuzzy
-msgid "Bot won't kick for repeats anymore."
-msgstr "A Bot nem fog kirúgni ismétlés miatt."
-
-msgid "By"
-msgstr ""
-
-msgid "CLEAR target"
-msgstr ""
-
-msgid "CLEAR time"
-msgstr ""
-
-#, fuzzy
-msgid "Cancel the last memo you sent"
-msgstr " CANCEL Visszavonja az utoljára küldött memot"
-
-#, fuzzy
-msgid "Cancel the registration of a channel"
-msgstr " DROP Törölheted a csatornád regisztrációját"
-
-#, fuzzy
-msgid "Cancel the registration of a nickname"
-msgstr " DROP Nicknév regisztrációjának törlése"
-
-#, fuzzy
-msgid ""
-"Cancels the last memo you sent to the given nick or channel,\n"
-"provided it has not been read at the time you use the command."
-msgstr ""
-"Syntax: CANCEL { nick | #szoba }\n"
-"\n"
-"Visszavonja az utolsó memo üzenetet, amit a nicknek\n"
-"vagy csatornának küldtél."
-
-#, fuzzy, c-format
-msgid "Cannot clone channel %s to itself!"
-msgstr "A Bot most már opot is kirúg a %s szobából."
-
-msgid "Cannot send mail now; please retry a little later."
-msgstr "Nem lehet most levelet küldeni; próbáld újra később."
-
-#, fuzzy
-msgid "Caps kicker"
-msgstr "\tCaps Lockért kirúgás : %s"
-
-#, fuzzy
-msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
-"not saved. This command should not be used unless\n"
-"damage to the in-memory copies of the databases is feared\n"
-"and they should not be saved."
-msgstr ""
-"Syntax: QUIT\n"
-"\n"
-"A Szervíz azonnal leáll; az adatbázist nem menti el.\n"
-"Ez a parancs annak elkerülésére hasznos, hogy a memóriában\n"
-"lévő adatok másolata bekerüljön az adatbázisba.\n"
-"Normál leállításokhoz használd kérlek a\n"
-"SHUTDOWN parancsot!\n"
-"\n"
-"Korlátozva Services Operatoroknak."
-
-#, fuzzy
-msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
-"session limitation, etc.)."
-msgstr ""
-"Syntax: RELOAD\n"
-"\n"
-"Újratölti a Szervíz konfigurációs fájlját. Jegyzet: néhány\n"
-"direktívának ettől függetlenül restart kell, hogy hatása\n"
-"életbe lépjen. (Például a Szervíz egységek nicknév váltása \n"
-"vagy session korlátozás aktíválása, stb.)\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-#, fuzzy
-msgid ""
-"Causes Services to save all databases and then restart\n"
-"(i.e. exit and immediately re-run the executable)."
-msgstr ""
-"Syntax: RESTART\n"
-"\n"
-"Menti a Szervíz adatbázisát, majd újraindítja a programot.\n"
-"(Kilép, majd újraindul.)\n"
-"\n"
-"Korlátozva Szervíz adminoknak.\t"
-
-#, fuzzy
-msgid "Causes Services to save all databases and then shut down."
-msgstr ""
-"Syntax: SHUTDOWN\n"
-"\n"
-"Menti a Szervíz adatbázisát, majd leállítja a programot.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-#, fuzzy
-msgid ""
-"Causes Services to update all database files as soon as you\n"
-"send the command."
-msgstr ""
-"Syntax: UPDATE\n"
-"\n"
-"Menti a Szervíz adatbázisát, azonnal amint kiadtad\n"
-"a parancsot.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-#, fuzzy, c-format
-msgid "Certificate list for %s:"
-msgstr "%s hozzáférési listája:"
-
-msgid "ChanServ is required to enable persist on this network."
-msgstr ""
-
-#, fuzzy
-msgid "Change channel modes"
-msgstr "%s váltóztatott a módodon."
-
-#, fuzzy
-msgid "Change the communication method of Services"
-msgstr " MSG Megváltoztatja a szervízzel való kommunikációt"
-
-#, fuzzy
-msgid "Change user modes"
-msgstr "%s váltóztatott a módodon."
-
-#, fuzzy, c-format
-msgid "Changed usermodes of %s to %s."
-msgstr "%s usermódjai megváltoztatva."
-
-#, fuzzy
-msgid ""
-"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
-msgstr ""
-"Syntax: SET DISPLAY új-megjelenítés\n"
-"\n"
-"Megváltoztatja a nicknév csoportod megjelenítését a \n"
-"szervízben.\tAz új megjelenítésnek a csoport egyik\n"
-"nickjének KELL lennie."
-
-#, fuzzy
-msgid ""
-"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
-msgstr ""
-"Syntax: SET DISPLAY új-megjelenítés\n"
-"\n"
-"Megváltoztatja a nicknév csoportod megjelenítését a \n"
-"szervízben.\tAz új megjelenítésnek a csoport egyik\n"
-"nickjének KELL lennie."
-
-#, fuzzy
-msgid ""
-"Changes the founder of a channel. The new nickname must\n"
-"be a registered one."
-msgstr ""
-"Syntax: %s #szoba FOUNDER nick\n"
-"\n"
-"Megváltoztatja a szoba founderjét.\n"
-"Az új nicknév regisztrált kell hogy legyen!"
-
-#, fuzzy
-msgid ""
-"Changes the language Services uses when sending messages to\n"
-"the given user (for example, when responding to a command they send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
-msgstr ""
-"Syntax: SET LANGUAGE sorszám\n"
-"Megváltoztatja a SERVICES nyelvezetét, amin az üzenteket\n"
-"írja.(Például: amikor válaszol egy parancsra, amit te \n"
-"adtál ki). A sorszám alapján válaszd ki a nyelvezetet:"
-
-#, fuzzy
-msgid ""
-"Changes the language Services uses when sending messages to\n"
-"you (for example, when responding to a command you send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
-msgstr ""
-"Syntax: SET LANGUAGE sorszám\n"
-"Megváltoztatja a SERVICES nyelvezetét, amin az üzenteket\n"
-"írja.(Például: amikor válaszol egy parancsra, amit te \n"
-"adtál ki). A sorszám alapján válaszd ki a nyelvezetet:"
-
-#, fuzzy
-msgid "Changes the password used to identify as the nick's owner."
-msgstr ""
-"Syntax: SET PASSWORD új-jelszó\n"
-"\n"
-"Megváltoztatja a nicknév tulajdonosának jelszavát."
-
-#, fuzzy
-msgid ""
-"Changes the password used to identify you as the nick's\n"
-"owner."
-msgstr ""
-"Syntax: SET PASSWORD új-jelszó\n"
-"\n"
-"Megváltoztatja a nicknév tulajdonosának jelszavát."
-
-#, fuzzy
-msgid ""
-"Changes the successor of a channel. If the founder's\n"
-"nickname expires or is dropped while the channel is still\n"
-"registered, the successor will become the new founder of the\n"
-"channel. The successor's nickname must be a registered one.\n"
-"If there's no successor set, then the first nickname on the\n"
-"access list (with the highest access, if applicable) will\n"
-"become the new founder, but if the access list is empty, the\n"
-"channel will be dropped."
-msgstr ""
-"Syntax: %s #szoba SUCCESSOR nick\n"
-"\n"
-"Megváltoztatja a successort a csatornán. Ha a founder neve\n"
-"elévül vagy törlődik, de a szoba még regisztrált, akkor\n"
-"a successor lesz a szoba új founderje.\n"
-"Ha, a successornak már túl sok regisztrált csatornája van \n"
-"(%d), a csatornának megszűnik a regisztrációja, akkor\n"
-"is ez történik, ha nem volt megadva successor.\n"
-"A nicknek regisztrálnak kell lennie."
-
-#, fuzzy
-msgid "Channel"
-msgstr "DROP #szoba"
-
-#, fuzzy, c-format
-msgid "Channel %s doesn't exist."
-msgstr "Channel %s is now persistant."
-
-#, c-format
-msgid "Channel %s has been dropped."
-msgstr "%s csatorna regisztrációjának törlése sikerült."
-
-#, fuzzy, c-format
-msgid "Channel %s has no key."
-msgstr "The channel %s has no key."
-
-#, c-format
-msgid "Channel %s is already registered!"
-msgstr "A megadott csatorna %s már regisztrált!"
-
-#, fuzzy, c-format
-msgid "Channel %s is forbidden by %s: %s"
-msgstr "Ez a szoba a %s adatbázisában regisztrált."
-
-#, fuzzy, c-format
-msgid "Channel %s is forbidden."
-msgstr "Channel %s is now persistant."
-
-#, fuzzy, c-format
-msgid "Channel %s is no longer persistent."
-msgstr "Channel %s is no longer persistant."
-
-#, fuzzy, c-format
-msgid "Channel %s is now persistent."
-msgstr "Channel %s is now persistant."
-
-#, c-format
-msgid "Channel %s is now released."
-msgstr "(%s) szoba újra használható."
-
-#, c-format
-msgid "Channel %s is now suspended."
-msgstr "(%s) szoba használata felfüggesztve."
-
-#, fuzzy, c-format
-msgid "Channel %s isn't registered."
-msgstr "Ez a csatorna %s nem regisztrálható. "
-
-#, fuzzy, c-format
-msgid "Channel %s isn't suspended."
-msgstr "(%s) szoba használata felfüggesztve."
-
-#, fuzzy, c-format
-msgid "Channel %s registered under your account: %s"
-msgstr "Ez a nicknév: %s számodra lett regisztrálva: %s"
-
-#, c-format
-msgid "Channel %s will expire."
-msgstr "A megadott csatorna (%s) el fog évülni."
-
-#, c-format
-msgid "Channel %s will not expire."
-msgstr "A megadott csatorna (%s) nem fog elévülni."
-
-#, fuzzy, c-format
-msgid "Channel %s %s list has been cleared."
-msgstr "Channel %s AOP list has been cleared."
-
-#, c-format
-msgid "Channel %s access list has been cleared."
-msgstr "Channel %s access list has been cleared."
-
-#, c-format
-msgid "Channel %s akick list has been cleared."
-msgstr "Channel %s akick list has been cleared."
-
-#, fuzzy, c-format
-msgid "Channel %s has no mode locks."
-msgstr "(%s) szoba újra használható."
-
-#, fuzzy, c-format
-msgid "Channel %s is currently suspended."
-msgstr "(%s) szoba használata felfüggesztve."
-
-#, fuzzy, c-format
-msgid "Channel %s is not a valid channel."
-msgstr "%s nem érvényes ban típus."
-
-#, fuzzy
-msgid "Channel list:"
-msgstr "Botok listája:"
-
-#, fuzzy, c-format
-msgid "Channel stats for %s on %s:"
-msgstr ""
-"Azon csatornák, ahol %s nicknek hozzáférése van:\n"
-" Sorszám Csatorna Szint Meghatározás"
-
-#, fuzzy
-msgid "Channels may not be on access lists."
-msgstr "%s nem található a (%s) csatorna hozzáférési listáján."
-
-#, fuzzy, c-format
-msgid "Channels that %s has access on:"
-msgstr ""
-"Azon csatornák, ahol %s nicknek hozzáférése van:\n"
-" Sorszám Csatorna Szint Meghatározás"
-
-#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-msgid "Chanstats"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Chanstats statistics are now disabled for %s"
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-msgid "Chanstats statistics are now disabled for this channel."
-msgstr ""
-
-#, fuzzy
-msgid "Chanstats statistics are now disabled for your nick."
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-#, fuzzy, c-format
-msgid "Chanstats statistics are now enabled for %s"
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-msgid "Chanstats statistics are now enabled for this channel."
-msgstr ""
-
-#, fuzzy
-msgid "Chanstats statistics are now enabled for your nick."
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-msgid ""
-"Checks for the last time nick was seen joining, leaving,\n"
-"or changing nick on the network and tells you when and, depending\n"
-"on channel or user settings, where it was."
-msgstr ""
-
-#, fuzzy
-msgid "Checks if last memo to a nick was read"
-msgstr " CHECK Ellenőrzi, hogy a címzett elolvasta-e már az üzit"
-
-#, fuzzy
-msgid ""
-"Checks whether the _last_ memo you sent to nick has been read\n"
-"or not. Note that this only works with nicks, not with channels."
-msgstr ""
-"Syntax: CHECK nick\n"
-"\n"
-"Ellenőrzi, hogy az _utolsó_ üzenet, amit a nick számára\n"
-"küldtél már olvasott-e vagy még olvasatlan.\n"
-"Megjegyzés, ez csak nickekkel működik szobákkal nem."
-
-#, c-format
-msgid "Cleared info from %s."
-msgstr ""
-
-#, fuzzy
-msgid "Colors kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Command"
-msgstr "%s parancsok:"
-
-#, fuzzy
-msgid "Configures AMSG kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures badwords kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures bolds kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures bot kickers. option can be one of:"
-msgstr ""
-"Syntax: SET opció paraméterek\n"
-"\n"
-"Beállítható nicknév opciók. Az opció ezek egyike lehet:"
-
-#, fuzzy
-msgid "Configures bot options"
-msgstr "SET Konfigurálja a bot opcióit"
-
-#, fuzzy
-msgid ""
-"Configures bot options.\n"
-" \n"
-"Available options:"
-msgstr "SET Konfigurálja a bot opcióit"
-
-#, fuzzy
-msgid "Configures caps kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures channel logging settings"
-msgstr "* Nem lehet új csatornát regisztrálni."
-
-#, fuzzy
-msgid "Configures color kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures flood kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures italics kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures kickers"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures repeat kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures reverses kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Configures the time bot bans expire in"
-msgstr "SET Konfigurálja a bot opcióit"
-
-#, fuzzy
-msgid "Configures underlines kicker"
-msgstr "KICK Konfigurálja a kirúgásokat"
-
-#, fuzzy
-msgid "Confirm a passcode"
-msgstr " CONFIRM Confirm a nickserv auth code"
-
-#, fuzzy
-msgid "Control modes and mode locks on a channel"
-msgstr " CLEARMODES Törli a szoba módot"
-
-msgid ""
-"Controls what messages will be sent to users when they join the channel."
-msgstr ""
-
-msgid ""
-"Copies all settings, access, akicks, etc from channel to the\n"
-"target channel. If what is ACCESS, AKICK, BADWORDS,\n"
-"or LEVELS then only the respective settings are cloned.\n"
-"You must be the founder of channel and target."
-msgstr ""
-
-#, fuzzy
-msgid "Copy all settings from one channel to another"
-msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-
-#, fuzzy
-msgid "Created"
-msgstr "Született: %s"
-
-#, fuzzy
-msgid "Creator"
-msgstr "Született: %s"
-
-#, fuzzy, c-format
-msgid "Current %s list:"
-msgstr "Aktuális AKILL lista:"
-
-#, fuzzy
-msgid "Current AKILL list:"
-msgstr "Aktuális AKILL lista:"
-
-msgid "Current Session Limit Exception list:"
-msgstr "Aktuális Session korlát kivétel lista:"
-
-#, fuzzy
-msgid "Current module list:"
-msgstr "Jelenlegi Modul lista:"
-
-#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Aktuális AKILLek száma: %d"
-
-#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Aktuális SNLINEok száma: %d"
-
-#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Aktuális SQLINEok száma : %d"
-
-#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Aktuális felhasználók: %d (%d op)"
-
-#, fuzzy
-msgid "DEL oper"
-msgstr "DEL <nick>."
-
-#, fuzzy
-msgid "DEL target info"
-msgstr "GROUP célnick jelszó"
-
-#, fuzzy
-msgid "DEL [nickname] channel"
-msgstr "MODE szoba mód"
-
-#, fuzzy
-msgid "DEL [nickname] fingerprint"
-msgstr "FORBID nicknév indok"
-
-#, fuzzy
-msgid "DEL [nickname] mask"
-msgstr "MODE szoba mód"
-
-#, fuzzy
-msgid "DEL {mask | entry-num | list | id}"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-#, fuzzy
-msgid "DEL {mask | entry-num | list}"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-#, fuzzy
-msgid "DEL {nick|mask}"
-msgstr "DEL <nick>."
-
-#, fuzzy
-msgid "DEL {num | ALL}"
-msgstr "Syntax: OPERNEWS DEL {szám | ALL}"
-
-msgid "DEL {NICK|CHAN|EMAIL|REGISTER} entry"
-msgstr ""
-
-msgid "DELIP server.name ip"
-msgstr ""
-
-msgid "DELSERVER server.name [zone.name]"
-msgstr ""
-
-msgid "DELZONE zone.name"
-msgstr ""
-
-#, fuzzy
-msgid "DEPOOL server.name"
-msgstr "NOOP {SET|REVOKE} szerver"
-
-#, c-format
-msgid "Database cleared, removed %lu nicks that were added after %s."
-msgstr ""
-
-msgid "Date/Time"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Deactivates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see your real host/IP address."
-msgstr ""
-"Syntax: OFF\n"
-"Kikapcsolja a vhostodat,ez most társitva van a nickedhez.\n"
-"Ha valaki használ /whois parancsot a nickeden, akkor a\n"
-"valós IP címed vagy hosztod fogja látni."
-
-#, fuzzy
-msgid "Deactivates your assigned vhost"
-msgstr " OFF Kikapcsolja a társított vhostot"
-
-#, c-format
-msgid "Default AKILL expiry time: %d days"
-msgstr "Alap AKILL lejárati idő: %d nap"
-
-#, c-format
-msgid "Default AKILL expiry time: %d hours"
-msgstr "Alap AKILL lejárati idő: %d óra"
-
-#, c-format
-msgid "Default AKILL expiry time: %d minutes"
-msgstr "Alap AKILL lejárati idő: %d perc"
-
-msgid "Default AKILL expiry time: 1 day"
-msgstr "Alap AKILL lejárati idő: 1 nap"
-
-msgid "Default AKILL expiry time: 1 hour"
-msgstr "Alap AKILL lejárati idő: 1 óra"
-
-msgid "Default AKILL expiry time: 1 minute"
-msgstr "Alap AKILL lejárati idő: 1 perc"
-
-msgid "Default AKILL expiry time: No expiration"
-msgstr "Alap AKILL lejárati idő: Nem elévülő"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d days"
-msgstr "Alap SNLINE lejárati idő: %d nap"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d hours"
-msgstr "Alap SNLINE lejárati idő: %d óra"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d minutes"
-msgstr "Alap SNLINE lejárati idő: %d perc"
-
-msgid "Default SNLINE expiry time: 1 day"
-msgstr "Alap SNLINE lejárati idő: 1 nap"
-
-msgid "Default SNLINE expiry time: 1 hour"
-msgstr "Alap SNLINE lejárati idő: 1 óra"
-
-msgid "Default SNLINE expiry time: 1 minute"
-msgstr "Alap SNLINE lejárati idő: 1 perc"
-
-msgid "Default SNLINE expiry time: No expiration"
-msgstr "Alap SNLINE lejárati ido: Nem elévülő"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d days"
-msgstr "Alap SQLINE lejárati idő: %d nap"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d hours"
-msgstr "Alap SQLINE lejárati idő: %d óra"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d minutes"
-msgstr "Alap SQLINE lejárati idő: %d perc"
-
-msgid "Default SQLINE expiry time: 1 day"
-msgstr "Alap SQLINE lejárati idő: 1 nap"
-
-msgid "Default SQLINE expiry time: 1 hour"
-msgstr "Alap SQLINE lejárati idő: 1 óra"
-
-msgid "Default SQLINE expiry time: 1 minute"
-msgstr "Alap SQLINE lejárati idő: 1 perc"
-
-msgid "Default SQLINE expiry time: No expiration"
-msgstr "Alap SQLINE lejárati idő Nem elévülő"
-
-#, fuzzy
-msgid "Define messages to be randomly shown to users at logon"
-msgstr " LOGONNEWS Fellépő üzenetek beállítása"
-
-#, fuzzy
-msgid "Define messages to be shown to users at logon"
-msgstr " LOGONNEWS Fellépő üzenetek beállítása"
-
-#, fuzzy
-msgid "Define messages to be shown to users who oper"
-msgstr " OPERNEWS Operek részére megjelenő üzenetet állít be"
-
-#, fuzzy
-msgid "Delete a memo or memos"
-msgstr " DEL Törli a megadott üzenete(ke)t"
-
-#, fuzzy
-msgid "Delete the vhost of another user"
-msgstr " DEL Törli egy felhasználónak a vhostját"
-
-#, fuzzy, c-format
-msgid "Deleted %d entries from %s %s list."
-msgstr "%d bejegyzés törölve a %s AOP listáról."
-
-#, c-format
-msgid "Deleted %d entries from %s access list."
-msgstr "%d bejegyzés törölve (%s) csatorna hozzáférési listájáról."
-
-#, c-format
-msgid "Deleted %d entries from %s autokick list."
-msgstr "%d bejegyzés törölve a (%s) csatorna autokick listájáról."
-
-#, c-format
-msgid "Deleted %d entries from %s bad words list."
-msgstr "Törölve %d bejegyzés %s tiltott szavak listájáról."
-
-#, c-format
-msgid "Deleted %d entries from session-limit exception list."
-msgstr "Törölve %d bejegyzés a session-korlát kivétel listáról."
-
-#, fuzzy, c-format
-msgid "Deleted %d entries from the %s list."
-msgstr "%d bejegyzés törölve a %s AOP listáról."
-
-#, c-format
-msgid "Deleted %d entries from the AKILL list."
-msgstr "Törölve %d bejegyzés az AKILL listáról."
-
-#, c-format
-msgid "Deleted 1 entry from %s access list."
-msgstr "1 bejegyzés törölve a (%s) csatorna hozzáférési listájáról"
-
-#, c-format
-msgid "Deleted 1 entry from %s autokick list."
-msgstr "1 bejegyzés törölve a (%s) csatorna autokick listájáról."
-
-#, c-format
-msgid "Deleted 1 entry from %s bad words list."
-msgstr "Törölve 1 bejegyzés %s tiltott szavak listájáról."
-
-msgid "Deleted 1 entry from session-limit exception list."
-msgstr "Törölve 1 bejegyzés a session-korlát kivétel listáról."
-
-#, fuzzy, c-format
-msgid "Deleted 1 entry from the %s list."
-msgstr "Törölve 1 bejegyzés az AKILL listáról."
-
-msgid "Deleted 1 entry from the AKILL list."
-msgstr "Törölve 1 bejegyzés az AKILL listáról."
-
-#, fuzzy, c-format
-msgid "Deleted info from %s."
-msgstr "Törölve 1 bejegyzés az AKILL listáról."
-
-#, fuzzy, c-format
-msgid "Deleted one entry from %s %s list."
-msgstr "1 bejegyzés törölve a %s AOP listáról."
-
-#, fuzzy
-msgid ""
-"Deletes the specified memo or memos. You can supply\n"
-"multiple memo numbers or ranges of numbers instead of a\n"
-"single number, as in the second example below.\n"
-" \n"
-"If LAST is given, the last memo will be deleted.\n"
-"If ALL is given, deletes all of your memos.\n"
-" \n"
-"Examples:\n"
-" \n"
-" DEL 1\n"
-" Deletes your first memo.\n"
-" \n"
-" DEL 2-5,7-9\n"
-" Deletes memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Syntax: DEL [#szoba] {sorszám | list | LAST | ALL}\n"
-"\n"
-"Törli a megadott memo üzenete(ke)t. \n"
-"Több számot is megadhatsz, intervallumot is használhatsz,\n"
-"az egyszerű sorszám helyett.\n"
-"\n"
-"Ha a LAST meg van adva, az utolsó memo üzenetet törli\n"
-"Ha az ALL van megadve, akkor minden memo üzenetet töröl.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tDEL 1\n"
-"\t\tTörli az első memo üzenetet.\n"
-"\n"
-"\tDEL 2-5,7-9\n"
-"\t\tTörli a memo üzeneteket 2 és 5, illetve 7 és 9 között."
-
-#, fuzzy
-msgid ""
-"Deletes the vhost assigned to the given nick from the\n"
-"database."
-msgstr ""
-"Syntax: DEL <nick>\n"
-"A vhost törölve az adott nick adatbázisából.\n"
-"Korlátozva Hoszt változtatókra."
-
-#, fuzzy
-msgid "Deletes the vhost for all nicks in a group"
-msgstr " DELALL Törli a vhosztot a nickekröl a csoportban"
-
-#, fuzzy
-msgid ""
-"Deletes the vhost for all nicks in the same group as\n"
-"that of the given nick."
-msgstr ""
-"Syntax: DELALL <nick>.\n"
-"Törlődik a vhost az összes nickről a csoportban ahol az\n"
-"adott nick van és ez a vhosztot használta \n"
-"\n"
-"Korlátozva Hoszt változtatókra."
-
-#, c-format
-msgid "Depooled %s."
-msgstr ""
-
-#, fuzzy
-msgid "Description"
-msgstr "%s csatorna leírás megváltoztatva: %s."
-
-#, c-format
-msgid "Description of %s changed to %s."
-msgstr "%s csatorna leírás megváltoztatva: %s."
-
-#, fuzzy, c-format
-msgid "Description of %s unset."
-msgstr "%s csatorna leírás megváltoztatva: %s."
-
-#, fuzzy
-msgid "Disabled"
-msgstr "%s is enable"
-
-#, fuzzy
-msgid ""
-"Disallows anyone from using the given channel.\n"
-"May be cancelled by using the UNSUSPEND\n"
-"command to preserve all previous channel data/settings.\n"
-"If an expiry is given the channel will be unsuspended after\n"
-"that period of time, else the default expiry from the\n"
-"configuration is used.\n"
-" \n"
-"Reason may be required on certain networks."
-msgstr ""
-"Syntax: SUSPEND #szoba [indok]\n"
-"Elutasít minden szobahasználatot. Lehet törölni a\n"
-"UNSUSPEND paranccsal és akkor használható az öüsszes \n"
-"megörzött szoba adat/beállítás.\n"
-"\n"
-"Indoklást kér némelyik hálózat.\n"
-"\n"
-"Korlátozva Szervíz adminnak."
-
-#, fuzzy, c-format
-msgid "Displayed %d records (%d total)."
-msgstr "Kiírja az összes bejegyzést (Számláló: %d)"
-
-#, fuzzy, c-format
-msgid "Displayed all records (count: %d)."
-msgstr "Kiírja az összes bejegyzést (Számláló: %d)"
-
-#, fuzzy, c-format
-msgid "Displayed records from %d to %d."
-msgstr "Kiírja a bejegyzéseket %d-tól %d-ig"
-
-#, fuzzy, c-format
-msgid "Displayed records matching key %s (count: %d)."
-msgstr ""
-"Kiírja azokat a hosztokat melyben a %s szó szerepel.\n"
-"(számláló: %d)"
-
-#, fuzzy
-msgid "Displays information about a given nickname"
-msgstr " INFO Displays information about a given nickname"
-
-#, fuzzy
-msgid ""
-"Displays information about the given nickname, such as\n"
-"the nick's owner, last seen address and time, and nick\n"
-"options. If no nick is given, and you are identified,\n"
-"your account name is used, else your current nickname is\n"
-"used."
-msgstr ""
-"Syntax: INFO nicknév\n"
-"\n"
-"Megmutatja a nicknévvel kapcsolatos információkat, mint a\n"
-"nick tulajdonosa, utoljára látott címe, regisztrálás ideje,\n"
-"a nick opciókat. Ha beazonosítasz egy nickre, akkor minden \n"
-"informaciót megkaphatsz az ALL paraméter használatával \n"
-"és így látni fogod a rejtett információkat is."
-
-#, fuzzy
-msgid "Displays information about your memos"
-msgstr " INFO Kiírja az üzenetekkel kapcsolatos információkat"
-
-#, fuzzy
-msgid "Displays one or more vhost entries"
-msgstr " LIST Kiír egy vagy több vhost bejegyzést"
-
-#, fuzzy
-msgid "Displays the top 10 users of a channel"
-msgstr " FOUNDER A founder megváltoztatása"
-
-msgid "Displays the top 10 users of the network"
-msgstr ""
-
-#, fuzzy
-msgid "Displays the top 3 users of a channel"
-msgstr " FOUNDER A founder megváltoztatása"
-
-msgid "Displays the top 3 users of the network"
-msgstr ""
-
-#, fuzzy
-msgid "Displays this list and give information about commands"
-msgstr " INFO Kiírja az üzenetekkel kapcsolatos információkat"
-
-msgid "Displays your Channel Stats"
-msgstr ""
-
-msgid "Displays your Global Stats"
-msgstr ""
-
-msgid "Don't use AMSGs!"
-msgstr ""
-
-msgid "Don't use bolds on this channel!"
-msgstr "Nem használható kiemelt betű ezen a csatornán!"
-
-msgid "Don't use colors on this channel!"
-msgstr "Nem szinezhetsz ezen a csatornán!"
-
-msgid "Don't use italics on this channel!"
-msgstr "Don't use italics on this channel!"
-
-msgid "Don't use reverses on this channel!"
-msgstr "Nem írj visszafelé ezen a csatornán!"
-
-#, c-format
-msgid "Don't use the word \"%s\" on this channel!"
-msgstr "Nem használható ez a szó: %s!"
-
-msgid "Don't use underlines on this channel!"
-msgstr "Nem használj aláhúzásokat ezen a csatornán!"
-
-msgid ""
-"Drops the given nick from the database. Once your nickname\n"
-"is dropped you may lose all of your access and channels that\n"
-"you may own. Any other user will be able to gain control of\n"
-"this nick."
-msgstr ""
-
-#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "E-mail address for %s changed to %s."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "E-mail address for %s unset."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "%sEmail címe nem érvényes."
-
-#, fuzzy, c-format
-msgid ""
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. However, no more than %d messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
-msgstr ""
-"Syntax: LOGONNEWS ADD text\n"
-" LOGONNEWS DEL {num | ALL}\n"
-" LOGONNEWS LIST\n"
-"\n"
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. (However, no more than %d messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent.)\n"
-"NewsCount can be configured in services.conf.\n"
-"\n"
-"LOGONNEWS may only be used by Services Operators."
-
-#, fuzzy, c-format
-msgid ""
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. However, no more than %d messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
-msgstr ""
-"Syntax: OPERNEWS ADD text\n"
-" OPERNEWS DEL {num | ALL}\n"
-" OPERNEWS LIST\n"
-"\n"
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. (However, no more than %d messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent.)\n"
-"NewsCount can be configured in services.conf.\n"
-"\n"
-"OPERNEWS may only be used by Services Operators."
-
-#, fuzzy
-msgid ""
-"Edits or displays the list of random news messages. When a\n"
-"user connects to the network, one (and only one) of the\n"
-"random news will be randomly chosen and sent to them."
-msgstr ""
-"Syntax: RANDOMNEWS ADD szöveg\n"
-" RANDOMNEWS DEL {sorszám | ALL}\n"
-" RANDOMNEWS LIST\n"
-"\n"
-"Szerkeszti és listázza a random news üzeneteket. Amikor\n"
-"egy felhasználó csatlakozik a hálózathoz, egy (csak egy)\n"
-"random newst fog véletlenszerűen elküldeni részére.\n"
-"\n"
-"RANDOMNEWS may only be used by Services Operators."
-
-#, fuzzy
-msgid "Email address"
-msgstr "E-mail cím: %s"
-
-#, fuzzy, c-format
-msgid "Email matched: %s (%s) to %s."
-msgstr "Egyező emailek %s ehhez: %s."
-
-msgid "Enable fantaisist commands"
-msgstr ""
-
-msgid "Enable greet messages"
-msgstr ""
-
-msgid "Enable or disable keep modes"
-msgstr ""
-
-#, fuzzy
-msgid "Enabled"
-msgstr "%s is enable"
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables %s's autoop feature for a\n"
-"channel. When disabled, users who join the channel will\n"
-"not automatically gain any status from %s."
-msgstr ""
-"Syntax: %s #szoba SECUREOPS {ON | OFF}\n"
-"\n"
-"Bekapcsolja vagy letiltja a secure ops opciót.\n"
-"Amikor a secure ops be van kapcsolva, akkor azok, akik \n"
-"nem szerepelnek a hozzáférési listán nem kaphatnak szoba\n"
-"operátori státuszt."
-
-#, fuzzy
-msgid ""
-"Enables or disables keepmodes for the given channel. If keep\n"
-"modes is enabled, services will remember modes set on the channel\n"
-"and attempt to re-set them the next time the channel is created."
-msgstr ""
-"Syntax: %s #szoba KEEPTOPIC {ON | OFF}\n"
-"\n"
-"Engedélyezi vagy letiltja a topic megtartása opciót a\n"
-"szoba részére. Ha a topic megtartása be van állítva,\n"
-"a topicot a %s megjegyzi miután az utolsó user elhagyja a\n"
-"szobát, és visszaállítja a következő megnyitáskor."
-
-msgid ""
-"Enables or disables keepmodes for the given nick. If keep\n"
-"modes is enabled, services will remember users' usermodes\n"
-"and attempt to re-set them the next time they authenticate."
-msgstr ""
-
-msgid ""
-"Enables or disables keepmodes for your nick. If keep\n"
-"modes is enabled, services will remember your usermodes\n"
-"and attempt to re-set them the next time you authenticate."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Syntax: %s #szoba SECURE {ON | OFF}\n"
-"\n"
-"Engedélyezi vagy letitlja a %s biztonsági lehetőségeit\n"
-"a szobában. Ha SECURE működik, csak azok a felhasználók\n"
-"akik regisztráltak és beazonosítottak a %s-be a\t\n"
-"jelszavukkal (használván az IDENTIFY parancsot) kaphatnak\n"
-"a szobában jogokat, ha szerepelnek a hozzáférési listán."
-
-#, fuzzy
-msgid ""
-"Enables or disables signed kicks for a\n"
-"channel. When SIGNKICK is set, kicks issued with\n"
-"the KICK command will have the nick that used the\n"
-"command in their reason.\n"
-" \n"
-"If you use LEVEL, those who have a level that is superior\n"
-"or equal to the SIGNKICK level on the channel won't have their\n"
-"kicks signed."
-msgstr ""
-"Syntax: %s #szoba SIGNKICK {ON | SZINT | OFF}\n"
-"\n"
-"Engedélyezi vagy letiltja a signed kick opciót a csatornán\n"
-"Amikor a SIGNKICK be van állítva, a %s KICK parancsával\n"
-"végrehajtott kirúgásokban az indokban szerepel az op neve.\n"
-"\n"
-"Ha használod a LEVEL-t, akkor azok, akiknek a szintje\n"
-"megegyezik vagy magasabb, mint a signkick szintje, azoknak\n"
-"a neve nem fog szerepelni a kick indokjában.\n"
-"Lásd még: /msg %s HELP LEVELS bővebb információkért. "
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the peace option for a channel.\n"
-"When peace is set, a user won't be able to kick,\n"
-"ban or remove a channel status of a user that has\n"
-"a level superior or equal to his via %s commands."
-msgstr ""
-"Syntax: %s #szoba PEACE {ON | OFF}\n"
-"\n"
-"Engedélyezi vagy letiltja a peace opciót.\n"
-"Amikor a peace be van állítva, akkor a userek nem,\n"
-"rúghatnak ki, tilthatnak ki olyan usert akinek az övékkel\n"
-"egyenlő vagy magasabb szintje van a %s parancsokhoz."
-
-msgid "Enables or disables the private option for a channel."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-msgstr ""
-"Syntax: %s #szoba RESTRICTED {ON | OFF}\n"
-"\n"
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-
-#, fuzzy
-msgid ""
-"Enables or disables the secure founder option for a channel.\n"
-"When secure founder is set, only the real founder will be\n"
-"able to drop the channel, change its founder and its successor,\n"
-"and not those who have founder level access through\n"
-"the access/qop command."
-msgstr ""
-"Syntax: %s #szoba SECUREFOUNDER {ON | OFF}\n"
-"\n"
-"Engedélyezi vagy letiltja a secure founder opciót a \n"
-"csatornán. Amikor a secure founder be van állítva, csak\n"
-"a valódi founder tudja dropolni a csatornát, átírni a \n"
-"szoba jelszavát, founderét, jogutódját, de azok nem,\n"
-"akik csak az IDENTIFY parancsot használták a %s-ben."
-
-#, fuzzy
-msgid ""
-"Enables or disables the secure ops option for a channel.\n"
-"When secure ops is set, users who are not on the access list\n"
-"will not be allowed channel operator status."
-msgstr ""
-"Syntax: %s #szoba SECUREOPS {ON | OFF}\n"
-"\n"
-"Bekapcsolja vagy letiltja a secure ops opciót.\n"
-"Amikor a secure ops be van kapcsolva, akkor azok, akik \n"
-"nem szerepelnek a hozzáférési listán nem kaphatnak szoba\n"
-"operátori státuszt."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the topic retention option for a\n"
-"channel. When %s is set, the topic for the\n"
-"channel will be remembered by %s even after the\n"
-"last user leaves the channel, and will be restored the\n"
-"next time the channel is created."
-msgstr ""
-"Syntax: %s #szoba KEEPTOPIC {ON | OFF}\n"
-"\n"
-"Engedélyezi vagy letiltja a topic megtartása opciót a\n"
-"szoba részére. Ha a topic megtartása be van állítva,\n"
-"a topicot a %s megjegyzi miután az utolsó user elhagyja a\n"
-"szobát, és visszaállítja a következő megnyitáskor."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the persistent channel setting.\n"
-"When persistent is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-" \n"
-"If your IRCd does not have a permanent (persistent) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-" \n"
-"If this network does not have %s enabled and does\n"
-"not have a permanent channel mode, %s will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-" \n"
-"If your IRCd has a permanent (persistent) channel mode\n"
-"and it is set or unset (for any reason, including MODE LOCK),\n"
-"persist is automatically set and unset for the channel as well.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-msgstr ""
-"Syntax: %s channel PERSIST {ON | OFF}\n"
-"Enables or disables the persistant channel setting.\n"
-"When persistant is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-"\n"
-"If your IRCd does not a permanent (persistant) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-"\n"
-"If this network does not have BotServ enabled and does\n"
-"not have a permanent channel mode, ChanServ will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-"\n"
-"If your IRCd has a permanent (persistant) channel mode\n"
-"and is is set or unset (for any reason, including MLOCK),\n"
-"persist is automatically set and unset for the channel aswell.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-
-#, fuzzy
-msgid "End of AKILL list."
-msgstr "Vége a felhasználó listának."
-
-#, fuzzy
-msgid "End of access list"
-msgstr "Hozzáférési lista vége."
-
-#, fuzzy, c-format
-msgid "End of access list - %d/%d entries shown."
-msgstr "Lista vége - %d / %d találat megjelenítve."
-
-msgid "End of access list."
-msgstr "Hozzáférési lista vége."
-
-#, fuzzy
-msgid "End of autokick list"
-msgstr "Hozzáférési lista vége."
-
-#, fuzzy
-msgid "End of bad words list."
-msgstr "Vége a felhasználó listának."
-
-#, fuzzy, c-format
-msgid "End of channel list. %u channels shown."
-msgstr "Lista vége - %d / %d találat megjelenítve."
-
-msgid "End of configuration."
-msgstr ""
-
-#, fuzzy
-msgid "End of entry message list."
-msgstr "Vége a felhasználó listának."
-
-#, fuzzy, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Lista vége - %d / %d találat megjelenítve."
-
-#, fuzzy
-msgid "End of forbid list."
-msgstr "Vége a felhasználó listának."
-
-#, fuzzy, c-format
-msgid "End of list - %d channels shown."
-msgstr "Lista vége - %d / %d találat megjelenítve."
-
-#, c-format
-msgid "End of list - %d/%d matches shown."
-msgstr "Lista vége - %d / %d találat megjelenítve."
-
-#, fuzzy
-msgid "End of news list."
-msgstr "Vége a felhasználó listának."
-
-#, fuzzy, c-format
-msgid "End of users list. %u users shown."
-msgstr "Lista vége - %d / %d találat megjelenítve."
-
-msgid "Enforce various channel modes and set options"
-msgstr ""
-
-msgid ""
-"Enforce various channel modes and set options. The channel\n"
-"option indicates what channel to enforce the modes and options\n"
-"on. The what option indicates what modes and options to\n"
-"enforce, and can be any of SECUREOPS, RESTRICTED, REGONLY, SSLONLY,\n"
-"BANS, or LIMIT.\n"
-" \n"
-"Use SECUREOPS to enforce the SECUREOPS option, even if it is not\n"
-"enabled. Use RESTRICTED to enforce the RESTRICTED option, also\n"
-"if it's not enabled. Use REGONLY to kick all unregistered users\n"
-"from the channel. Use SSLONLY to kick all users not using a secure\n"
-"connection from the channel. BANS will enforce bans on the channel by\n"
-"kicking users affected by them, and LIMIT will kick users until the\n"
-"user count drops below the channel limit, if one is set."
-msgstr ""
-
-msgid "English"
-msgstr "Magyar"
-
-#, fuzzy, c-format
-msgid "Entry message %i for %s deleted."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid "Entry message %s not found on channel %s."
-msgstr "Fantasy mód most ON a %s csatornán."
-
-#, fuzzy, c-format
-msgid "Entry message added to %s"
-msgstr "Greet message for %s changed to %s."
-
-#, fuzzy, c-format
-msgid "Entry message list for %s is empty."
-msgstr "Access list for %s is empty."
-
-#, fuzzy, c-format
-msgid "Entry message list for %s:"
-msgstr "%s hozzáférési listája:"
-
-#, fuzzy, c-format
-msgid "Entry messages for %s have been cleared."
-msgstr "Minden üzenetet töröltem a %s csatornán."
-
-#, fuzzy, c-format
-msgid "Error reloading configuration file: %s"
-msgstr " RELOAD Újratölti a szervíz Konfigurációs fájlját"
-
-#, c-format
-msgid ""
-"Error! The vHost ident is too long, please use an ident shorter than %d "
-"characters."
-msgstr ""
-
-#, c-format
-msgid ""
-"Error! The vHost is too long, please use a hostname shorter than %d "
-"characters."
-msgstr ""
-
-msgid ""
-"Examples:\n"
-" \n"
-" CERT ADD\n"
-" Adds your current fingerprint to the certificate list and\n"
-" automatically identifies you when you connect to IRC\n"
-" using this fingerprint.\n"
-" \n"
-" CERT DEL <fingerprint>\n"
-" Removes the fingerprint <fingerprint> from your certificate list.\n"
-" \n"
-" CERT LIST\n"
-" Displays the current certificate list."
-msgstr ""
-
-#, c-format
-msgid "Exception for %s has been updated to %d."
-msgstr "Exception for %s has been updated to %d."
-
-#, fuzzy
-msgid "Expires"
-msgstr "Expires in: %s"
-
-#, fuzzy, c-format
-msgid "Expiry and reason updated for %s."
-msgstr "Exception for %s has been updated to %d."
-
-#, fuzzy, c-format
-msgid "Expiry for %s updated."
-msgstr "Lejárati idő megváltozott: %s."
-
-msgid "Fantasy"
-msgstr "Fantasy"
-
-#, fuzzy, c-format
-msgid "Fantasy mode is now off on channel %s."
-msgstr "Fantasy mód most ON a %s csatornán."
-
-#, fuzzy, c-format
-msgid "Fantasy mode is now on on channel %s."
-msgstr "Fantasy mód most ON a %s csatornán."
-
-#, fuzzy
-msgid "Find a user's status on a channel"
-msgstr " DEOWNER Removes your owner status on a channel"
-
-#, fuzzy, c-format
-msgid "Fingerprint %s already present on %s's certificate list."
-msgstr "Ez a maszk: %s már szerepel a hozzáférési listádon."
-
-#, fuzzy, c-format
-msgid "Fingerprint %s is already in use."
-msgstr "You are already in %s! "
-
-msgid "Flags"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Flags for %s on %s set to +%s"
-msgstr "%s hozzáférése a (%s) csatornán változott: %d."
-
-#, fuzzy, c-format
-msgid "Flags list for %s"
-msgstr "%s hozzáférési listája:"
-
-#, fuzzy
-msgid "Flood kicker"
-msgstr "\tFloodért kirúgás: %s"
-
-msgid ""
-"Forbid allows you to forbid usage of certain nicknames, channels,\n"
-"and email addresses. Wildcards are accepted for all entries."
-msgstr ""
-
-#, fuzzy
-msgid "Forbid list is empty."
-msgstr "Mellőzöttek lista üres."
-
-#, fuzzy
-msgid "Forbid list:"
-msgstr "Botok listája:"
-
-#, c-format
-msgid "Forbid on %s was not found."
-msgstr ""
-
-msgid "Forbid usage of nicknames, channels, and emails"
-msgstr ""
-
-#, fuzzy
-msgid "Force the Services databases to be updated immediately"
-msgstr ""
-" UPDATE A Szervíz adatbázist frissíti, felülírja\n"
-" lemezre közvetlenül"
-
-#, fuzzy
-msgid "Forcefully change a user's nickname"
-msgstr " SVSNICK Megváltoztatja a felhasználó nicknevét"
-
-#, fuzzy
-msgid "Forcefully changes a user's nickname from nick to newnick."
-msgstr ""
-"Syntax: SVSNICK nick újnick\n"
-"\n"
-"Erőszakkal meváltóztatja a user nickevét újnicknévre."
-
-#, fuzzy
-msgid "Forcefully join a user to a channel"
-msgstr " SVSNICK Megváltoztatja a felhasználó nicknevét"
-
-#, fuzzy
-msgid "Forcefully join a user to a channel."
-msgstr " SVSNICK Megváltoztatja a felhasználó nicknevét"
-
-#, fuzzy
-msgid "Forcefully part a user from a channel"
-msgstr " KICK Kirúgja a felhasználót csatornáról"
-
-#, fuzzy
-msgid "Forcefully part a user from a channel."
-msgstr " KICK Kirúgja a felhasználót csatornáról"
-
-#, fuzzy
-msgid "Founder"
-msgstr "Founderjog védelme"
-
-#, fuzzy, c-format
-msgid "Founder of %s changed to %s."
-msgstr "A megadott csatorna (%s) új foundere: %s."
-
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "GETPASS nem elérhető, amíg az encryption használatban van"
-
-msgid "Ghost with your nick has been killed."
-msgstr "A befagyott kliens killelve."
-
-#, fuzzy
-msgid "Give Operflags to a certain user"
-msgstr " OLINE Operflaget ad a biztos felhasználónak"
-
-#, c-format
-msgid ""
-"Gives %s status to the selected nick on a channel. If nick is\n"
-"not given, it will %s you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Gives you or the specified nick %s status on a channel"
-msgstr " OWNER Gives you owner status on channel"
-
-msgid "Greet"
-msgstr "Üdvözlés"
-
-#, fuzzy
-msgid "Greet message displayed on join"
-msgstr "Greet message for %s changed to %s."
-
-#, c-format
-msgid "Greet message for %s changed to %s."
-msgstr "Greet message for %s changed to %s."
-
-#, c-format
-msgid "Greet message for %s unset."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid "Greet mode is now off on channel %s."
-msgstr "Üdvözlő mód most ON a %s szobán."
-
-#, fuzzy, c-format
-msgid "Greet mode is now on on channel %s."
-msgstr "Üdvözlő mód most ON a %s szobán."
-
-#, fuzzy
-msgid "Helps you reset lost passwords"
-msgstr " RESETPASS Helps you reset lost passwords."
-
-#, fuzzy
-msgid "Hide certain pieces of nickname information"
-msgstr " HIDE A nicknévhez tartozó információk elrejtése"
-
-#, fuzzy
-msgid "Hide channel from the LIST command"
-msgstr " PRIVATE A szoba elrejtése a listából"
-
-msgid "Host"
-msgstr ""
-
-#, c-format
-msgid "Hosts with at least %d sessions:"
-msgstr "Hosztok legalább %d sessionnel:"
-
-#, c-format
-msgid "I don't know who %s is."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "I've never seen %s on this channel."
-msgstr "Nem írj visszafelé ezen a csatornán!"
-
-msgid "ID"
-msgstr ""
-
-msgid "INFO [type]"
-msgstr ""
-
-msgid "IP"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "IP %s already exists for %s."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy, c-format
-msgid "IP %s does not exist for %s."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy
-msgid "Identify yourself with your password"
-msgstr " IDENTIFY Jelszavas azonosítás"
-
-#, fuzzy, c-format
-msgid "If you do not change within %s, I will change your nick."
-msgstr "Ha nem váltasz nevet 20 sec.-en belül, én megváltoztatom."
-
-msgid "Ignore list has been cleared."
-msgstr "Mellőzöttek lista törölve."
-
-msgid "Ignore list is empty."
-msgstr "Mellőzöttek lista üres."
-
-#, fuzzy
-msgid "Ignore list:"
-msgstr "Botok listája:"
-
-#, fuzzy
-msgid "Immediate protection"
-msgstr "Voices védelme"
-
-#, fuzzy
-msgid "Incorrect email address."
-msgstr "E-mail cím: %s"
-
-msgid "Incorrect range specified. The correct syntax is #from-to."
-msgstr ""
-
-#, fuzzy
-msgid "Info about a loaded module"
-msgstr " MODINFO Információ a betöltött modulokról"
-
-#, c-format
-msgid "Information for bot %s:"
-msgstr "Információk a %s nevű botról:"
-
-#, fuzzy, c-format
-msgid "Information for channel %s:"
-msgstr "Információk a %s nevű botról:"
-
-#, c-format
-msgid "Invalid duration %s, using %d days."
-msgstr ""
-
-msgid "Invalid expiry time."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Invalid hostmask. Only real hostmasks are valid, as exceptions are not "
-"matched against nicks or usernames."
-msgstr ""
-"Érvénytelen hosztmaszk. Csak érvényes hosztmaszk lehet,\n"
-"a kivétel nem lehet nick vagy usernév."
-
-#, c-format
-msgid "Invalid limit %s, using %d."
-msgstr ""
-
-msgid ""
-"Invalid passcode has been entered, please check the e-mail again, and retry."
-msgstr ""
-
-msgid "Invalid passcode."
-msgstr ""
-
-#, c-format
-msgid ""
-"Invalid session limit. It must be a valid integer greater than or equal to "
-"zero and less than %d."
-msgstr ""
-"Érvénytelen session korlát. Érvényes számnak kell lennie\n"
-"és nagyobbnak vagy egyenlőnek mint zéró és kissebbnek \n"
-"mint %d."
-
-msgid "Invalid threshold value. It must be a valid integer greater than 1."
-msgstr ""
-"Érvénytelen küszöb érték. 1-nél nagyobb egész számnak\n"
-"kell lennie."
-
-msgid "Invalid value for LIMIT. Must be numerical."
-msgstr ""
-
-#, fuzzy
-msgid "Invites you or an optionally specified nick into a channel"
-msgstr " OP Gives Op status to a selected nick on a channel"
-
-#, fuzzy
-msgid "Italics kicker"
-msgstr "\tItalics kicker : %s"
-
-#, fuzzy
-msgid "Join a group"
-msgstr " GROUP Csatlakozás egy csoporthoz"
-
-#, fuzzy
-msgid "Keep modes"
-msgstr "Üzenet mód"
-
-#, fuzzy, c-format
-msgid "Keep modes for %s is now off."
-msgstr "Peace option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Keep modes for %s is now on."
-msgstr "Peace option for %s is now ON."
-
-msgid "Key"
-msgstr ""
-
-#, c-format
-msgid "Key for channel %s is %s."
-msgstr "Key for channel %s is %s."
-
-#, fuzzy
-msgid "Kick a user from a channel"
-msgstr " KICK Kirúgja a felhasználót csatornáról"
-
-#, c-format
-msgid "Kicked %d/%d users matching %s from %s."
-msgstr ""
-
-#, fuzzy
-msgid "Kicks a specified nick from a channel"
-msgstr " KICK Kicks a selected nick from a channel"
-
-#, fuzzy
-msgid ""
-"Kicks a specified nick from a channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders can also specify masks."
-msgstr ""
-"Syntax: KICK #szoba nick [indok]\n"
-"\n"
-"A ChanServ kirúgja a megadott nicknevet a csatornáról.\n"
-"\n"
-"Alapbeállítás szerint, min. AOP vagy 5-ös access szinttel\n"
-"kell rendelkezned a csatornán, hogy használhasd."
-
-msgid "Kill a user"
-msgstr ""
-
-msgid "LIMIT enforced by "
-msgstr ""
-
-#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr ""
-
-msgid "LIST threshold"
-msgstr ""
-
-#, fuzzy
-msgid "LIST [mask | list | id]"
-msgstr "LIST [#szoba] [list | NEW ]"
-
-#, fuzzy
-msgid "LIST [mask | list]"
-msgstr "LIST [#szoba] [list | NEW ]"
-
-#, fuzzy
-msgid "LIST [nickname]"
-msgstr "CHECK nicknév "
-
-msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "LOGONNEWS { ADD | DEL | LIST } [szöveg|szám]"
-
-msgid "Language changed to English."
-msgstr "Új nyelvezet: Magyar."
-
-#, fuzzy, c-format
-msgid "Language for %s changed to %s."
-msgstr "A megadott csatorna (%s) új successora: %s."
-
-#, c-format
-msgid "Last memo to %s has been cancelled."
-msgstr "%s részére küldött utolsó memo üzenet visszavonva."
-
-#, fuzzy
-msgid "Last quit message"
-msgstr "Utolsó kilépő üzenet: %s"
-
-#, fuzzy
-msgid "Last seen"
-msgstr "Utoljára ekkor volt: %s"
-
-#, fuzzy
-msgid "Last seen address"
-msgstr "Utoljára látott cím: %s"
-
-msgid "Last topic"
-msgstr ""
-
-#, fuzzy
-msgid "Last used"
-msgstr "Utoljára ekkor volt: %s"
-
-#, fuzzy
-msgid "Last usermask"
-msgstr "Utoljára ekkor volt: %s"
-
-msgid "Level"
-msgstr ""
-
-#, c-format
-msgid "Level for %s on channel %s changed to %d."
-msgstr "%s szintjének új értéke a (%s) csatornán: %d."
-
-#, c-format
-msgid "Level for %s on channel %s changed to founder only."
-msgstr "Level for %s on channel %s changed to founder only."
-
-#, c-format
-msgid "Level must be between %d and %d inclusive."
-msgstr "A szintnek kizárólag %d és %d között kell lennie."
-
-msgid "Limit"
-msgstr ""
-
-#, fuzzy
-msgid "List all registered nicknames that match a given pattern"
-msgstr ""
-" LIST List all registered nicknames that match a given pattern"
-
-#, fuzzy
-msgid "List channels you have access on"
-msgstr " ALIST List channels you have access on"
-
-#, c-format
-msgid "List for mode %c is full."
-msgstr ""
-
-#, fuzzy
-msgid "List loaded modules"
-msgstr " MODLIST Listázza a betöltött modulokat"
-
-#, fuzzy, c-format
-msgid "List of entries matching %s:"
-msgstr "%s csoportjába tartozó nickek listája:"
-
-#, c-format
-msgid "List of nicknames in the group of %s:"
-msgstr "%s csoportjába tartozó nickek listája:"
-
-msgid "List of nicknames in your group:"
-msgstr "A csoportodba tartozó nickek listája:"
-
-#, fuzzy
-msgid "List your memos"
-msgstr " LIST Megjeleníti az üzenetek listáját"
-
-#, fuzzy
-msgid ""
-"Lists all available bots on this network.\n"
-"Bots prefixed by a * are reserved for IRC Operators."
-msgstr ""
-"Syntax: BOTLIST\n"
-"\n"
-"Listázza az összes érvényes botot a hálózatról."
-
-#, fuzzy
-msgid "Lists all channel records"
-msgstr " CHANLIST Listázza az összes csatornát "
-
-#, fuzzy
-msgid ""
-"Lists all channels currently in use on the IRC network, whether they\n"
-"are registered or not.\n"
-" \n"
-"If pattern is given, lists only channels that match it. If a nickname\n"
-"is given, lists only the channels the user using it is on. If SECRET is\n"
-"specified, lists only channels matching pattern that have the +s or\n"
-"+p mode."
-msgstr ""
-"Syntax: CHANLIST [{pattern | nick} [SECRET]]\n"
-"\n"
-"Listáz minden csatornát, ami most aktív az IRC hálózaton\n"
-"attól függetlenül, hogy regisztrált vagy sem.\n"
-"\n"
-"Ha a pattern meg van adva, akkor csak az egyezőket\n"
-"listázza. Ha a nicknév van megadva, akkor listázza azokat\n"
-"a csatornákat, ahol az adott user bent van. Ha a SECRET\n"
-"van megadva, akkor listáz minden pattern-nek megfelelő\n"
-"csatornár, melyen +s vagy +p mód van fent.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-msgid ""
-"Lists all channels you have access on.\n"
-" \n"
-"Channels that have the NOEXPIRE option set will be\n"
-"prefixed by an exclamation mark. The nickname parameter is\n"
-"limited to Services Operators"
-msgstr ""
-
-#, fuzzy
-msgid "Lists all nicknames in your group"
-msgstr "A csoportodba tartozó nickek listája:"
-
-#, fuzzy
-msgid "Lists all registered channels matching the given pattern"
-msgstr ""
-" LIST Lists all registered channels matching the given pattern"
-
-#, fuzzy
-msgid ""
-"Lists all registered channels matching the given pattern.\n"
-"Channels with the PRIVATE option set will only be\n"
-"displayed to Services Operators with the proper access.\n"
-"Channels with the NOEXPIRE option set will have\n"
-"a ! prefixed to the channel for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range, channel names\n"
-"are to be written without '#'.\n"
-" \n"
-"If the SUSPENDED or NOEXPIRE options are given, only channels\n"
-"which, respectively, are SUSPENDED or have the NOEXPIRE\n"
-"flag set will be displayed. If multiple options are given,\n"
-"all channels matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *anope*\n"
-" Lists all registered channels with anope in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered channels which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered channels within the given range (51-100)."
-msgstr ""
-"Syntax: LIST pattern [FORBIDDEN] [SUSPENDED] [NOEXPIRE]\n"
-"\n"
-"Listáz minden regisztrált nicknevet, amely vagy nicknév\n"
-"vagy az utoljára látott cím (user@hostformában), amely\n"
-"azonos a megadott sablonnal. Nickek PRIVATE opcióval\n"
-"beállítva csak szervíz adminoknak jelennek meg. A nickek\n"
-"NOEXPIRE opcióval beállítva !prefixel jelennek meg\n"
-"a szervíz adminoknak.\n"
-"\n"
-"Ha a FORBIDDEN, SUSPENDED vagy NOEXPIRE opció meg van adva, csak azok\n"
-"a nickek amelyek vagy forbidoltak vagy NOEXPIRE flegjük van\n"
-"fognak megjelenik. Ha mindkét opció meg van adva mindkét\n"
-"tipus megjelenik. Az opciók korlátozva Services Operatoroknak.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tLIST *!joeuser@foo.com\n"
-" Kiírja a felhasználókat, akiknek a hosztja joeuser@foo.com\n"
-"\n"
-"\tLIST *Bot*!*@*\n"
-" Kiírja az összes regisztrált nicket, melyek nevében \n"
-" szerepel a Bot (betű érzéketlen).\n"
-"\n"
-" LIST * NOEXPIRE\n"
-" Listázza az összes felhasználót, akinek a beállítása\n"
-" nem elévülő."
-
-#, fuzzy
-msgid ""
-"Lists all registered nicknames which match the given\n"
-"pattern, in nick!user@host format. Nicks with the PRIVATE\n"
-"option set will only be displayed to Services Operators with the\n"
-"proper access. Nicks with the NOEXPIRE option set will have\n"
-"a ! prefixed to the nickname for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range.\n"
-" \n"
-"If the SUSPENDED, UNCONFIRMED or NOEXPIRE options are given, only\n"
-"nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n"
-"NOEXPIRE flag set will be displayed. If multiple options are\n"
-"given, all nicks matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *!joeuser@foo.com\n"
-" Lists all registered nicks owned by joeuser@foo.com.\n"
-" \n"
-" LIST *Bot*!*@*\n"
-" Lists all registered nicks with Bot in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered nicks which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered nicks within the given range (51-100)."
-msgstr ""
-"Syntax: LIST pattern [FORBIDDEN] [SUSPENDED] [NOEXPIRE]\n"
-"\n"
-"Listáz minden regisztrált nicknevet, amely vagy nicknév\n"
-"vagy az utoljára látott cím (user@hostformában), amely\n"
-"azonos a megadott sablonnal. Nickek PRIVATE opcióval\n"
-"beállítva csak szervíz adminoknak jelennek meg. A nickek\n"
-"NOEXPIRE opcióval beállítva !prefixel jelennek meg\n"
-"a szervíz adminoknak.\n"
-"\n"
-"Ha a FORBIDDEN, SUSPENDED vagy NOEXPIRE opció meg van adva, csak azok\n"
-"a nickek amelyek vagy forbidoltak vagy NOEXPIRE flegjük van\n"
-"fognak megjelenik. Ha mindkét opció meg van adva mindkét\n"
-"tipus megjelenik. Az opciók korlátozva Services Operatoroknak.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tLIST *!joeuser@foo.com\n"
-" Kiírja a felhasználókat, akiknek a hosztja joeuser@foo.com\n"
-"\n"
-"\tLIST *Bot*!*@*\n"
-" Kiírja az összes regisztrált nicket, melyek nevében \n"
-" szerepel a Bot (betű érzéketlen).\n"
-"\n"
-" LIST * NOEXPIRE\n"
-" Listázza az összes felhasználót, akinek a beállítása\n"
-" nem elévülő."
-
-#, fuzzy
-msgid "Lists all user records"
-msgstr " USERLIST Listázza az összes felhasználót "
-
-#, fuzzy
-msgid ""
-"Lists all users currently online on the IRC network, whether their\n"
-"nick is registered or not.\n"
-" \n"
-"If pattern is given, lists only users that match it (it must be in\n"
-"the format nick!user@host[#realname]). If channel is given, lists\n"
-"only users that are on the given channel. If INVISIBLE is specified, only "
-"users\n"
-"with the +i flag will be listed."
-msgstr ""
-"Syntax: USERLIST [{pattern | #szoba} [INVISIBLE]]\n"
-"\n"
-"Listáz minden jelenleg online usert az IRC hálózaton,\n"
-"attól függetlenül, hogy regisztrált vagy sem.\n"
-"\n"
-"Ha a pattern meg van adva, akkor csak az egyezőket \n"
-"listázza (formátum: nick!user@host). Ha a #szoba\n"
-"meg van adva, akkor csak az adott csatornán lévőket\n"
-"listázza. Ha az INVISIBLE meg van adva, akkor csak a\n"
-"+i flages usereket listázza.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-#, fuzzy
-msgid ""
-"Lists any memos you currently have. With NEW, lists only\n"
-"new (unread) memos. Unread memos are marked with a \"*\"\n"
-"to the left of the memo number. You can also specify a list\n"
-"of numbers, as in the example below:\n"
-" LIST 2-5,7-9\n"
-" Lists memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Syntax: LIST [#szoba] [list | NEW]\n"
-"\n"
-"Megjelenít egy listát a jelenlegi üzenteteidrol. A NEW\n"
-"opcióval csak az új (olvasatlan) üzenteket listázza.\n"
-"listázza. Az olvasatlan üzeneteket jelöli egy \"*\" jellel\n"
-"az üzenetszámtól balra. Megadhatsz számlistát is, mint\n"
-"ahogy az alábbi példa mutatja:\n"
-"\n"
-"\tLIST 2-5,7-9\n"
-"\t\tListázza az üzeneteket 2 és 5, illetve 7 és 9 között."
-
-#, fuzzy
-msgid "Lists available bots"
-msgstr "BOTLIST Listázza az elérhető botokat"
-
-#, fuzzy
-msgid "Lists currently loaded modules."
-msgstr " MODLIST Listázza a betöltött modulokat"
-
-#, fuzzy
-msgid "Lists information about the specified registered channel"
-msgstr " INFO Lists information about the named registered channel"
-
-#, fuzzy
-msgid ""
-"Lists information about the specified registered channel,\n"
-"including its founder, time of registration, last\n"
-"time used, and description. If the user issuing the\n"
-"command has the appropriate access for it, then the\n"
-"successor, last topic set, settings and expiration\n"
-"time will also be displayed when applicable."
-msgstr ""
-"Syntax: INFO #szoba\n"
-"\n"
-"Listázza az összes információt a megnevezett regisztrált\n"
-"csatornáról, pl a foundert, a regisztrálás időpontját,\n"
-"az utolsó használat idejét, a leírást, az mlock-ot. \n"
-"Ha beazonosítottad magad a szoba founderjének, akkor\n"
-"teljes információt az ALL paraméterrel kaphatsz, az \n"
-"entrymessage, a successor és a rejtett infók is látszódnak\n"
-"\n"
-"Alapból az ALL opció csak a foundernek engedélyezett."
-
-#, fuzzy
-msgid "Load a module"
-msgstr " MODLOAD Betölti a modult"
-
-msgid "Local channels cannot be registered."
-msgstr "Helyi csatornák nem regisztrálhatók."
-
-#, fuzzy, c-format
-msgid "Log list for %s:"
-msgstr "%s hozzáférési listája:"
-
-#, c-format
-msgid "Logging changed for command %s on %s, now using log method %s%s%s."
-msgstr ""
-
-#, c-format
-msgid "Logging for command %s on %s with log method %s%s%s has been removed."
-msgstr ""
-
-#, c-format
-msgid "Logging is now active for command %s on %s, using log method %s%s%s."
-msgstr ""
-
-#, c-format
-msgid "Login to %s"
-msgstr ""
-
-#, c-format
-msgid "Logon news item #%d deleted."
-msgstr "Logon news tétel #%d törölve."
-
-#, fuzzy, c-format
-msgid "Logon news item #%s not found!"
-msgstr "Logon news tétel #%d nem található!"
-
-msgid "Logon news items:"
-msgstr "Fellépési hírek:"
-
-#, fuzzy, c-format
-msgid "Logout from %s"
-msgstr "%s hozzáférési listája:"
-
-#, c-format
-msgid ""
-"Logs you in to %s so you gain Services Operator privileges.\n"
-"This command may be unnecessary if your oper block is\n"
-"configured without a password."
-msgstr ""
-
-#, c-format
-msgid ""
-"Logs you out from %s so you lose Services Operator privileges.\n"
-"This command is only useful if your oper block is configured\n"
-"with a password."
-msgstr ""
-
-#, c-format
-msgid "Looking for yourself, eh %s?"
-msgstr ""
-
-#, c-format
-msgid ""
-"Mainly controls mode locks and mode access (which is different from channel "
-"access)\n"
-"on a channel.\n"
-" \n"
-"The %s LOCK command allows you to add, delete, and view mode locks on a "
-"channel.\n"
-"If a mode is locked on or off, services will not allow that mode to be "
-"changed. The SET\n"
-"command will clear all existing mode locks and set the new one given, while "
-"ADD and DEL\n"
-"modify the existing mode lock.\n"
-"Example:\n"
-" MODE #channel LOCK ADD +bmnt *!*@*aol*\n"
-" \n"
-"The %s SET command allows you to set modes through services. Wildcards * "
-"and ? may\n"
-"be given as parameters for list and status modes.\n"
-"Example:\n"
-" MODE #channel SET +v *\n"
-" Sets voice status to all users in the channel.\n"
-" \n"
-" MODE #channel SET -b ~c:*\n"
-" Clears all extended bans that start with ~c:\n"
-" \n"
-"The %s CLEAR command is an easy way to clear modes on a channel. what may "
-"be\n"
-"any mode name. Examples include bans, excepts, inviteoverrides, ops, "
-"halfops, and voices. If what\n"
-"is not given then all basic modes are removed."
-msgstr ""
-
-#, fuzzy
-msgid "Maintain the AutoKick list"
-msgstr " AKICK AutoKirúgás listára teheted a \"rossz\" usereket"
-
-#, fuzzy
-msgid "Maintains network bot list"
-msgstr "BOT Karbantartja a hálózat botjainak listáját"
-
-#, c-format
-msgid ""
-"Maintains the %s list for a channel. Users who match an access entry\n"
-"on the %s list receive the following privileges:\n"
-" "
-msgstr ""
-
-#, c-format
-msgid ""
-"Maintains the AutoKick list for a channel. If a user\n"
-"on the AutoKick list attempts to join the channel,\n"
-"%s will ban that user from the channel, then kick\n"
-"the user.\n"
-" \n"
-"The AKICK ADD command adds the given nick or usermask\n"
-"to the AutoKick list. If a reason is given with\n"
-"the command, that reason will be used when the user is\n"
-"kicked; if not, the default reason is \"User has been\n"
-"banned from the channel\".\n"
-"When akicking a registered nick the %s account\n"
-"will be added to the akick list instead of the mask.\n"
-"All users within that nickgroup will then be akicked.\n"
-msgstr ""
-
-#, c-format
-msgid ""
-"Maintains the access list for a channel. The access\n"
-"list specifies which users are allowed chanop status or\n"
-"access to %s commands on the channel. Different\n"
-"user levels allow for access to different subsets of\n"
-"privileges. Any registered user not on the access list has\n"
-"a user level of 0, and any unregistered user has a user level\n"
-"of -1."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Maintains the bad words list for a channel. The bad\n"
-"words list determines which words are to be kicked\n"
-"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
-" \n"
-"The ADD command adds the given word to the\n"
-"bad words list. If SINGLE is specified, a kick will be\n"
-"done only if a user says the entire word. If START is\n"
-"specified, a kick will be done if a user says a word\n"
-"that starts with word. If END is specified, a kick\n"
-"will be done if a user says a word that ends with\n"
-"word. If you don't specify anything, a kick will\n"
-"be issued every time word is said by a user.\n"
-" \n"
-msgstr ""
-"Syntax:BADWORDS #szoba ADD szó [SINGLE | START | END]\n"
-"\t BADWORDS #szoba DEL { szó | sorszám | list}\n"
-"\t BADWORDS #szoba LIST [ maszk | list]\n"
-"\t BADWORDS #szoba CLEAR\n"
-"Karbantartja a szoba csúnyaszó listáját. A tiltott\n"
-"szavak listája meghatározza, hogy mely szavak kiejtésére\n"
-"rúgja ki a bot a usert, ha a kirúgás engedélyezve van,\n"
-"erről bővebb információk: /msg %s HELP KICK BADWORDS.\n"
-"\n"
-"A BADWORDS ADD parancs hozzáad egy szót a listához.\n"
-"Ha a SINGLE van megadva, akkor lesz kirúgja a user, ha\n"
-"a konkrét szót mondja ki.\n"
-"Ha a START van megadva, akkor a szó elejét figyeli a bot.\n"
-"Ha az END van megadva, akkor a szó végét figyeli a bot.\n"
-"Ha nem adsz meg semmit, akkor\ta user minden alkalommal\n"
-"kirúgásra kerül, ha kiejti a szót.\n"
-"Ha nem beszél csúnyán, akkor semmi baja nem lesz! :-)\n"
-"A BADWORDS DEL parancs eltávolítja a megadott szót\n"
-"a tiltott szavak listájáról. Ha egy sorozatot adsz meg\n"
-"a bejegyzések számával, akkor azok a bejegyzések kerülnek\n"
-"törlésre. (Lásd lentebb a listázást.)\n"
-"\n"
-"A BADWORDS LIST parancs megjeleníti a tiltott szavakat.\n"
-"Ha használod a * karaktert, akkor csak az egyező\n"
-"bejegyzések kerülnek listázásra. Ha egy sorozatot adsz meg\n"
-"akkor azok a bejegyzések kerülnek megjelenítésre; példa:\n"
-" BADWORDS #szoba LIST 2-5,7-9\n"
-" Listázza a csúnyaszavakat 2-től 5-ig és a 7-től\n"
-" 9-ig.\n"
-" \n"
-"BADWORDS CLEAR parancs törli az összes bejegyzést\n"
-"a tiltott szavak listájáról"
-
-#, fuzzy
-msgid "Maintains the bad words list"
-msgstr "BADWORDS Szerkeszti a tiltott szavak listáját"
-
-#, fuzzy
-msgid "Makes the bot do the equivalent of a \"/me\" command"
-msgstr ""
-"ACT Makes the bot do the equivalent of a \"/me\" command"
-
-#, fuzzy
-msgid ""
-"Makes the bot do the equivalent of a \"/me\" command\n"
-"on the specified channel using the specified text."
-msgstr ""
-"Syntax: ACT #szoba szöveg\n"
-"\n"
-"A bot \"/me\" akcióval küldi el a megadott szöveget\n"
-"a csatornára."
-
-#, fuzzy
-msgid "Makes the bot say the specified text on the specified channel"
-msgstr ""
-"SAY Makes the bot say the given text on the given channel"
-
-#, fuzzy
-msgid "Makes the bot say the specified text on the specified channel."
-msgstr ""
-"SAY Makes the bot say the given text on the given channel"
-
-#, fuzzy
-msgid ""
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary\n"
-"access on it."
-msgstr ""
-"Syntax: SASET nickname GREET message\n"
-"\n"
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary \n"
-"access on it."
-
-#, fuzzy
-msgid ""
-"Makes the given message the greet of your nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that you have the necessary\n"
-"access on it."
-msgstr ""
-"Syntax: SET GREET üzenet\n"
-"\n"
-"Ez az opció társít egy üzenetet a nicknevedhez,\n"
-"ami akkor fog megjelenni belépéskor, ha a csatornán\n"
-"a GREET opció engedélyezve van és te rendelkezel a\n"
-"megfelelő szinttel, ami az üzenet megjelenitéséhez\n"
-"szükséges a csatornán."
-
-#, fuzzy
-msgid "Manage DNS zones for this network"
-msgstr "Nem törölheted ezen a hálózaton az e-mail címed."
-
-#, fuzzy
-msgid "Manage the channel's entry messages"
-msgstr " PERSIST Set the channel as permanent"
-
-#, fuzzy
-msgid "Manage the memo ignore list"
-msgstr " IGNORE Módosítja a Szervíz mellőzési listáját"
-
-#, fuzzy
-msgid "Manage your auto join list"
-msgstr " AKICK AutoKirúgás listára teheted a \"rossz\" usereket"
-
-#, fuzzy, c-format
-msgid "Manipulate the %s list"
-msgstr " AKILL Szerkeszti az AKILL listát"
-
-#, fuzzy
-msgid "Manipulate the AKILL list"
-msgstr " AKILL Szerkeszti az AKILL listát"
-
-#, fuzzy
-msgid "Manipulate the DefCon system"
-msgstr " DEFCON Manipulálja a DefCon rendszert"
-
-#, fuzzy
-msgid "Manipulate the topic of the specified channel"
-msgstr " TOPIC Manipulate the topic of the specified channel"
-
-msgid "Mask"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "Ez a maszk: %s már szerepel a hozzáférési listádon."
-
-msgid "Mask must be in the form user@host."
-msgstr ""
-
-#, fuzzy
-msgid "Masks and unregistered users may not be on access lists."
-msgstr "Ez a maszk: %s már szerepel a hozzáférési listádon."
-
-#, fuzzy
-msgid "Matches and returns all users that registered using given email"
-msgstr ""
-" GETEMAIL Kiírja az ilyen e-mail címmel regisztrált\n"
-" felhasználókat"
-
-#, fuzzy, c-format
-msgid "Matches for %s:"
-msgstr "\tRögzített módok: %s"
-
-#, c-format
-msgid "Maximum users: %d (%s)"
-msgstr "Legtöbb felhasználó: %d (%s)"
-
-#, fuzzy, c-format
-msgid "Memo %d from %s (%s)."
-msgstr "\tRögzített módok: %s"
-
-#, c-format
-msgid "Memo %d has been deleted."
-msgstr "A megadott üzenetet (%d) töröltem."
-
-#, fuzzy
-msgid "Memo ignore list is empty."
-msgstr "Mellőzöttek lista üres."
-
-#, c-format
-msgid "Memo limit disabled for %s."
-msgstr "%s ezentúl korlátlan számú üzenetet fogadhat."
-
-#, c-format
-msgid "Memo limit for %s set to %d."
-msgstr "%s maximálisan fogadható üzeneteinek száma: %d."
-
-#, c-format
-msgid "Memo limit for %s set to 0."
-msgstr "%s ezentúl nem fogadhat üzeneteket."
-
-#, c-format
-msgid "Memo sent to %s."
-msgstr "Üzenet elküldve %s részére."
-
-#, fuzzy, c-format
-msgid "Memos for %s:"
-msgstr "\tRögzített módok: %s"
-
-#, fuzzy
-msgid "Message"
-msgstr "GLOBAL üzenet"
-
-msgid "Message mode"
-msgstr "Üzenet mód"
-
-msgid "Method"
-msgstr ""
-
-#, c-format
-msgid "Missing parameter for mode %c."
-msgstr ""
-
-msgid "Mode"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Mode %s is a virtual mode and can't be cleared."
-msgstr " %snick illegális nicknév vagy nem használható."
-
-#, fuzzy, c-format
-msgid "Mode %s is not a status or list mode."
-msgstr "%s nick nem található a mellőzöttek listáján."
-
-#, fuzzy
-msgid "Mode lock"
-msgstr "\tRögzített módok: %s"
-
-#, fuzzy, c-format
-msgid "Mode locks for %s:"
-msgstr "\tRögzített módok: %s"
-
-msgid "Modes"
-msgstr ""
-
-#, c-format
-msgid "Modes cleared on %s and the channel destroyed."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
-msgstr ""
-"Syntax: ACCESS ADD maszk\n"
-" ACCESS DEL maszk\n"
-" ACCESS LIST\n"
-"\n"
-"Módosítja vagy kiirja a hozzáférési listát a nickedhez.\n"
-"Ez azon címeknek a listája, amelyek automatikusan úgy \n"
-"tekintődnek a %s-ben, hogy engedélyük van a nicket \n"
-"használni. Ha a nicked más címekről akarod használni,\n"
-"akkor nem kell IDENTIFY parancsot küldened, hogy úgy\n"
-"legyél tekintve, a %s-ben, mint a nick tulajdonosa.\n"
-"\n"
-"Példák:\n"
-"\n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Hozzáférést engedélyez az anyone identnek bármely\n"
-" gépről aminek a bepeg.com a domainje.\n"
-"\n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Törli az elöző parancsot.\n"
-"\n"
-" ACCESS LIST\n"
-" Megmutatja a hozzáférési listát."
-
-msgid ""
-"Modifies or displays the certificate list for your nick.\n"
-"If you connect to IRC and provide a client certificate with a\n"
-"matching fingerprint in the cert list, you will be\n"
-"automatically identified to services. Services Operators\n"
-"may provide a nick to modify other users' certificate lists.\n"
-" \n"
-msgstr ""
-
-#, fuzzy
-msgid "Modify the Services ignore list"
-msgstr " IGNORE Módosítja a Szervíz mellőzési listáját"
-
-#, fuzzy, c-format
-msgid "Modify the list of %s users"
-msgstr " AOP AutoOperátor lista beállítása"
-
-#, fuzzy
-msgid "Modify the list of authorized addresses"
-msgstr " ACCESS A hozzáférési lista módosítása"
-
-#, fuzzy
-msgid "Modify the list of privileged users"
-msgstr " ACCESS A szoba hozzáférési listájának beállítása"
-
-#, fuzzy
-msgid "Modify the nickname client certificate list"
-msgstr " IGNORE Módosítja a Szervíz mellőzési listáját"
-
-#, fuzzy
-msgid "Modify the session-limit exception list"
-msgstr " EXCEPTION Módosítja a session-korlát/kivétel listát"
-
-#, c-format
-msgid "Module %s is already loaded."
-msgstr "Module %s is already loaded."
-
-#, c-format
-msgid "Module %s isn't loaded."
-msgstr "Module %s isn't loaded."
-
-#, fuzzy, c-format
-msgid "Module %s loaded."
-msgstr "%s modul betöltve"
-
-#, fuzzy, c-format
-msgid "Module %s reloaded."
-msgstr "%s modul betöltve"
-
-#, fuzzy, c-format
-msgid "Module %s unloaded."
-msgstr "%s modul kitöltve"
-
-#, fuzzy
-msgid "Module Name"
-msgstr "%s modul betöltve"
-
-msgid "Module settings:"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Module: %s Version: %s Author: %s Loaded: %s"
-msgstr "Modul: %s Verzió: %s Szerző: %s Betöltve: %s"
-
-#, c-format
-msgid "Module: %s [%s] [%s]"
-msgstr "Modul: %s [%s] [%s]"
-
-msgid "Name"
-msgstr ""
-
-msgid "Name Type"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Network stats for %s:"
-msgstr "%s hozzáférési listája:"
-
-msgid "Never"
-msgstr ""
-
-#, fuzzy
-msgid "Nick"
-msgstr "INFO nick"
-
-#, fuzzy, c-format
-msgid "Nick %s has been confirmed."
-msgstr "A %s nicknevet dropoltad."
-
-#, fuzzy, c-format
-msgid "Nick %s is already an operator."
-msgstr "Ez a nicknév: %s már regisztrált!"
-
-#, fuzzy, c-format
-msgid "Nick %s is already confirmed."
-msgstr "Ez a nicknév: %s már regisztrált!"
-
-#, c-format
-msgid "Nick %s is an illegal nickname and cannot be used."
-msgstr " %snick illegális nicknév vagy nem használható."
-
-#, c-format
-msgid "Nick %s is currently in use."
-msgstr "Ez a nick: %s jelenleg használatban van."
-
-#, fuzzy, c-format
-msgid "Nick %s is forbidden by %s: %s"
-msgstr "Ez a nick: %s jelenleg használatban van."
-
-#, fuzzy, c-format
-msgid "Nick %s is forbidden."
-msgstr "Ezt a nicket %s nem fogja a services."
-
-#, fuzzy, c-format
-msgid "Nick %s is not a Services Operator."
-msgstr "%s is a services operator of type %s."
-
-#, c-format
-msgid "Nick %s is part of this Network's Services."
-msgstr "A %s nick a Hálózat Szervízének egysége."
-
-#, fuzzy, c-format
-msgid "Nick %s isn't currently in use."
-msgstr "Ez a nick: %s jelenleg használatban van."
-
-#, fuzzy, c-format
-msgid "Nick %s isn't registered."
-msgstr "Nickname %s registered."
-
-#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "A nicked %s meg lett csonkítva %d karakter hosszúságúra."
-
-#, c-format
-msgid "Nick %s will expire."
-msgstr "Nick %s will expire."
-
-#, c-format
-msgid "Nick %s will not expire."
-msgstr "Nick %s will not expire."
-
-#, c-format
-msgid "Nick %s doesn't have a memo from you."
-msgstr "%s nickre nem érkezett memo üzenet tőled."
-
-#, c-format
-msgid "Nick %s has been logged out."
-msgstr " %s nick sikeresen kijelentkezett."
-
-#, c-format
-msgid "Nick %s has been ungrouped from %s."
-msgstr "Nick %s has been ungrouped from %s."
-
-#, fuzzy, c-format
-msgid "Nick %s is currently suspended."
-msgstr "Nick %s is now suspended."
-
-#, fuzzy, c-format
-msgid "Nick %s is not in your group."
-msgstr "The nick %s is not in your group."
-
-#, fuzzy, c-format
-msgid "Nick %s is not suspended."
-msgstr "Nick %s is now suspended."
-
-#, c-format
-msgid "Nick %s is now released."
-msgstr "Nick %s is now released."
-
-#, c-format
-msgid "Nick %s is now suspended."
-msgstr "Nick %s is now suspended."
-
-#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr ""
-
-#, c-format
-msgid "Nickname %s has been dropped."
-msgstr "A %s nicknevet dropoltad."
-
-#, fuzzy, c-format
-msgid "Nickname %s is already registered!"
-msgstr "A megadott csatorna %s már regisztrált!"
-
-#, fuzzy, c-format
-msgid "Nickname %s may not be registered."
-msgstr "Ez a csatorna %s nem regisztrálható. "
-
-#, fuzzy, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr "Ez a nicknév: %s számodra lett regisztrálva: %s"
-
-#, fuzzy, c-format
-msgid "Nickname %s registered."
-msgstr "Nickname %s registered."
-
-#, fuzzy
-msgid "No auto-op"
-msgstr "Auto-op"
-
-msgid "No bot"
-msgstr "Nincs bot"
-
-#, fuzzy
-msgid "No expire"
-msgstr "nem fog elévülni"
-
-#, c-format
-msgid "No help available for %s."
-msgstr "Nincs ezzel kapcsolatban segítség: %s."
-
-#, fuzzy, c-format
-msgid "No information about module %s is available."
-msgstr "Nincs elérhető információ a %s modulról"
-
-#, fuzzy, c-format
-msgid "No limit is set on %s."
-msgstr "%s maximálisan fogadható üzeneteinek száma: %d."
-
-msgid "No logon news items to delete!"
-msgstr "Nincs törölhető fellépési hír!"
-
-#, fuzzy, c-format
-msgid "No matches for %s found."
-msgstr "Nincs Email listázva ehhez: %s."
-
-#, fuzzy, c-format
-msgid "No matching entries on %s %s list."
-msgstr "Nincs ilyen bejegyzés a %s AOP listán."
-
-#, c-format
-msgid "No matching entries on %s access list."
-msgstr "Nincs ilyen bejegyzés a (%s) csatorna hozzáférési listáján."
-
-#, c-format
-msgid "No matching entries on %s autokick list."
-msgstr "Nincs ilyen bejegyzés a (%s) csatorna autokick listáján."
-
-#, c-format
-msgid "No matching entries on %s bad words list."
-msgstr "Nincs ilyen szó %s a tiltott szavak listáján."
-
-msgid "No matching entries on session-limit exception list."
-msgstr "Nincs ilyen bejegyzés a session-korlát kivétel listán."
-
-#, fuzzy, c-format
-msgid "No matching entries on the %s list."
-msgstr "Nincs ilyen bejegyzés a %s AOP listán."
-
-msgid "No matching entries on the AKILL list."
-msgstr "Nincs ilyen bejegyzés az AKILL listán."
-
-msgid "No memo was cancelable."
-msgstr "Nincs visszavont memo üzenet."
-
-msgid "No memos to display."
-msgstr ""
-
-#, fuzzy
-msgid "No modules currently loaded matching that criteria."
-msgstr "Jelenleg nincs modul betöltve."
-
-msgid "No one is using your nick, and services are not holding it."
-msgstr ""
-
-msgid "No oper block for your nick."
-msgstr ""
-
-msgid "No oper news items to delete!"
-msgstr "Nincs törölhető opernews tétel!"
-
-msgid "No random news items to delete!"
-msgstr "Nincs törölhető random news tétel!"
-
-msgid "No records to display."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "No registrations matching %s were found."
-msgstr "* Nem lehet új nicket regisztrálni."
-
-#, c-format
-msgid "No request for nick %s found."
-msgstr ""
-
-msgid "No signed kick when SIGNKICK LEVEL is used"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "No stats for %s."
-msgstr "%s hozzáférési listája:"
-
-#, fuzzy, c-format
-msgid "No such info \"%s\" on %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "No users on %s match %s."
-msgstr "%s usermódjai megváltoztatva."
-
-#, fuzzy, c-format
-msgid "No-bot mode is now off on channel %s."
-msgstr "Nincs Bot mód most ONa %s szobán."
-
-#, fuzzy, c-format
-msgid "No-bot mode is now on on channel %s."
-msgstr "Nincs Bot mód most ONa %s szobán."
-
-#, c-format
-msgid "Non-status modes cleared on %s."
-msgstr ""
-
-msgid "None"
-msgstr "Nincs"
-
-#, c-format
-msgid ""
-"Note, however, if the successor already has too many\n"
-"channels registered (%d), they will not be able to\n"
-"become the new founder and it will be as if the\n"
-"channel had no successor set."
-msgstr ""
-
-msgid "Nothing to do."
-msgstr ""
-
-msgid "Number"
-msgstr ""
-
-msgid "OPERNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "OPERNEWS { ADD | DEL |LIST } [ szöveg | szám ]"
-
-#, fuzzy
-msgid "Online from"
-msgstr "Jelenleg online erről a címről: %s"
-
-#, c-format
-msgid ""
-"Oper %s is configured in the configuration file(s) and can not be removed by "
-"this command."
-msgstr ""
-
-msgid "Oper Info"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Oper info list for %s is empty."
-msgstr "Access list for %s is empty."
-
-#, c-format
-msgid "Oper news item #%d deleted."
-msgstr "Oper news tétel #%d törölve."
-
-#, fuzzy, c-format
-msgid "Oper news item #%s not found!"
-msgstr "Oper news tétel #%d nem található!"
-
-msgid "Oper news items:"
-msgstr "Oper hírek listája:"
-
-#, c-format
-msgid "Oper privileges removed from %s (%s)."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Oper type %s has not been configured."
-msgstr "A %s nicknevet dropoltad."
-
-#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "%s operflagek megadva a %s nicknek."
-
-#, fuzzy, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "%s operflagek megadva a %s nicknek."
-
-#, c-format
-msgid "Opertype %s has no allowed commands."
-msgstr ""
-
-#, c-format
-msgid "Opertype %s has no allowed privileges."
-msgstr ""
-
-#, c-format
-msgid "Opertype %s receives modes %s once identified."
-msgstr ""
-
-msgid "Ops protection"
-msgstr "Opok védelme"
-
-#, fuzzy
-msgid "Options"
-msgstr "Beállításai: %s"
-
-#, fuzzy
-msgid "POOL server.name"
-msgstr "NOOP {SET|REVOKE} szerver"
-
-msgid "Param"
-msgstr ""
-
-msgid "Password accepted - you are now recognized."
-msgstr "Jelszavad elfogadva - azonosítás sikeres."
-
-#, fuzzy
-msgid "Password accepted."
-msgstr "Hibás jelszó."
-
-msgid "Password authentication required for that command."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Password for %s changed to %s."
-msgstr "A megadott csatorna (%s) új successora: %s."
-
-#, fuzzy, c-format
-msgid "Password for %s changed."
-msgstr "%s nick jelszava elküldve."
-
-#, c-format
-msgid "Password for %s is %s."
-msgstr "%s jelszava: %s."
-
-#, fuzzy
-msgid "Password incorrect."
-msgstr "Hibás jelszó."
-
-#, c-format
-msgid "Password reset email for %s has been sent."
-msgstr "Password reset email for %s has been sent."
-
-msgid "Peace"
-msgstr "Békesség"
-
-#, fuzzy, c-format
-msgid "Peace option for %s is now off."
-msgstr "Peace option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Peace option for %s is now on."
-msgstr "Peace option for %s is now ON."
-
-#, fuzzy
-msgid "Persistent"
-msgstr "Persistant"
-
-msgid "Please contact an Operator to get a vHost assigned to this nick."
-msgstr ""
-
-msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab "
-"characters."
-msgstr ""
-
-#, fuzzy
-msgid "Please use a valid server name when juping."
-msgstr "Kérlek használj érvényes szerver nevet amikor jupolsz!"
-
-msgid "Please use the symbol of # when attempting to register."
-msgstr ""
-
-#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Kérlek várj %d másodpercet és próbáld újra."
-
-#, fuzzy, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Kérlek, várj %d másodpercet mielőtt SEND parancsot újra használod!"
-
-#, fuzzy, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Kérlek, várj %d másodpercet mielőtt SEND parancsot újra használod!"
-
-#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Kérlek várj %d másodpercet, mielőtt ismét használod a GROUP parancsot."
-
-#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr " Várj %d másodpercet mielőtt használnád ezt a parancsot!"
-
-#, c-format
-msgid "Pooled %s."
-msgstr ""
-
-msgid "Pooled/Active"
-msgstr ""
-
-msgid "Pooled/Not Active"
-msgstr ""
-
-msgid "Prevent a bot from being assigned by non IRC operators"
-msgstr ""
-
-#, fuzzy
-msgid "Prevent a bot from being assigned to a channel"
-msgstr ""
-" SUSPEND Felfüggeszti a szoba használatát de\n"
-" megőrzi az adatokat és beállításokat."
-
-#, fuzzy
-msgid "Prevent a channel from being used preserving channel data and settings"
-msgstr ""
-" SUSPEND Felfüggeszti a szoba használatát de\n"
-" megőrzi az adatokat és beállításokat."
-
-#, fuzzy
-msgid "Prevent the channel from expiring"
-msgstr " NOEXPIRE Prevent the channel from expiring"
-
-#, fuzzy
-msgid "Prevent the nickname from appearing in the LIST command"
-msgstr ""
-" PRIVATE Prevent the nickname from appearing in a\n"
-" /msg %s LIST"
-
-#, fuzzy
-msgid "Prevent the nickname from expiring"
-msgstr " NOEXPIRE Prevent the nickname from expiring"
-
-msgid "Prevents users being kicked by Services"
-msgstr ""
-
-msgid "Private"
-msgstr "Privát"
-
-#, fuzzy, c-format
-msgid "Private mode of bot %s is now off."
-msgstr "Private mód a %s botban most ON."
-
-#, fuzzy, c-format
-msgid "Private mode of bot %s is now on."
-msgstr "Private mód a %s botban most ON."
-
-#, fuzzy, c-format
-msgid "Private option for %s is now off."
-msgstr "Private option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Private option for %s is now on."
-msgstr "Private option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Private option is now off for %s."
-msgstr "Private option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Private option is now on for %s."
-msgstr "Private option is now ON for %s."
-
-#, c-format
-msgid "Privilege %s added to %s on %s, new flags are +%s"
-msgstr ""
-
-#, c-format
-msgid "Privilege %s removed from %s on %s, new flags are +%s"
-msgstr ""
-
-msgid "Protection"
-msgstr "Kill védelem"
-
-#, fuzzy, c-format
-msgid "Protection is now off for %s."
-msgstr "Protection is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s, with a reduced delay."
-msgstr "Protection is now ON for %s, with a reduced delay."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s, with no delay."
-msgstr "Protection is now ON for %s, with no delay."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s."
-msgstr "Protection is now ON for %s."
-
-#, fuzzy
-msgid ""
-"Puts an AKILL for every nick on the specified channel. It\n"
-"uses the entire real ident@host for every nick, and\n"
-"then enforces the AKILL."
-msgstr ""
-"Syntax: CHANKILL [+lejárat] #szobaindok\n"
-"Akillre tesz minden nicket az adott csatornán. Ez a létezo\n"
-"és teljesen valós ident@host maszkot használja, minden \n"
-"nick esetében végrehajtja az AKILLt."
-
-#, fuzzy
-msgid "Quick protection"
-msgstr "Voices védelme"
-
-msgid "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "RANDOMNEWS { ADD | DEL | LIST } [ szöveg | szám ]"
-
-msgid "REGONLY enforced by "
-msgstr ""
-
-msgid "RESTRICTED enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "REVOKE server"
-msgstr "NOOP {SET|REVOKE} szerver"
-
-#, c-format
-msgid "Random news item #%d deleted."
-msgstr "Random news tétel #%d törölve."
-
-#, fuzzy, c-format
-msgid "Random news item #%s not found!"
-msgstr "Random news tétel #%d nem található!"
-
-msgid "Random news items:"
-msgstr "Véletlenszerű hírek listája:"
-
-#, fuzzy
-msgid "Read a memo or memos"
-msgstr " READ Elolvassa a megadott üzenete(ke)t"
-
-#, fuzzy
-msgid "Real name"
-msgstr "Valódi neve: %s"
-
-#, fuzzy
-msgid "Realname"
-msgstr "Valódi neve: %s"
-
-msgid "Reason"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Reason for %s updated."
-msgstr "A megadott csatorna %s successora törölve."
-
-msgid ""
-"Recovers your nick from another user or from services.\n"
-"If services are currently holding your nick, the hold\n"
-"will be released. If another user is holding your nick\n"
-"and is identified they will be killed (similar to the old\n"
-"GHOST command). If they are not identified they will be\n"
-"forced off of the nick."
-msgstr ""
-
-#, fuzzy
-msgid "Redefine the meanings of access levels"
-msgstr " LEVELS Átállíthatod a szoba hozzáférési szintjeit"
-
-#, fuzzy
-msgid "Regains control of your nick"
-msgstr " RELEASE Visszaadja a neved a RECOVER után"
-
-#, fuzzy
-msgid "Regex is disabled."
-msgstr "%s is enable"
-
-#, c-format
-msgid ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your mask in // if this is desired."
-msgstr ""
-
-#, c-format
-msgid ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your pattern in // if this is desired."
-msgstr ""
-
-#, fuzzy
-msgid "Register a channel"
-msgstr " REGISTER Nicknév regisztráció"
-
-#, fuzzy
-msgid "Register a nickname"
-msgstr " REGISTER Nicknév regisztráció"
-
-#, fuzzy
-msgid "Registered"
-msgstr "Regisztrálás ideje: %s"
-
-#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered only enforced on %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which is optional, is a\n"
-"general description of the channel's purpose.\n"
-" \n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel."
-msgstr ""
-"Syntax: REGISTER #szoba leírás\n"
-"\n"
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which must be included, is a\n"
-"general description of the channel's purpose.\n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel.\n"
-"See the ACCESS command (/msg %s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname. If you haven't,\n"
-"/msg %s HELP for information on how to do so."
-
-#, fuzzy, c-format
-msgid ""
-"Registers your nickname in the %s database. Once\n"
-"your nick is registered, you can use the SET and ACCESS\n"
-"commands to configure your nick's settings as you like\n"
-"them. Make sure you remember the password you use when\n"
-"registering - you'll need it to make changes to your nick\n"
-"later. (Note that case matters! ANOPE, Anope, and\n"
-"anope are all different passwords!)\n"
-" \n"
-"Guidelines on choosing passwords:\n"
-" \n"
-"Passwords should not be easily guessable. For example,\n"
-"using your real name as a password is a bad idea. Using\n"
-"your nickname as a password is a much worse idea ;) and,\n"
-"in fact, %s will not allow it. Also, short\n"
-"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
-"Finally, the space character cannot be used in passwords."
-msgstr ""
-"Syntax: REGISTER jelszó [email]\n"
-"\n"
-"Regisztrálja a nickneved a %s adatbázisába. Amint a nicked\n"
-"regisztráltad, használhatod a SET és ACCESS parancsokat,\n"
-"hogy konfiguráljad a nicked beállításait. Olyan jelszót \n"
-"válassz, amire emlékezni fogsz, hogy használni tudd a neved\n"
-"és a beállításokat eszközölhesd. Később szükséged lehet a\n"
-"nickeddel kapcsolatos beállítások végrehajtására.\n"
-"(Jegyzet: PROBLÉMÁT OKOZHAT FIDO, Fido, és fido\n"
-"mind különböző jelszavak!)\n"
-"Útikalaúz jelszó választáshoz:\n"
-"\n"
-"A jelszavad ne legyen könnyen kitalálható. Például az\n"
-"általad használt valósnevet megadni jelszónak rossz ötlet.\n"
-"A nickneved használni jelszónak még rosszabb ötlet ;) és\n"
-"a %s nem is engedi. A rövid jelszavak is rosszak a védelem\n"
-"szempontjából, ezért válassz legalább 5 karakter hosszút.\n"
-"Végezetül ne használhatsz szóközt a jelszóban.\n"
-"\n"
-"Aze-mail paraméter megadás lehetséges, megadásakor\n"
-"beállítja a nickedhez. Megadása a legtöbb hálózaton\n"
-"szükséges. Az e-mail címed nem kerül harmadik személy\n"
-"tudtára, bizalmasan kezeljük.\n"
-"\n"
-"Ez a parancs létrehoz egy új csoportot a nickeddel, ami\n"
-"lehetővé teszi számodra, hogy másik nickeket regisztrálva\n"
-"megoszthasd a hozzáféréseidet és beállításaidat a nickjeid\n"
-"között. Bővebb információkért írd be: /msg %s HELP GROUP"
-
-#, fuzzy
-msgid "Registration is currently disabled."
-msgstr "Sajnálom, a csatorna regisztráció jelenleg szünetel."
-
-#, fuzzy
-msgid "Regulate the use of critical commands"
-msgstr " PEACE Szabályozza a kritikus parancsok használatát"
-
-#, fuzzy
-msgid "Reject the requested vHost for the given nick."
-msgstr " STATUS Returns the owner status of the given nickname"
-
-#, fuzzy
-msgid "Reject the requested vHost of a user"
-msgstr " DEL Törli egy felhasználónak a vhostját"
-
-#, fuzzy
-msgid "Releases a suspended channel"
-msgstr " UNSUSPEND Törli a suspendet a csatornáról."
-
-#, fuzzy
-msgid ""
-"Releases a suspended channel. All data and settings\n"
-"are preserved from before the suspension."
-msgstr ""
-"Syntax: UNSUSPEND #szoba\n"
-"\n"
-"Törli a suspendet a csatornáról. Összes adat és beállítás\n"
-"megőrizve a suspend használat előttröl.\n"
-"\n"
-"Korlátozva Szervíz adminnak."
-
-#, fuzzy
-msgid "Reload a module"
-msgstr " MODLOAD Betölti a modult"
-
-#, fuzzy
-msgid "Reload services' configuration file"
-msgstr " RELOAD Újratölti a szervíz Konfigurációs fájlját"
-
-#, fuzzy
-msgid "Remove a nick from a group"
-msgstr " UNGROUP Remove a nick from a group"
-
-#, fuzzy
-msgid "Remove all bans preventing a user from entering a channel"
-msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-
-#, fuzzy
-msgid "Remove all operators from a server remotely"
-msgstr ""
-" NOOP Ideiglenesen törli az összes O:line-t a szerver\n"
-" távollétében"
-
-#, fuzzy, c-format
-msgid "Removed IP %s from %s."
-msgstr "\tRögzített módok: %s"
-
-#, c-format
-msgid "Removed server %s from zone %s."
-msgstr ""
-
-#, c-format
-msgid "Removed server %s."
-msgstr ""
-
-#, c-format
-msgid ""
-"Removes %s status from the selected nick on a channel. If nick is\n"
-"not given, it will de%s you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Removes %s status from you or the specified nick on a channel"
-msgstr " OP Gives Op status to a selected nick on a channel"
-
-#, fuzzy
-msgid "Removes a selected nicks status from a channel"
-msgstr " KICK Kicks a selected nick from a channel"
-
-msgid ""
-"Removes a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is removed. If channel is omitted then\n"
-"your channel status is removed on every channel you are in."
-msgstr ""
-
-#, c-format
-msgid "Removing %s because %s covers it."
-msgstr ""
-
-#, fuzzy
-msgid "Repeat kicker"
-msgstr "\tIsmétlésért kirúgás: %s"
-
-#, fuzzy
-msgid "Request a vHost for your nick"
-msgstr "Nincs beállítva email cím a nevedhez."
-
-msgid ""
-"Request the given vHost to be activated for your nick by the\n"
-"network administrators. Please be patient while your request\n"
-"is being considered."
-msgstr ""
-
-#, fuzzy
-msgid "Resend registration confirmation email"
-msgstr " RELOAD Újratölti a szervíz Konfigurációs fájlját"
-
-#, fuzzy
-msgid "Restrict access to the channel"
-msgstr " RESTRICTED Restrict access to the channel"
-
-#, fuzzy
-msgid "Restricted access"
-msgstr "Korlátozott hozzáférés"
-
-#, fuzzy, c-format
-msgid "Restricted access option for %s is now off."
-msgstr "Restricted access option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Restricted access option for %s is now on."
-msgstr "Restricted access option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Restricted enforced on %s."
-msgstr "Korlátozott hozzáférés"
-
-#, fuzzy
-msgid "Retain modes when channel is not in use"
-msgstr " KEEPTOPIC Topic megtartása ha a szoba nincs használatban"
-
-#, fuzzy
-msgid "Retain topic when channel is not in use"
-msgstr " KEEPTOPIC Topic megtartása ha a szoba nincs használatban"
-
-#, fuzzy
-msgid "Retrieve the password for a nickname"
-msgstr ""
-" GETPASS Kiirja a jeszavát a nicknévnek\n"
-" (encryption esetén nem használható)"
-
-msgid "Retrieves the vhost requests"
-msgstr ""
-
-#, fuzzy
-msgid "Returns the key of the given channel"
-msgstr " GETKEY Returns the key of the given channel"
-
-#, fuzzy
-msgid "Returns the key of the given channel."
-msgstr " GETKEY Returns the key of the given channel"
-
-#, fuzzy
-msgid "Returns the matching accounts that used given email."
-msgstr " GETKEY Returns the key of the given channel"
-
-#, fuzzy
-msgid "Returns the owner status of the given nickname"
-msgstr " STATUS Returns the owner status of the given nickname"
-
-#, fuzzy
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Syntax: GETPASS nicknév\n"
-"\n"
-"Visszadja a megadott nicknév jelszavát. Jegyzet Ezt \n"
-"a parancsot amaikor használod, üzenetet küld arról \n"
-"hogy ki használta és kinek a jelszavát kérte le. \n"
-"Naplózva lesz és WALLOPS/GLOBOPS üzenetben is megjelenik.\n"
-"\t\n"
-"Korlátozva Szervíz adminokra.\n"
-"\n"
-"A parancs nem elérhető, ha az encryption használatban van."
-
-#, fuzzy
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
-msgstr ""
-"Syntax: STATUS nicknév...\n"
-"\n"
-"A következőket kapod, ha a nicknévre, amit a felhasználó \n"
-"használ azonosította magát, mint tulajdonos. \n"
-"Az eredmény formája a következő:\n"
-"\n"
-"\tnicknév státusz-kód account\n"
-"\n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-"\n"
-" 0 - Nincs ilyen user online vagy a nick nem regisztrált\n"
-" 1 - A felhasználó nem azonosított be, mint a nick tulajdonosa\n"
-" 2 - A felhasználó beazonosított, mint tulajdonos de csak a \n"
-" hozzáférési lista alapján\n"
-" 3 - A felhasználó beazonosított tulajdonosként a jelszavával\n"
-" \n"
-"Tizenhat nicknév küldhető el parancsonként; a többit \n"
-"figyelmen kívül hagyja. If no nickname is given, your status\n"
-"will be returned."
-
-#, fuzzy
-msgid "Reverses kicker"
-msgstr "\tVisszafelé írásért kirúgás: %s"
-
-#, fuzzy
-msgid "Reverses the effect of the IDENTIFY command"
-msgstr " LOGOUT Reverses the effect of the IDENTIFY command"
-
-#, fuzzy
-msgid "SET server"
-msgstr "NOOP {SET|REVOKE} szerver"
-
-msgid "SET server.name option value"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "SSL certificate fingerprint accepted, you are now identified to %s."
-msgstr "Jelszavad elfogadva - azonosítás sikeres."
-
-#, fuzzy
-msgid "SSL certificate fingerprint accepted, you are now identified."
-msgstr "Jelszavad elfogadva - azonosítás sikeres."
-
-#, c-format
-msgid "SSL only enforced on %s."
-msgstr ""
-
-msgid "SSLONLY enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "Save databases and restart Services"
-msgstr " RESTART Menti az adatbázist, és újraindítja a szervízt"
-
-msgid "Searches logs for a matching pattern"
-msgstr ""
-
-#, fuzzy
-msgid "Secure founder"
-msgstr "Founderjog védelme"
-
-#, fuzzy, c-format
-msgid "Secure founder option for %s is now off."
-msgstr "Secure founder option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure founder option for %s is now on."
-msgstr "Secure founder option for %s is now ON."
-
-#, fuzzy
-msgid "Secure ops"
-msgstr "Opjog védelme"
-
-#, fuzzy, c-format
-msgid "Secure ops option for %s is now off."
-msgstr "Secure ops option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure ops option for %s is now on."
-msgstr "Secure ops option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now off."
-msgstr "Secure option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now on."
-msgstr "Secure option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Secure option is now off for %s."
-msgstr "Secure option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Secure option is now on for %s."
-msgstr "Secure option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Secureops enforced on %s."
-msgstr "Secure option is now ON for %s."
-
-msgid "Security"
-msgstr "Biztonság"
-
-#, fuzzy, c-format
-msgid ""
-"See %s%s HELP %s for more information\n"
-"about the access list."
-msgstr ""
-"Írd be: /msg %s HELP SET opció bővebb információért az\n"
-"adott opcióról."
-
-#, fuzzy, c-format
-msgid ""
-"See %s%s HELP %s for more information\n"
-"about the flags system."
-msgstr ""
-"Írd be: /msg %s HELP SET opció bővebb információért az\n"
-"adott opcióról."
-
-#, fuzzy
-msgid "Send a memo to a nick or channel"
-msgstr " SEND Üzenetet küld egy nicknek vagy csatornára"
-
-#, fuzzy
-msgid "Send a memo to all opers/admins"
-msgstr " STAFF Memo küldése minden opernek/adminnak."
-
-#, fuzzy
-msgid "Send a memo to all registered users"
-msgstr " SENDALL Memo küldése minden regisztrált felhasználónak."
-
-#, fuzzy
-msgid "Send a message to all users"
-msgstr " GLOBAL Üzenetet küld összes felhasználónak"
-
-#, fuzzy
-msgid "Sender"
-msgstr "Founderjog védelme"
-
-#, fuzzy
-msgid "Sends a memo and requests a read receipt"
-msgstr " RSEND Memo üzenetet küld és olvasási visszaigazolást kér"
-
-#, fuzzy
-msgid ""
-"Sends a passcode to the nickname with instructions on how to\n"
-"reset their password. Email must be the email address associated\n"
-"to the nickname."
-msgstr ""
-"Syntax: RESETPASS nickname\n"
-"\n"
-"Sends a code key to the nickname with instructions on how to\n"
-"reset their password."
-
-#, fuzzy
-msgid "Sends all registered users a memo containing memo-text."
-msgstr ""
-"Syntax: SENDALL memo-üzenet\n"
-"\n"
-"Memo üzenet küldése minden regisztrált felhasználónak."
-
-#, fuzzy
-msgid "Sends all services staff a memo containing memo-text."
-msgstr ""
-"Syntax: STAFF memo-üzenet\n"
-"\n"
-"Memo üzenet küldése az opereknek/adminoknak."
-
-#, fuzzy
-msgid ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered."
-msgstr ""
-"Syntax: SEND { nick | #szoba } memo-szöveg\n"
-"\n"
-"Üzenetet küld a megnevezett nicknek vagy csatornára\n"
-"a üzenet-szövegét tartalmazva. Amikor nicknévnek küldesz\n"
-"a címzett kap egy üzenetet az új üzenet érkezéséről\n"
-"A címzett csatornának vagy nicknévnek regisztráltnak kell\n"
-"lennie."
-
-#, fuzzy
-msgid ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered.\n"
-"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
-"has been read."
-msgstr ""
-"Syntax: RSEND {nick | #szoba} memo-üzenet\n"
-"\n"
-"Memot küld a megadott névnek, szobának a memo-üzenet\n"
-"tartalmával. Ha nicknévnek küldöd, akkor értesítést fog\n"
-"kapni, hogy új üzenete érkezett. A cél nicknévnek vagy\n"
-"csatornának regisztráltnak kell lennie.\n"
-"Amint a címzett elolvasta a memot, egy automatikus értesítést\n"
-"fog kapni a feladó arról, hogy az üzenetét elolvasták."
-
-#, fuzzy
-msgid ""
-"Sends you the text of the memos specified. If LAST is\n"
-"given, sends you the memo you most recently received. If\n"
-"NEW is given, sends you all of your new memos. If ALL is\n"
-"given, sends you all of your memos. Otherwise, sends you\n"
-"memo number num. You can also give a list of numbers,\n"
-"as in this example:\n"
-" \n"
-" READ 2-5,7-9\n"
-" Displays memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Syntax: READ [#szoba] {sorszám| list| LAST | NEW}\n"
-"\n"
-"Elküldi a megadott üzenetek tartalmát. A LAST opcióval\n"
-"megjeleníti a legutolsó üzenetet. A NEW opcióval\n"
-"minden új üzenetet. Egyébként a megadott számú üzenetet.\n"
-"Megadhatsz számlistát is, mint a LIST parancsnál.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tREAD 2-5,7-9\n"
-"\t\tMegjeleníti 2 és 5, a 7 és 9 között a memo üzeneteket"
-
-#, fuzzy
-msgid "Server"
-msgstr "NOOP {SET|REVOKE} szerver"
-
-#, fuzzy, c-format
-msgid "Server %s added to zone %s."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s already exists."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy, c-format
-msgid "Server %s does not exist."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s has no configured IPs."
-msgstr "A %s nicknevet dropoltad."
-
-#, fuzzy, c-format
-msgid "Server %s is already in zone %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "Server %s is already pooled."
-msgstr "Module %s is already loaded."
-
-#, fuzzy, c-format
-msgid "Server %s is not currently linked."
-msgstr "%s jelenleg online."
-
-#, fuzzy, c-format
-msgid "Server %s is not in zone %s."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s is not linked to the network."
-msgstr "Nincsen bot kijelölve %s szobában többet."
-
-#, fuzzy, c-format
-msgid "Server %s is not pooled."
-msgstr " %s (does not expire)"
-
-#, c-format
-msgid "Server %s must be quit before it can be deleted."
-msgstr ""
-
-#, fuzzy
-msgid "Servers"
-msgstr "NOOP {SET|REVOKE} szerver"
-
-#, c-format
-msgid "Servers found: %d"
-msgstr "Servers found: %d"
-
-#, fuzzy
-msgid "Service"
-msgstr "Servers found: %d"
-
-#, fuzzy, c-format
-msgid "Service's hold on %s has been released."
-msgstr "A Services rendelkezésedre bocsájtotta a nicket."
-
-#, fuzzy
-msgid "Services Operator commands"
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "Services are in DefCon mode, please try again later."
-msgstr "Szervíz Defcon módban fut, próbáld később."
-
-#, fuzzy
-msgid "Services are in read-only mode!"
-msgstr "Szervíz most  csak olvas módban."
-
-#, fuzzy, c-format
-msgid "Services are now at DEFCON %d."
-msgstr "Szervíz új DEFCON szintje %d"
-
-#, fuzzy, c-format
-msgid "Services are now in debug mode (level %d)."
-msgstr "Szervíz most debug módban (szint: %d)."
-
-#, fuzzy
-msgid "Services are now in debug mode."
-msgstr "Szervíz most debug módban fut."
-
-msgid "Services are now in expire mode."
-msgstr "Szervíz elévülő módban van."
-
-msgid "Services are now in no expire mode."
-msgstr "Szervíz nem elévülő módban van."
-
-#, fuzzy
-msgid "Services are now in non-debug mode."
-msgstr "Szervíz most már nem fut debug módban."
-
-msgid "Services are now in read-only mode."
-msgstr "Szervíz most  csak olvas módban."
-
-msgid "Services are now in read-write mode."
-msgstr "Szervíz most olvas ír módban."
-
-msgid "Services have been configured to not send mail."
-msgstr "A Szervíz úgy van beállítva, hogy nem küld mailt."
-
-#, fuzzy
-msgid "Services ignore list:"
-msgstr " IGNORE Módosítja a Szervíz mellőzési listáját"
-
-#, fuzzy
-msgid ""
-"Services is unable to change modes. Are your servers' U:lines configured "
-"correctly?"
-msgstr ""
-"Szervíz nem tudja változtatni a módokat.\n"
-"A szerverek U:lines beállitása helyes?"
-
-#, fuzzy, c-format
-msgid "Services up %s."
-msgstr "Servers found: %d"
-
-#, fuzzy, c-format
-msgid "Services will from now on set status modes on %s in channels."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Services will no longer automatically give modes to users in %s."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Services will no longer set status modes on %s in channels."
-msgstr "Services will no longer autoop %s in channels."
-
-#, fuzzy, c-format
-msgid "Services will now automatically give modes to users in %s."
-msgstr "Services will now autoop %s in channels."
-
-#, c-format
-msgid "Services will now reply to %s with messages."
-msgstr "Services will now reply to %s with messages."
-
-#, c-format
-msgid "Services will now reply to %s with notices."
-msgstr "Services will now reply to %s with notices."
-
-#, fuzzy
-msgid "Services' configuration has been reloaded."
-msgstr "Szervíz konfigurációs fájl újratöltve."
-
-msgid "Session"
-msgstr ""
-
-#, c-format
-msgid "Session limit for %s set to %d."
-msgstr "Session korlát %s részére %d-re állítva."
-
-msgid "Session limiting is disabled."
-msgstr "Session korlátozás tiltva."
-
-#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, fuzzy
-msgid "Set SET-options on another nickname"
-msgstr " SASET Set SET-options on another nickname"
-
-#, fuzzy
-msgid "Set channel options and information"
-msgstr " SET Beállíthatod a csatornád opcióit"
-
-#, fuzzy
-msgid "Set how Services make bans on the channel"
-msgstr " BANTYPE A banolás tipusának beállítása"
-
-#, fuzzy
-msgid "Set options related to memos"
-msgstr " SET Üzenetekkel kapcsolatos beállításokat hajt végre"
-
-#, fuzzy
-msgid "Set options, including kill protection"
-msgstr " SET Opciók beállítása, például kill védelem"
-
-#, fuzzy
-msgid "Set the channel as permanent"
-msgstr " PERSIST Set the channel as permanent"
-
-#, fuzzy
-msgid "Set the channel description"
-msgstr " DESC A szobameghatározás állítás"
-
-#, fuzzy
-msgid "Set the display of your group in Services"
-msgstr " DISPLAY Set the display of your group in Services"
-
-#, fuzzy
-msgid "Set the founder of a channel"
-msgstr " FOUNDER A founder megváltoztatása"
-
-#, fuzzy
-msgid "Set the language Services will use when messaging you"
-msgstr " LANGUAGE A szervíz nyelvezetének megválasztása"
-
-#, fuzzy
-msgid "Set the nickname password"
-msgstr " PASSWORD Set the nickname password"
-
-#, fuzzy
-msgid "Set the successor for a channel"
-msgstr " SUCCESSOR A successor megadása"
-
-#, fuzzy
-msgid "Set the vhost for all nicks in a group"
-msgstr " SETALL Beállítja a vhosztot összes nicknek a csoportban"
-
-#, fuzzy
-msgid "Set the vhost of another user"
-msgstr " SET Beállít egy vhosztot a felhasználónak"
-
-#, fuzzy
-msgid "Set various global Services options"
-msgstr " SET Beállítja szervíz általános változóit"
-
-#, fuzzy
-msgid "Set your nickname password"
-msgstr " PASSWORD Set your nickname password"
-
-#, fuzzy, c-format
-msgid ""
-"Sets the AMSG kicker on or off. When enabled, the bot will\n"
-"kick users who send the same message to multiple channels\n"
-"where %s bots are.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before they get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-
-#, fuzzy, c-format
-msgid ""
-"Sets the bad words kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who say certain words\n"
-"on the channels.\n"
-"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
-"more information.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szoba BADWORDS {ON|OFF} [ttb]\n"
-"\n"
-"Beállítja a csúnyaszavak miatti kirúgást. Ha engedélyezve\n"
-"van, akkor a bot kirúgja azt, aki kiejt egy olyan szót,\n"
-"ami szerepel a csúnyaszavak listáján.\n"
-"\n"
-"A csúnyaszavak listáját a csatornádhoz neked kell megadnod\n"
-"A BADWORDS paranccsal. Írd be /msg %s HELP BADWORDS \n"
-"bővebb információkért.\n"
-"\n"
-"A ttb a banolás elotti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy
-msgid ""
-"Sets the ban type that will be used by services whenever\n"
-"they need to ban someone from your channel.\n"
-" \n"
-"Bantype is a number between 0 and 3 that means:\n"
-" \n"
-"0: ban in the form *!user@host\n"
-"1: ban in the form *!*user@host\n"
-"2: ban in the form *!*@host\n"
-"3: ban in the form *!*user@*.domain"
-msgstr ""
-"Syntax: %s #szoba BANTYPE bantípus\n"
-"\n"
-"A banolás típusának beállítása, amit a Services akkor fog\n"
-"használni, ha valakit banolni kell a csatornáról.\n"
-"\n"
-"A bantípus egy szám 0 és 3 között a jelentése:\n"
-"\n"
-"0: *!user@host formátumú tiltás\n"
-"1: *!*user@host formátumú tiltás\n"
-"2: *!*@host formátumú tiltás\n"
-"3: *!*user@*.domain formátumú tiltás"
-
-#, fuzzy
-msgid ""
-"Sets the bolds kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use bolds.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szoba BOLDS { ON|OFF } [ ttb ]\n"
-"\n"
-"Beállítja a félkövér írásért járó kirúgást.\n"
-"Ha engedélyezve van akkor a bot kirúg a félkövér betűkért.\n"
-"\n"
-"A ttb a banolás elotti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy, c-format
-msgid ""
-"Sets the caps kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are talking in\n"
-"CAPS.\n"
-"The bot kicks only if there are at least min caps\n"
-"and they constitute at least percent%% of the total\n"
-"text line (if not given, it defaults to 10 characters\n"
-"and 25%%).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szobaCAPS { ON|OFF } [ ttb [ min [ százalék ]]]\n"
-"\n"
-"Beállítja a túlzott caps miatt járó kirúgást.\n"
-"Ha engedélyezve van, akkor a bot kirúgja a \"kiabálókat\".\n"
-"\n"
-"A bot csak akkor rúgja ki a usert, ha legalább min számú\n"
-"betű van és ez legalább százaléka%% az összes szövegnek\n"
-"a sorban (ha nincs megadva, akkor 10 karakter a min és\n"
-"annak legalább a 25%-a az alapbeállítás)\n"
-"\n"
-"A ttb a banolás előtti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy
-msgid ""
-"Sets the colors kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use colors.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szoba COLORS { ON|OFF } [ ttb ]\n"
-"\n"
-"Beállítja a szines írásért járó kirúgást.\n"
-"Ha engedélyezve van akkor a bot kirúgja a színesen írókat.\n"
-"\n"
-"A ttb a banolás előtti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy
-msgid ""
-"Sets the description for the channel, which shows up with\n"
-"the LIST and INFO commands."
-msgstr ""
-"Syntax: %s #szoba DESC leírás\n"
-"\n"
-"Beállítható a szoba általános meghatározása, ami látszódni\n"
-"fog a LIST és INFO parancs használata esetén."
-
-#, fuzzy
-msgid ""
-"Sets the flood kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are flooding\n"
-"the channel using at least ln lines in secs seconds\n"
-"(if not given, it defaults to 6 lines in 10 seconds).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szoba FLOOD { ON|OFF } [ ttb [ sor [ mp ]]]\n"
-"\n"
-"Beállítja a flood miatti kirúgást. Ha engedélyezve van\n"
-"akkor a bot kirúgja a floodoló usereket, ha legalább\n"
-"sor számú sort írtak mp másodpercnyi idő alatt.\n"
-"(ha nincs megadva, akkor 6 sor és 10 mp alatt).\n"
-"\n"
-"A ttb a banolás előtti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy
-msgid ""
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-
-#, fuzzy
-msgid ""
-"Sets the repeat kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are repeating\n"
-"themselves num times (if num is not given, it\n"
-"defaults to 3).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szoba REPEAT { ON|OFF } [ ttb [ szám ]]\n"
-"\n"
-"Beállítja az ismétlés miatti kirúgást. Ha engedélyezve\n"
-"van az opció, akkor a bot kirúgja az önmagukat ismétlő\n"
-"usereket, ha szám alkalommal ismételtek. \n"
-"(Ha nem adsz meg értéket, akkor az érték 3 lesz)\n"
-"\n"
-"A ttb a banolás előtti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy
-msgid ""
-"Sets the reverses kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use reverses.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szobaREVERSES { ON|OFF } [ ttb ]\n"
-"\n"
-"Beállítja a visszafelé írásért járó kirúgást.\n"
-"Ha engedélyezve van akkor a bot kirúgja a reverse írókat.\n"
-"\n"
-"A ttb a banolás előtti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot.\t"
-
-#, fuzzy
-msgid ""
-"Sets the underlines kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use underlines.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK #szobaUNDERLINES { ON|OFF } [ ttb ]\n"
-"\n"
-"Beállítja az aláhúzott írásért járó kirúgást.\n"
-"Ha engedélyezve van akkor a bot kirúgja az aláhúzva írókat\n"
-"\n"
-"A ttb a banolás előtti kickek száma.\n"
-"Ha nem adod meg, akkor csak kirúgást eszközöl a bot.\n"
-"Ha megadod a ttb-t, akkor x kirúgás után banol a bot."
-
-#, fuzzy
-msgid ""
-"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
-"using SETALL <nick> <ident>@<hostmask> will set idents\n"
-"for users as well as vhosts.\n"
-"* NOTE, this will not update the vhost for any nicks\n"
-"added to the group after this command was used."
-msgstr ""
-"Syntax: SETALL <nick> <hosztmaszk>.\n"
-"Beállítja a vhosztot összes nick részére aki a csoportban \n"
-"van. Ha az IRCD támogatja a vIdent, akkor használja a \n"
-"settall <nick> <ident>@<hosztnév> parancsot, ez beállítja\n"
-"az adott identet és hosztot az összes tag részére vhosztként.\n"
-"*Jegyzet: ez nem fogja frissíteni a vhostot azoknak, akik\n"
-"a nickeket a csoportban a parancs után jegyezték\t\n"
-"Korlátozva Hoszt változtatókra."
-
-#, fuzzy
-msgid ""
-"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
-"SET <nick> <ident>@<hostmask> set idents for users as\n"
-"well as vhosts."
-msgstr ""
-"Syntax: SET <nick> <hostmask>.\n"
-"\n"
-"Beállítja vhostnak a nick részére a hosztmaszkot.\n"
-"Ha az IRCD támogatja a vIdentet használd a SET\n"
-"<nick> <ident>@<hostmask>, beállitja az identet\n"
-" és a hosztot a nick vhosztjaként.\n"
-"\n"
-"Korlátozva Hoszt változtatókra."
-
-#, fuzzy
-msgid ""
-"Sets various global Services options. Option names\n"
-"currently defined are:\n"
-" READONLY Set read-only or read-write mode\n"
-" DEBUG Activate or deactivate debug mode\n"
-" NOEXPIRE Activate or deactivate no expire mode\n"
-" SUPERADMIN Activate or deactivate super admin mode\n"
-" LIST List the options"
-msgstr ""
-"Syntax: SET opció beállítás\n"
-"\n"
-"Beállítja a Services általános opcióit.\n"
-"A lehetséges opciók:\n"
-" READONLY Csak-olvasás vagy olvasás-írás mód beállítása\n"
-" LOGCHAN Kiírja a naplózott üzeneteket a csatornára\n"
-" DEBUG Bekapcsolja/kikapcsolja a debug módot\n"
-" NOEXPIRE Bekapcsolja/kikapcsolja a nem elévülő módot\n"
-" SUPERADMIN Bekapcsolja/kikapcsolja a super-admin módot\n"
-" IGNORE Activate or deactivate ignore mode\n"
-" LIST List the options\n"
-"\n"
-"Korlátozva Szervíz adminnak."
-
-#, fuzzy, c-format
-msgid ""
-"Sets various memo options. option can be one of:\n"
-" \n"
-" NOTIFY Changes when you will be notified about\n"
-" new memos (only for nicknames)\n"
-" LIMIT Sets the maximum number of memos you can\n"
-" receive\n"
-" \n"
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
-msgstr ""
-"Syntax: SET opció paraméterek\n"
-"\n"
-"Beállít különbözo memo opciókat. \n"
-"Az opció lehet az alábbiak egyike:\n"
-"\n"
-" NOTIFY Itt állíthatod be, ha figyelmeztetést szeretnél\n"
-" kapni az új üzenetekrol (csak nicknevehez)\n"
-" LIMIT Beállítja a maximális üzenetek számát\n"
-"\n"
-"További információért írd be: /msg %s HELP SET opció"
-
-#, fuzzy
-msgid "Sets various nickname options. option can be one of:"
-msgstr ""
-"Syntax: SET opció paraméterek\n"
-"\n"
-"Beállítható nicknév opciók. Az opció ezek egyike lehet:"
-
-msgid ""
-"Sets whether services should set channel status modes on you automatically."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Sets whether the given channel will expire. Setting this\n"
-"to ON prevents the channel from expiring."
-msgstr ""
-"Syntax: SET #szoba NOEXPIRE {ON | OFF}\n"
-"\n"
-"Beállítja a szoba elévülését. Beállitva az\n"
-"ON paranmétert megelőzi az elévülő csatornákat.\n"
-"\n"
-"Korlátozva Szervíz adminnak."
-
-#, fuzzy, c-format
-msgid ""
-"Sets whether the given nickname will be given its status modes\n"
-"in channels automatically. Set to ON to allow %s\n"
-"to set status modes on the given nickname automatically when it\n"
-"is entering channels. Note that depending on channel settings\n"
-"some modes may not get set automatically."
-msgstr ""
-"Syntax: SASET nickname AUTOOP {ON | OFF}\n"
-"\n"
-"Sets whether the given nickname will be opped automatically.\n"
-"Set to ON to allow ChanServ to op the given nickname \n"
-"automatically when joining channels."
-
-#, fuzzy
-msgid ""
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
-msgstr ""
-"Syntax: SASET nickname NOEXPIRE {ON | OFF}\n"
-"\n"
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
-
-#, fuzzy, c-format
-msgid ""
-"Sets whether you will be given your channel status modes automatically.\n"
-"Set to ON to allow %s to set status modes on you automatically\n"
-"when entering channels. Note that depending on channel settings some modes\n"
-"may not get set automatically."
-msgstr ""
-"Syntax: SET AUTOOP {ON | OFF}\n"
-"\n"
-"Sets whether you will be opped automatically. Set to ON to \n"
-"allow ChanServ to op you automatically when entering channels."
-
-#, fuzzy, c-format
-msgid ""
-"Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
-msgstr ""
-"%s beállítás nem ismert. Írd be /msg %s HELP LEVELS DESC\n"
-"az érvényes beállítások listájának megtekintéséhez. "
-
-#, fuzzy
-msgid "Setting for DEBUG must be ON, OFF, or a positive number."
-msgstr "A DEBUG beállításhoz kell ON,/OFF,/ pozitív szám."
-
-#, fuzzy
-msgid "Setting for NOEXPIRE must be ON or OFF."
-msgstr "Az NOEXPIRE beállításhoz kell ON vagy OFF."
-
-#, fuzzy
-msgid "Setting for READONLY must be ON or OFF."
-msgstr "READONLY beállitáshoz kell lenni ON vagy OFF."
-
-#, fuzzy
-msgid "Setting for super admin must be ON or OFF."
-msgstr "READONLY beállitáshoz kell lenni ON vagy OFF."
-
-#, fuzzy
-msgid "Should services automatically give status to users"
-msgstr " AUTOOP Should services op you automatically. "
-
-#, fuzzy
-msgid "Show status of Services and network"
-msgstr " STATS Mutatja a Szervít és hálózat állapotát"
-
-#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr ""
-
-#, fuzzy
-msgid "Sign kicks that are done with the KICK command"
-msgstr " SIGNKICK Sign kickek, melyek a KICK paranccsal történnek"
-
-#, fuzzy, c-format
-msgid "Signed kick option for %s is now off."
-msgstr "Signed kick option for %s is now ON."
-
-#, fuzzy, c-format
-msgid ""
-"Signed kick option for %s is now on, but depends of the\n"
-"level of the user that is using the command."
-msgstr ""
-"Signed kick option for %s is now ON, but depends of the\n"
-"level of the user that is using the command."
-
-#, fuzzy, c-format
-msgid "Signed kick option for %s is now on."
-msgstr "Signed kick option for %s is now ON."
-
-msgid "Signed kicks"
-msgstr "Signed kicks"
-
-#, fuzzy, c-format
-msgid "Sorry, %s currently has too many memos and cannot receive more."
-msgstr "%s túl sok üzenettel rendelkezik, és nem fogadhat többet."
-
-#, c-format
-msgid "Sorry, I have not seen %s."
-msgstr ""
-
-#, fuzzy
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr "Csatornán tiltott szaval listájának változtatása letiltva."
-
-#, fuzzy
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr "Bot beállítás időlegesen szünetel."
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "A bot módosítás ideiglenesen szünetel."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr "Bot beállítás időlegesen szünetel."
-
-#, fuzzy
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr "Bot beállítás időlegesen szünetel."
-
-#, fuzzy, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
-msgstr "Csatorna AOP lista módosítás szünetel."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr "A csatorna hozzáférési listájának módosítása szünetel."
-
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr "Csatorna autokick listájának módosítása szünetel."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr "A csatornák regisztrációjának törlése jelenleg szünetel."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Sajnálom, a csatorna regisztráció jelenleg szünetel."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
-msgstr "Kirúgás használata ideiglenesen letiltva."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr "Üzenet opcióinak beállítása szünetel."
-
-#, fuzzy
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr "Üzenet opcióinak beállítása szünetel."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Sajnálom, a nicknevek regisztrációjának törlése szünetel."
-
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Sajnálom, a csoportok használata ideiglenesen le van tiltva."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Sajnálom, a nickregisztráció jelenleg nem működik."
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
-msgstr "Neked csak %d helyed van a csatorna listáján."
-
-#, c-format
-msgid "Sorry, the maximum of %d auto join entries has been reached."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d certificate entries has been reached."
-msgstr "Neked csak %d bejegyzésed lehet a hozzáférési listán."
-
-#, fuzzy, c-format
-msgid "Sorry, the memo ignore list for %s is full."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid ""
-"Sorry, you can only have %d access entries on a channel, including access "
-"entries from other channels."
-msgstr "Neked csak %d helyed van a csatorna listáján."
-
-#, c-format
-msgid "Sorry, you can only have %d autokick masks on a channel."
-msgstr "%d bejegyzésnél nem lehet több a listán."
-
-#, c-format
-msgid "Sorry, you can only have %d bad words entries on a channel."
-msgstr "Csak %d tiltott szó lehet a csatornán."
-
-#, fuzzy, c-format
-msgid "Sorry, you have already exceeded your limit of %d channels."
-msgstr "Csak %d tiltott szó lehet a csatornán."
-
-#, fuzzy, c-format
-msgid "Sorry, you have already reached your limit of %d channels."
-msgstr "Csak %d tiltott szó lehet a csatornán."
-
-msgid "State"
-msgstr ""
-
-msgid "Statistics and maintenance for seen data"
-msgstr ""
-
-msgid "Statistics reset."
-msgstr "Statisztika nullázva."
-
-msgid "Status updated (memos, vhost, chmodes, flags)."
-msgstr "Státusz frissítve (memok, vhost, chmodok, flagek)."
-
-msgid "Stop flooding!"
-msgstr "Ne floodolj!"
-
-msgid "Stop repeating yourself!"
-msgstr "Ne ismételd magad!"
-
-#, fuzzy
-msgid "Stricter control of channel founder status"
-msgstr " SECUREFOUNDER Csatornán a founder státusz szigorú kezelése"
-
-#, fuzzy
-msgid "Stricter control of chanop status"
-msgstr " SECUREOPS A csatornán az op státusz szigorú kezelése"
-
-msgid "Successor"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Successor for %s changed to %s."
-msgstr "A megadott csatorna (%s) új successora: %s."
-
-#, c-format
-msgid "Successor for %s unset."
-msgstr "A megadott csatorna %s successora törölve."
-
-#, fuzzy
-msgid ""
-"Super admin can not be set because it is not enabled in the configuration."
-msgstr "SuperAdmin setting not enabled in services.conf"
-
-#, fuzzy
-msgid "Suspend a given nick"
-msgstr " SUSPEND Suspend a given nick"
-
-#, fuzzy
-msgid "Suspend reason"
-msgstr "JUPE szervernév [leírás]"
-
-msgid "Suspended"
-msgstr ""
-
-msgid "Suspended by"
-msgstr ""
-
-#, fuzzy
-msgid "Suspended on"
-msgstr " SUSPEND Suspend a given nick"
-
-#, fuzzy
-msgid ""
-"Suspends a registered nickname, which prevents it from being used\n"
-"while keeping all the data for that nick. If an expiry is given\n"
-"the nick will be unsuspended after that period of time, else the\n"
-"default expiry from the configuration is used."
-msgstr ""
-"Syntax: SUSPEND #szoba [indok]\n"
-"Elutasít minden szobahasználatot. Lehet törölni a\n"
-"UNSUSPEND paranccsal és akkor használható az öüsszes \n"
-"megörzött szoba adat/beállítás.\n"
-"\n"
-"Indoklást kér némelyik hálózat.\n"
-"\n"
-"Korlátozva Szervíz adminnak."
-
-#, fuzzy
-msgid "Suspension expires"
-msgstr " %s (does not expire)"
-
-#, fuzzy
-msgid "Sync users channel modes"
-msgstr "%s váltóztatott a módodon."
-
-msgid ""
-"Syncs all modes set on users on the channel with the modes\n"
-"they should have based on their access."
-msgstr ""
-
-#, fuzzy
-msgid "Syncs the vhost for all nicks in a group"
-msgstr " GROUP A vhostot a csoport minden tagjára állítja"
-
-msgid "Syntax"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: %s\n"
-" \n"
-"Lists all nicks in your group."
-msgstr ""
-"Syntax: GLIST\n"
-"\n"
-"Listáz minden nicket a csoportodból."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: %s [nickname]\n"
-" \n"
-"Without a parameter, lists all nicknames that are in\n"
-"your group.\n"
-" \n"
-"With a parameter, lists all nicknames that are in the\n"
-"group of the given nick.\n"
-"Specifying a nick is limited to Services Operators."
-msgstr ""
-"Syntax: GLIST [nicknév]\n"
-"\n"
-"Paraméter nélkül, listázza az összes nicknevet \n"
-"a csoportodban.\n"
-"Paraméterrel listázza az összes nicknevet, abból a \n"
-"csoportból ahol az adott nicknév van.\t\n"
-"\n"
-"Ennek a használata korlátozva Szervíz adminra."
-
-#, fuzzy
-msgid ""
-"Syntax: DEBUG {ON | OFF}\n"
-" \n"
-"Sets debug mode on or off.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--debug."
-msgstr ""
-"Syntax: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Bekapcsolja a nem elévülést. A nem elévülő módban nickek,\n"
-"csatornák, akillek és kivételek rakhatóak nem elévülőre is\n"
-"amíg ezt az opciót nem kapcsolod ki.\n"
-"\n"
-"Ez az opció megegyezik a parancs-sorban kiadható opcióval:\n"
-"-noexpire."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIMIT [channel] limit\n"
-" \n"
-"Sets the maximum number of memos you (or the given channel)\n"
-"are allowed to have. If you set this to 0, no one will be\n"
-"able to send any memos to you. However, you cannot set\n"
-"this any higher than %d."
-msgstr ""
-"Syntax: SET LIMIT [#szoba] limit\n"
-"\n"
-"Beállítja, hogy max. hány üzenetet fogadhatsz a nickedre\n"
-"(vagy a csatornára). Ha 0-ra állítod, senki nem\n"
-"küldhet üzenetet a nickedre/csatornára. Mindamellett,\n"
-"nem állíthatod ezt a számot többre, mint %d."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIMIT [user | channel] {limit | NONE} [HARD]\n"
-" \n"
-"Sets the maximum number of memos a user or channel is\n"
-"allowed to have. Setting the limit to 0 prevents the user\n"
-"from receiving any memos; setting it to NONE allows the\n"
-"user to receive and keep as many memos as they want. If\n"
-"you do not give a nickname or channel, your own limit is\n"
-"set.\n"
-" \n"
-"Adding HARD prevents the user from changing the limit. Not\n"
-"adding HARD has the opposite effect, allowing the user to\n"
-"change the limit (even if a previous limit was set with\n"
-"HARD).\n"
-" \n"
-"This use of the SET LIMIT command is limited to Services\n"
-"Operators. Other users may only enter a limit for themselves\n"
-"or a channel on which they have such privileges, may not\n"
-"remove their limit, may not set a limit above %d, and may\n"
-"not set a hard limit."
-msgstr ""
-"Syntax: SET LIMIT [user | #szoba]{korlát|NONE}[HARD]\n"
-"\n"
-"Beállítja egy felhasználó vagy szoba max.fogadható\n"
-"memo üzenetienek számát, ha a limitet 0-ra állitod \n"
-"akkor a felhasználó nem fogadhat üzeneteket.Ha a \n"
-"NONE-vel állítod be akkor annyit fogadhat és tarthat\n"
-"meg amennyit akar.Ha nem adsz meg nicknevet, vagy csatornát\n"
-"akkor a saját korlátaidat állitja.\n"
-"\n"
-"HARD-al hozzáadva nem állíthatja a felhasználó a korlát \n"
-"értékét Ha nem adod hozzá a HARD-ot akkor a felhasználó \n"
-"kedve szerint váltóztathatja a korlát értékét (akkor is ha\n"
-"az előző értéket a HARD-al adtad meg)\n"
-"\n"
-"SET LIMIT parancs használata korlátozható Szervíz\n"
-"adminokra. Egyéb felhasználók csak saját maguknak és a \n"
-"csatornáknak ahol megfelelő hozzáférésük van állíthatnak\n"
-"korlátot de nem törölhetik, és nem állíthatnak %d érték \n"
-"felett valamint HARD korlátot."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIST\n"
-" \n"
-"Display the various %s settings."
-msgstr ""
-"Syntax: SET LIST\n"
-"Display the various %s settings"
-
-#, fuzzy
-msgid ""
-"Syntax: NOEXPIRE {ON | OFF}\n"
-" \n"
-"Sets no expire mode on or off. In no expire mode, nicks,\n"
-"channels, akills and exceptions won't expire until the\n"
-"option is unset.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--noexpire."
-msgstr ""
-"Syntax: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Bekapcsolja a nem elévülést. A nem elévülő módban nickek,\n"
-"csatornák, akillek és kivételek rakhatóak nem elévülőre is\n"
-"amíg ezt az opciót nem kapcsolod ki.\n"
-"\n"
-"Ez az opció megegyezik a parancs-sorban kiadható opcióval:\n"
-"-noexpire."
-
-#, fuzzy
-msgid ""
-"Syntax: NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-" \n"
-"Changes when you will be notified about new memos:\n"
-" \n"
-" ON You will be notified of memos when you log on,\n"
-" when you unset /AWAY, and when they are sent\n"
-" to you.\n"
-" LOGON You will only be notified of memos when you log\n"
-" on or when you unset /AWAY.\n"
-" NEW You will only be notified of memos when they\n"
-" are sent to you.\n"
-" MAIL You will be notified of memos by email as well as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF You will not receive any notification of memos.\n"
-" \n"
-"ON is essentially LOGON and NEW combined."
-msgstr ""
-"Syntax: SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-"\n"
-"Itt tudod beállítani, ha értesítést szeretnél kapni\n"
-"az új üzenetekről:\n"
-"\n"
-" ON Értesítést kapsz az új üzenetről csatlakozáskor,\n"
-" amikor visszajössz /AWAY-ból, vagy ha küldenek neked.\n"
-" LOGON Értesítést kapsz az új üzenetekről csatlakozáskor\n"
-" vagy ha visszajössz /AWAY-ból.\n"
-" NEW Csak akkor kapsz értesítést, ha új üzenet érkezett.\n"
-" MAIL You will be notified of memos by email aswell as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF Nem kapsz értesítést az üzeneteidről.\n"
-"\n"
-"Az ON ekvivalens a LOGON és a NEW kombinálásával."
-
-#, fuzzy
-msgid ""
-"Syntax: READONLY {ON | OFF}\n"
-" \n"
-"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
-"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
-"suspend or forbid nicknames and channels, and manage news,\n"
-"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
-"terminated or restarted.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--readonly."
-msgstr ""
-"Syntax: SET READONLY {ON | OFF}\n"
-"\n"
-"Csak-olvasás mód aktiválása/kikapcsolása. A csak-olvasás\n"
-"mód, a normal felhasználó részére nem engedi, hogy bármit\n"
-"módosítson a szervízben, beleértve a nicknév, a\n"
-"hozzáférés listát, stb. IRCoperátorok a megfelelő flaggel\n"
-"módosítani tudja a szervíz akill listát és a droppolhat\n"
-"vagy forbidolhat nickneveket és szobákat, de ez nem fog\n"
-"kerül mentésre, amíg a csak olvasni módot kikapcsolja\n"
-"és restartolja a szervízt.\n"
-"\n"
-"Ez a parancs egyenértéku a parancs-sorban kiadott\n"
-"-readonly opcióval.\t"
-
-#, fuzzy
-msgid ""
-"Syntax: SUPERADMIN {ON | OFF}\n"
-" \n"
-"Setting this will grant you extra privileges such as the\n"
-"ability to be \"founder\" on all channel's etc...\n"
-" \n"
-"This option is not persistent, and should only be used when\n"
-"needed, and set back to OFF when no longer needed."
-msgstr ""
-"Syntax: SET SUPERADMIN {ON | OFF}\n"
-"\n"
-"Ez a beállítás extra jogokat biztosít számodra, például\n"
-"az \"összes szoba founderje\" stb...\n"
-"\n"
-"Ez az opció nem ajánlott, csak akkor használd, ha \n"
-"szükséges és kapcsold ki, ha már nem."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s that you are really the owner of this\n"
-"nick. Many commands require you to authenticate yourself\n"
-"with this command before you use them. The password\n"
-"should be the same one you sent with the REGISTER\n"
-"command."
-msgstr ""
-"Syntax: IDENTIFY [account] jelszó\n"
-"\n"
-"Tudatja a %s-vel, hogy te vagy a tulajdonosa ennek a \n"
-"nicknek. Jelszónak ugyanannak kell lennie amit a \n"
-"regisztrációnál megadtál, vagy amire módosítottad."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s to invite you or an optionally specified\n"
-"nick into the given channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
-msgstr ""
-"Syntax: INVITE #szoba\n"
-"\t\n"
-"Utasítja a %s-et, hogy hívjon meg a megadott csatornára.\n"
-"\n"
-"Alapbeállítás szerint, min. AOP vagy 5-ös access szinttel\n"
-"kell rendelkezned a csatornán, hogy használhasd."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel. If no channel is\n"
-"given, all bans affecting you in channels you have access\n"
-"in are removed.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
-msgstr ""
-"Syntax: UNBAN #szoba [nick]\n"
-"\n"
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel.\n"
-"\n"
-"Alapbeállítás szerint, min. AOP vagy 5-ös access szinttel\n"
-"kell rendelkezned, hogy használhasd.\t"
-
-#, fuzzy
-msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
-"the real server of that name from connecting. The jupe\n"
-"may be removed using a standard SQUIT. If a reason is\n"
-"given, it is placed in the server information field;\n"
-"otherwise, the server information field will contain the\n"
-"text \"Juped by <nick>\", showing the nickname of the\n"
-"person who jupitered the server."
-msgstr ""
-"Syntax: JUPE server [leirás]\n"
-"\n"
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
-"the real server of that name from connecting. The jupe\n"
-"may be removed using a standard SQUIT. If a reason is\n"
-"given, it is placed in the server information field;\n"
-"otherwise, the server information field will contain the\n"
-"text \"Juped by <nick>\", showing the nickname of the\n"
-"person who jupitered the server.\n"
-"\n"
-"Korlátozva Szervíz adminoknak."
-
-msgid "Tells you about the last time a user was seen"
-msgstr ""
-
-#, fuzzy
-msgid "Terminate Services WITHOUT saving"
-msgstr " SHUTDOWN Leállítja a szervíz programot mentéssel"
-
-#, fuzzy
-msgid "Terminate services with save"
-msgstr " SHUTDOWN Leállítja a szervíz programot mentéssel"
-
-msgid "Text"
-msgstr ""
-
-msgid ""
-"The ACCESS ADD command adds the given mask to the\n"
-"access list with the given user level; if the mask is\n"
-"already present on the list, its access level is changed to\n"
-"the level specified in the command. The level specified\n"
-"may be a numerical level or the name of a privilege (eg AUTOOP).\n"
-"When a user joins the channel the access they receive is from the\n"
-"highest level entry in the access list."
-msgstr ""
-
-msgid ""
-"The ACCESS DEL command removes the given nick from the\n"
-"access list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-"You may remove yourself from an access list, even if you\n"
-"do not have access to modify that list otherwise."
-msgstr ""
-
-msgid ""
-"The ACCESS LIST command displays the access list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" ACCESS #channel LIST 2-5,7-9\n"
-" Lists access entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The ACCESS VIEW command displays the access list similar\n"
-"to ACCESS LIST but shows the creator and last used time.\n"
-" \n"
-"The ACCESS CLEAR command clears all entries of the\n"
-"access list."
-msgstr ""
-
-msgid ""
-"The CLEAR command clears the channel access list. This requires channel "
-"founder access."
-msgstr ""
-
-#, c-format
-msgid ""
-"The CLEAR command lets you clean the database by removing all entries from "
-"the\n"
-"database that were added within time.\n"
-" \n"
-"Example:\n"
-" %s CLEAR 30m\n"
-" Will remove all entries that were added within the last 30 minutes."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The DEL command removes the given word from the\n"
-"bad words list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The LIST command displays the bad words list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" #channel LIST 2-5,7-9\n"
-" Lists bad words entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The CLEAR command clears all entries from the\n"
-"bad words list."
-msgstr ""
-"Syntax: HOP #szoba ADD nick\n"
-" HOP #szoba DEL { nick | sorszám | lista}\n"
-" HOP #szoba LIST [ maszk | lista ]\n"
-" HOP #szoba CLEAR\n"
-"\n"
-"Karbantartja az HOP (HALFOP) listát a csatornán. A HOP\n"
-"listán szereplő userek automatikusan megkapják belépéskor\n"
-"a féloperátor státuszt.\n"
-"\n"
-"HOP ADD paranccsal hozzáadhatsz egy nickenevet csatornád\n"
-"HOP listájához.\n"
-"\n"
-"HOP DEL paranccsal eltávolíthatsz egy megadott nicknevet\n"
-"a csatornád HOP listájáról. Ha sorszámokat intervallumban\n"
-"adunk meg (lásd a listázásnál),akkor a megadott bejegyzések\n"
-"kerülnek törlésre.\n"
-"\n"
-"Az HOP LIST parancs megadja az HOP listát. Ha nem vagy \n"
-"kiváncsi a teljes listára akkor a listában szereplő HOP \n"
-"sorszámát megadva is megtudhatjuk a nevét, megadhatunk \n"
-"intervallumot is.\n"
-"\n"
-"Példák:\n"
-"\n"
-"\tHOP #szoba LIST 2-5,7-9\n"
-"\tListázza az HOP-okat 2 és 5 között és\n"
-"\t7-tol 9-ig.\n"
-" \n"
-"Az HOP CLEAR parancs kiüriti a szoba HOP listáját.\n"
-"\n"
-"Az HOP ADD és HOP DEL parancsokat csak AOP / magasabb\n"
-"szinttel rendelkező userek használhatják,de az HOP CLEAR\n"
-"parancsot csak a szoba foundere adhatja ki.\n"
-"Habár, minden HOP listán szereplo user használhatja az\n"
-"HOP LIST parancsot.\n"
-"\n"
-"Ezt a parancsot letilthatod a csatornádon, és helyette \n"
-"használhatod az access lista rendszert. Nézd meg: /msg \n"
-"%s HELP ACCESS bővebb információért az access listáról,\n"
-"és írd be: /msg %s HELP SET XOP hogy megnézd, hogyan \n"
-"tudsz váltani az xOP rendszerről access lista rendszerre."
-
-msgid ""
-"The ENTRYMSG ADD command adds the given message to\n"
-"the list of messages shown to users when they join\n"
-"the channel."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG CLEAR command clears all entries from\n"
-"the list of messages shown to users when they join\n"
-"the channel, effectively disabling entry messages."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG DEL command removes the specified message from\n"
-"the list of messages shown to users when they join\n"
-"the channel. You can remove a message by specifying its number\n"
-"which you can get by listing the messages as explained below."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG LIST command displays a listing of messages\n"
-"shown to users when they join the channel."
-msgstr ""
-
-msgid "The IMMED option is not available on this network."
-msgstr "Az IMMED opció nem elérhető ezen a hálózaton."
-
-#, fuzzy, c-format
-msgid ""
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-" \n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it). Use LEVELS SET founder to make a level\n"
-"founder only.\n"
-" \n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel.\n"
-" \n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
-msgstr ""
-"Syntax:\tLEVELS #szoba SET típus [szint|FOUNDER]\n"
-"\t\tLEVELS #szoba {DIS | DISABLE} típus\n"
-"\t\tLEVELS #szoba LIST\n"
-"\t\tLEVELS #szoba RESET\n"
-"\n"
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-"\n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it).\n"
-"\n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel (see\n"
-"HELP ACCESS LEVELS).\n"
-"\n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
-
-msgid ""
-"The LIST command allows you to list existing entries on the channel access "
-"list.\n"
-"If a mask is given, the mask is wildcard matched against all existing "
-"entries on the\n"
-"access list, and only those entries are returned. If a set of flags is "
-"given, only those\n"
-"on the access list with the specified flags are returned."
-msgstr ""
-
-msgid ""
-"The MODIFY command allows you to modify the access list. If the mask is\n"
-"not already on the access list it is added, then the changes are applied.\n"
-"If the mask has no more flags, then the mask is removed from the access "
-"list.\n"
-"Additionally, you may use +* or -* to add or remove all flags, respectively. "
-"You are\n"
-"only able to modify the access list if you have the proper permission on the "
-"channel,\n"
-"and even then you can only give other people access to the equivalent of "
-"what your access is."
-msgstr ""
-
-msgid ""
-"The STATS command prints out statistics about stored nicks and memory usage."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
-"after registering if it isn't the default setting already."
-msgstr ""
-"Írd be: /msg %s SET EMAIL e-mail \n"
-"Az email címed nem lesz kiadva harmadik személynek."
-
-#, c-format
-msgid ""
-"The %s command allows users to configure logging settings\n"
-"for their channel. If no parameters are given this command\n"
-"lists the current logging methods in place for this channel.\n"
-" \n"
-"Otherwise, command must be a command name, and method\n"
-"is one of the following logging methods:\n"
-" \n"
-" MESSAGE [status], NOTICE [status], MEMO\n"
-" \n"
-"Which are used to message, notice, and memo the channel respectively.\n"
-"With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
-"to your channel. Status may be a channel status such as @ or +.\n"
-" \n"
-"To remove a logging method use the same syntax as you would to add it.\n"
-" \n"
-"Example:\n"
-" %s #anope chanserv/access MESSAGE @\n"
-" Would message any channel operators whenever someone used the\n"
-" ACCESS command on ChanServ on the channel."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The %s list for %s is full."
-msgstr "Greet message for %s unset."
-
-#, fuzzy, c-format
-msgid "The %s list has been cleared."
-msgstr "Az AKILL lista törölve."
-
-msgid "The AKILL list has been cleared."
-msgstr "Az AKILL lista törölve."
-
-#, fuzzy, c-format
-msgid "The Defcon level is now at: %d"
-msgstr "A Defcon szint most: %d"
-
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr "The E-mail address of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr "The E-mail address of %s will now be shown in %s INFO displays."
-
-msgid "The available flags are:"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The defcon system can be used to implement a pre-defined\n"
-"set of restrictions to services useful during an attempted\n"
-"attack on the network."
-msgstr ""
-"Syntax: DEFCON [1|2|3|4|5]\n"
-"A defcon rendszer képes használni előre beállított\n"
-"korlátozást a szervíz használatban egy támadás alkalmával\n"
-"a hálózaton."
-
-#, c-format
-msgid "The email address %s has reached its usage limit of %d users."
-msgstr ""
-
-#, c-format
-msgid "The email address %s has reached its usage limit of 1 user."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The entry message list for %s is full."
-msgstr "Greet message for %s unset."
-
-msgid "The following feature/function names are available:"
-msgstr ""
-
-msgid ""
-"The given mask may also be a channel, which will use the\n"
-"access list from the other channel up to the given level."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"The host %s currently has %d sessions with a limit of %d because it matches "
-"entry: %s."
-msgstr "A %s hoszt aktuálisan %d sessiont használ, a határértéke %d."
-
-#, c-format
-msgid "The last memo you sent to %s (sent on %s) has been read."
-msgstr "Az utolsó memo, amit %s részére (%s időpontban) küldtél már olvasott."
-
-#, c-format
-msgid "The last memo you sent to %s (sent on %s) has not yet been read."
-msgstr ""
-"Az utolsó memo, amit %s részére (%s időpontban) küldtél még olvasatlan."
-
-#, c-format
-msgid "The last quit message of %s will now be hidden from %s INFO displays."
-msgstr "The last quit message of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The last quit message of %s will now be shown in %s INFO displays."
-msgstr "The last quit message of %s will now be shown in %s INFO displays."
-
-#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
-msgstr ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
-msgstr ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
-
-#, fuzzy, c-format
-msgid "The limit on %s is not valid."
-msgstr "Nem változtathatod meg %s üzeneteinek számát."
-
-msgid "The mask must contain at least one non wildcard character."
-msgstr ""
-
-#, c-format
-msgid "The memo limit for %s may not be changed."
-msgstr "Nem változtathatod meg %s üzeneteinek számát."
-
-#, fuzzy, c-format
-msgid "The mode lock list of %s is full."
-msgstr "Greet message for %s unset."
-
-#, c-format
-msgid "The new display MUST be a nickname of the nickname group %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The new display is now %s."
-msgstr "A Defcon szint most: %d"
-
-#, c-format
-msgid "The nick %s is now being changed to %s."
-msgstr "A nicked %s meg lett változtatva erre: %s."
-
-msgid "The old information is the same as the new information specified."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The oper info already exists on %s."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy, c-format
-msgid "The oper info list for %s is full."
-msgstr "Greet message for %s unset."
-
-#, c-format
-msgid ""
-"The services access status of %s will now be hidden from %s INFO displays."
-msgstr ""
-"The services access status of %s will now be hidden from %s INFO displays."
-
-#, c-format
-msgid "The services access status of %s will now be shown in %s INFO displays."
-msgstr ""
-"The services access status of %s will now be shown in %s INFO displays."
-
-#, fuzzy
-msgid "The session exception list is empty."
-msgstr " EXCEPTION Módosítja a session-korlát/kivétel listát"
-
-msgid ""
-"The user with your nick has been removed. Use this command again\n"
-"to release services's hold on your nick."
-msgstr ""
-
-#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "Összesen %d üzenet van a %s csatornán."
-
-msgid ""
-"There are no bots available at this time.\n"
-"Ask a Services Operator to create one!"
-msgstr ""
-"Nem áll rendelkezésre bot.\n"
-"Kérj meg egy szervíz admint, hogy csináljon!"
-
-msgid "There are no configured servers."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "There are no forbids of type %s."
-msgstr "Összesen %d üzenet van a %s csatornán."
-
-#, fuzzy
-msgid "There are too many nicks in your group."
-msgstr " DELALL Törli a vhosztot a nickekröl a csoportban"
-
-#, fuzzy, c-format
-msgid "There currently are no logging configurations for %s."
-msgstr " RELOAD Újratölti a szervíz Konfigurációs fájlját"
-
-#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "%d üzenete van a %s szobának."
-
-#, fuzzy, c-format
-msgid ""
-"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
-msgstr "Használd a /msg %s READ %d parancsot."
-
-#, c-format
-msgid "There is no bot assigned to %s anymore."
-msgstr "Nincsen bot kijelölve %s szobában többet."
-
-msgid "There is no logon news."
-msgstr "Nincs fellépő üzenet."
-
-msgid "There is no oper news."
-msgstr "Nincs oper news."
-
-msgid "There is no random news."
-msgstr "Nincs véletlenszerű hír."
-
-#, fuzzy, c-format
-msgid "There is no such configuration block %s."
-msgstr " RELOAD Újratölti a szervíz Konfigurációs fájlját"
-
-#, fuzzy, c-format
-msgid "There is no such mode %s."
-msgstr "Nincs oper news."
-
-msgid "There's no email address set for your nick."
-msgstr "Nincs beállítva email cím a nevedhez."
-
-#, fuzzy, c-format
-msgid "This channel has been forbidden: %s"
-msgstr "Ez a szoba a %s adatbázisában regisztrált."
-
-#, fuzzy
-msgid "This channel has been suspended."
-msgstr "Ez a csatorna nem használható."
-
-#, fuzzy
-msgid "This channel is suspended."
-msgstr "Ez a csatorna nem használható."
-
-msgid "This channel may not be used."
-msgstr "Ez a csatorna nem használható."
-
-msgid ""
-"This command allows managing DNS zones used for controlling what servers "
-"users\n"
-"are directed to when connecting. Omitting all parameters prints out the "
-"status of\n"
-"the DNS zone.\n"
-" \n"
-"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to "
-"this\n"
-"zone with the ADDSERVER command.\n"
-" \n"
-"The ADDSERVER command adds a server to the given zone. When a query is done, "
-"the\n"
-"zone in question is served if it exists, else all servers in all zones are "
-"served.\n"
-"A server may be in more than one zone.\n"
-" \n"
-"The ADDIP command associates an IP with a server.\n"
-" \n"
-"The POOL and DEPOOL commands actually add and remove servers to their given "
-"zones."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command allows users to set the vhost of their\n"
-"CURRENT nick to be the vhost for all nicks in the same\n"
-"group."
-msgstr ""
-"Syntax: GROUP\n"
-"\n"
-"Ez a parancs lehetővé teszi, hogy a JELENLEGI nick\n"
-"vhostját beállítsuk a csoport minden nickjére."
-
-msgid ""
-"This command also creates a new group for your nickname,\n"
-"that will allow you to register other nicks later sharing\n"
-"the same configuration, the same set of memos and the\n"
-"same channel privileges."
-msgstr ""
-
-#, c-format
-msgid "This command is an alias to the command %s."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command is used by several commands as a way to confirm\n"
-"changes made to your account.\n"
-" \n"
-"This is most commonly used to confirm your email address once\n"
-"you register or change it.\n"
-" \n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-msgstr ""
-"Syntax: CONFIRM passcodE\n"
-"\n"
-"This is the second step of nickname registration process.\n"
-"You must perform this command in order to get your nickname\n"
-"registered with %s. The passcode (or called auth code also)\n"
-"is sent to your e-mail address in the first step of the\n"
-"registration process. For more information about the first\n"
-"stage of the registration process, type: /msg %s HELP REGISTER\n"
-"\n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-
-#, fuzzy
-msgid "This command lists information about the specified loaded module."
-msgstr ""
-"Syntax: MODINFO Fájlnév\n"
-"\n"
-"A parancs részletes információt ad a betöltött modulokról."
-
-#, fuzzy
-msgid ""
-"This command lists registered vhosts to the operator.\n"
-"If a key is specified, only entries whose nick or vhost match\n"
-"the pattern given in key are displayed e.g. Rob* for all\n"
-"entries beginning with \"Rob\"\n"
-"If a #X-Y style is used, only entries between the range of X\n"
-"and Y will be displayed, e.g. #1-3 will display the first 3\n"
-"nick/vhost entries."
-msgstr ""
-"Syntax: LIST [<kulcs>|<#X-Y>]\n"
-"\n"
-"Ez parancs listázza a regisztrált vhostokat az operátornak\n"
-"Ha egy kulcs meg van határozva, akkor csak a feltételnek\n"
-"megfelelő vhostokat adja ki melyekben vagy a nickben vagy\n"
-"a hosztban szerepel a kulcs. Pl: Rob*\n"
-"Ha az #x-y stílust használod, csak a megadott sorozatba\n"
-"tartozó X és Y közötti vhostok fognak megjelenni. Például\n"
-"az #1-3 csak az első 3 vhostot jeleníti meg.\n"
-"A lista használja NSListMax értéket, mint tág határértéket\n"
-"amikor megjeleníti a tartalmat az operátornak.\n"
-"Korlátozva Szervíz operátorokra."
-
-#, fuzzy
-msgid ""
-"This command loads the module named modname from the modules\n"
-"directory."
-msgstr ""
-"Syntax: MODLOAD Fájlnév\n"
-"\n"
-"Ez a parancs betölti azt modult, a modules könyvtárból,\n"
-"amelyiknek a fájlnevét megadtad."
-
-#, fuzzy
-msgid ""
-"This command makes your nickname join the target nickname's\n"
-"group. password is the password of the target nickname.\n"
-" \n"
-"Joining a group will allow you to share your configuration,\n"
-"memos, and channel privileges with all the nicknames in the\n"
-"group, and much more!\n"
-" \n"
-"A group exists as long as it is useful. This means that even\n"
-"if a nick of the group is dropped, you won't lose the\n"
-"shared things described above, as long as there is at\n"
-"least one nick remaining in the group.\n"
-" \n"
-"You may be able to use this command even if you have not registered\n"
-"your nick yet. If your nick is already registered, you'll\n"
-"need to identify yourself before using this command.\n"
-" \n"
-"It is recommended to use this command with a non-registered\n"
-"nick because it will be registered automatically when\n"
-"using this command. You may use it with a registered nick (to\n"
-"change your group) only if your network administrators allowed\n"
-"it.\n"
-" \n"
-"You can only be in one group at a time. Group merging is\n"
-"not possible.\n"
-" \n"
-"Note: all the nicknames of a group have the same password."
-msgstr ""
-"Syntax: GROUP célnicknév jelszó\n"
-"\n"
-"A parancs belépteti a nickneved a célnicknév csoportjába.\n"
-"A jelszó a célnicknév jelszavának kell lennie.\n"
-"\n"
-"A csoportba való belépés lehetővé teszi, hogy megoszd a\n"
-"konfigurációt, memo üzeneteket, szoba hozzáféréseket\n"
-"a nicknevekkel a csoportban, és sok más lehetőséget nyújt!\n"
-" \n"
-"A csoport addig létezik, amig használatban van.\n"
-"Ez azt jelenti, ha egy nicknevet dropolnak a csoportból,\n"
-"nem fogod elveszteni a megosztott dolgokat, egészen addig,\n"
-"amig legalább egy nick van a csoportban.\n"
-"\n"
-"Akkor is használhatod a parancsot, ha még nem regisztrált\n"
-"a nicked. Ha a nicked regisztrált, akkor előbb azonosítani\n"
-"kell a jelszavaddal, mielőtt ezt a parancsot használod.\n"
-"Írd be:/msg %s HELP IDENTIFY bővebb információért.\n"
-"\n"
-"Ajánlott, hogy inkább nem regisztrált névvel használd\n"
-"ezt a parancsot, mert ezzel automatikusan regisztrálódik.\n"
-"Ha regisztált nickről használod (hogy megváltoztasd a\n"
-"csoportod) csak akkor működik, ha a network adminok ezt\n"
-"engedélyezik.\n"
-"\n"
-"Egyszerre egy csoportban lehetsz. \n"
-"\n"
-"Megjegyzés: minden nicknévnek a csoportban ugyanaz\n"
-"\t\t a jelszava."
-
-msgid ""
-"This command manages your auto join list. When you identify\n"
-"you will automatically join the channels on your auto join list.\n"
-"Services Operators may provide a nick to modify other users'\n"
-"auto join lists."
-msgstr ""
-
-msgid ""
-"This command may not be used on this network because nickname ownership is "
-"disabled."
-msgstr ""
-
-#, fuzzy
-msgid "This command reloads the module named modname."
-msgstr ""
-"Syntax: MODLOAD Fájlnév\n"
-"\n"
-"Ez a parancs betölti azt modult, a modules könyvtárból,\n"
-"amelyiknek a fájlnevét megadtad."
-
-msgid "This command retrieves the vhost requests."
-msgstr ""
-
-msgid ""
-"This command searches the Services logfiles for messages\n"
-"that match the given pattern. The day and limit argument\n"
-"may be used to specify how many days of logs to search\n"
-"and the number of replies to limit to. By default this\n"
-"command searches one week of logs, and limits replies\n"
-"to 50.\n"
-" \n"
-"For example:\n"
-" LOGSEARCH +21d +500l Anope\n"
-" Searches the last 21 days worth of logs for messages\n"
-" containing Anope and lists the most recent 500 of them."
-msgstr ""
-
-msgid ""
-"This command tells you what a users access is on a channel\n"
-"and what access entries, if any, they match. Additionally it\n"
-"will tell you of any auto kick entries they match. Usage of\n"
-"this command is limited to users who have the ability to modify\n"
-"access entries on the channel."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, and url. Everything else\n"
-"is reset. You may not ungroup yourself if there is only one nick in\n"
-"your group."
-msgstr ""
-"Syntax: UNGROUP [nick]\n"
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, url, and icq. Everything\n"
-"else is reset. You may not ungroup yourself if there is only one\n"
-"nick in your group."
-
-#, fuzzy
-msgid "This command unloads the module named modname."
-msgstr ""
-"Syntax: MODLOAD Fájlnév\n"
-"\n"
-"Ez a parancs betölti azt modult, a modules könyvtárból,\n"
-"amelyiknek a fájlnevét megadtad."
-
-msgid "This command will resend you the registration confirmation email."
-msgstr ""
-
-#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "This nickname has been forbidden: %s"
-msgstr "This nickname is currently suspended, reason: %s"
-
-#, fuzzy, c-format
-msgid "This nickname has been recovered by %s."
-msgstr "This nickname is currently suspended, reason: %s"
-
-#, c-format
-msgid ""
-"This nickname has been recovered by %s. If you did not do\n"
-"this then %s may have your password, and you should change it."
-msgstr ""
-
-#, fuzzy
-msgid "This nickname has been registered; you may not use it."
-msgstr "Ez a szoba a %s adatbázisában regisztrált."
-
-#, fuzzy
-msgid "This nickname is suspended."
-msgstr "Ez a csatorna nem használható."
-
-#, c-format
-msgid ""
-"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
-"please choose a different nick."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr "Üzenet szám: %d; feladó.: %s (%s). Törléshez: /msg %s DEL %s %d"
-
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr "Üzenet szám: %d; feladó.: %s (%s). Törléshez: /msg %s DEL %s %d"
-
-msgid "To protect ops against bot kicks"
-msgstr ""
-
-msgid "To protect voices against bot kicks"
-msgstr ""
-
-msgid ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
-msgstr ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
-
-#, fuzzy, c-format
-msgid "Too many results for %s."
-msgstr "%s hozzáférési listája:"
-
-#, c-format
-msgid "Top %i of %s"
-msgstr ""
-
-#, fuzzy
-msgid "Topic"
-msgstr "Témaváltás lezárása"
-
-#, fuzzy
-msgid "Topic lock"
-msgstr "Témaváltás lezárása"
-
-#, fuzzy, c-format
-msgid "Topic lock option for %s is now off."
-msgstr "Topic lock option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Topic lock option for %s is now on."
-msgstr "Topic lock option for %s is now ON."
-
-#, fuzzy
-msgid "Topic retention"
-msgstr "Témamegőrzés"
-
-#, fuzzy, c-format
-msgid "Topic retention option for %s is now off."
-msgstr "Topic retention option for %s is now ON."
-
-#, fuzzy, c-format
-msgid "Topic retention option for %s is now on."
-msgstr "Topic retention option for %s is now ON."
-
-msgid "Topic set by"
-msgstr ""
-
-msgid "Turn caps lock OFF!"
-msgstr "Kapcsold ki a caps lockod!"
-
-#, fuzzy
-msgid "Turn chanstats statistics on or off"
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-#, fuzzy
-msgid "Turn nickname security on or off"
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-#, fuzzy
-msgid "Turn protection on or off"
-msgstr " KILL A kill védelem be-,kikapcsolása"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
-msgstr ""
-"Syntax: SASET nickname PRIVATE {ON | OFF}\n"
-"\n"
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's privacy option on or off for your nick.\n"
-"With PRIVATE set, your nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows your nickname can still get\n"
-"information on it using the INFO command.)"
-msgstr ""
-"Syntax: SET PRIVATE {ON | OFF}\n"
-"\n"
-"Be/kikapcsolja a %s a privát opciót a nicknevedhez.\n"
-"A PRIVATE beállítással, beállíthatod azt, hogy\n"
-"a nickneved ne szerepeljen a nicknév listában ami \n"
-"lekérhető a %s LIST paranccsal.\n"
-"(Máskülönben, bárki kaphat információt a nicknevedről\n"
-"használva az INFO parancsot.)"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Syntax: SET SECURE {ON | OFF}\n"
-"\n"
-"Be/kikapcsolja a %s a biztonsági beállításokat a nickhez.\n"
-"A SECURE beállítással, be kell írnod a jelszavadat\n"
-"mielőtt a nicknév tulajdonsaként leszel tekintve,\n"
-"kivéve, ha a hosztod szerepel az access listán.\n"
-"Habár, ha az access listán szerepel a hosztod, akkor\n"
-"nem fog automatikusan nevet váltóztatni a %s, hacsak\n"
-"nincs bekapcsolva a KILL opció."
-
-#, fuzzy
-msgid "Turns chanstats channel statistics ON or OFF for this user."
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-#, fuzzy
-msgid "Turns chanstats statistics ON or OFF."
-msgstr " SECURE A nickneved védelmének be-,kikapcsolása"
-
-#, fuzzy, c-format
-msgid ""
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-msgstr ""
-"Syntax: SASET nickname KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-"\n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-
-#, fuzzy, c-format
-msgid ""
-"Turns the automatic protection option for your nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take your nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-msgstr ""
-"Syntax: SET KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Be/kikapcsolja az automatikus kill védelmet a nickedhez.\n"
-"A kill védelem bekapcsolásakor, ha más user megpróbálja\n"
-"használni a nicked, kap egy percet mialatt meg kell\n"
-"változtatnia a nickjét, ha letelt az idő akkor a %s \n"
-"megváltóztatja a nickjét pl: Vendég-000001-re.\n"
-"\n"
-"Ha a QUICK -et választod, a user csak 20 másodpercet kap\n"
-"a nickváltásra eltérően az általános 60 másodperctől.\n"
-"Ha az IMMED-et választod akkor azonnal megváltóztatja.\n"
-"Figyelmeztetés nélkül,nem kap esélyt a nickváltásra;\n"
-"kérlek ne használd ezt az opciót csak ha nagyon indokolt.\n"
-"A network adminisztrátorok letilthatják ezt."
-
-msgid "Type"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
-msgstr ""
-"Írd be: /msg %s HELP SET opció bővebb információért az\n"
-"adott opcióról."
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option.\n"
-" \n"
-"Note: access to this command is controlled by the\n"
-"level SET."
-msgstr ""
-"Type /msg %s HELP SASET option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname. "
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname."
-msgstr ""
-"Type /msg %s HELP SASET option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname. "
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information on a\n"
-"particular option."
-msgstr ""
-"Írd be: /msg %s HELP SET opció bővebb információért az\n"
-"adott opcióról."
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
-msgstr ""
-"Írd be: /msg %s SET EMAIL e-mail \n"
-"Az email címed nem lesz kiadva harmadik személynek."
-
-#, fuzzy
-msgid "Un-Load a module"
-msgstr " MODUNLOAD Kitölti a modult"
-
-#, fuzzy, c-format
-msgid "Unable to find regex engine %s."
-msgstr "Nem sikerült eltávolítani a %s modult"
-
-#, fuzzy, c-format
-msgid "Unable to load module %s."
-msgstr "Nem sikerült a betölteni a %s modult"
-
-#, fuzzy, c-format
-msgid "Unable to remove module %s."
-msgstr "Nem sikerült eltávolítani a %s modult"
-
-#, fuzzy
-msgid "Unassigns a bot from a channel"
-msgstr "UNASSIGN Unassigns a bot from a channel"
-
-#, fuzzy
-msgid ""
-"Unassigns a bot from a channel. When you use this command,\n"
-"the bot won't join the channel anymore. However, bot\n"
-"configuration for the channel is kept, so you will always\n"
-"be able to reassign a bot later without having to reconfigure\n"
-"it entirely."
-msgstr ""
-"Syntax: UNASSIGN #szoba\n"
-"\n"
-"Eltávolítja a botot a csatornáról. Ha használod ezt a\n"
-"parancsot, akkor a botod nem fog többet belépni a\n"
-"szobába. A bot konfigurációi megmaradnak.\n"
-"Azaz nem kell újra bekonfigurálnod, ha később vissza\n"
-"akarod hozni a szobádba."
-
-#, fuzzy
-msgid "Underlines kicker"
-msgstr "\tAláhúzásért kirúgás: %s"
-
-#, fuzzy
-msgid "Unknown SET option."
-msgstr "Unknown SASET option %s."
-
-#, fuzzy, c-format
-msgid "Unknown STATS option: %s"
-msgstr "Ismeretlen STATS opció: %s."
-
-#, fuzzy, c-format
-msgid "Unknown command %s."
-msgstr "Ismeretlen beállítás %s."
-
-#, fuzzy, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Ismeretlen parancs %s. Írd be: \"%s%s HELP\"."
-
-#, fuzzy, c-format
-msgid "Unknown mode character %c ignored."
-msgstr "Ismeretlen mód karakter: %c figyelmen kívül hagyva."
-
-#, fuzzy, c-format
-msgid "Unknown parameter: %s"
-msgstr "SET opció beállítás"
-
-msgid "Unpooled"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Unregisters the named channel. Can only be used by\n"
-"the channel founder."
-msgstr ""
-"Syntax: DROP #szoba\n"
-"\n"
-"Törli a megnevezett szoba regisztrációját.\n"
-"Csak a szoba founder használhatja."
-
-#, fuzzy
-msgid ""
-"Unregisters the specified channel. Only Services Operators\n"
-"can drop a channel of which they are not the founder of."
-msgstr ""
-"Syntax: DROP #szoba\n"
-"\n"
-"Törli a regisztrációt a csatornáról.Csak Services Operators\n"
-"droppolhat csatornát,úgy hogy nem használja a szoba\n"
-"jelszavát."
-
-#, fuzzy
-msgid "Unsuspend a given nick"
-msgstr " UNSUSPEND Unsuspend a given nick"
-
-msgid "Unsuspends a nickname which allows it to be used again."
-msgstr ""
-
-msgid ""
-"Updates a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is updated. If channel is omitted then\n"
-"your channel status is updated on every channel you are in."
-msgstr ""
-
-#, fuzzy
-msgid "Updates a selected nicks status on a channel"
-msgstr " BAN Bans a selected nick on a channel"
-
-#, fuzzy
-msgid "Updates your current status, i.e. it checks for new memos"
-msgstr ""
-" UPDATE Updates your current status, i.e. it checks for new memos"
-
-#, fuzzy
-msgid ""
-"Updates your current status, i.e. it checks for new memos,\n"
-"sets needed channel modes and updates your vhost and\n"
-"your userflags (lastseentime, etc)."
-msgstr ""
-"Syntax: UPDATE\n"
-"Frissíti a jelenlegi státuszod, vagyis ellenőrzi, hogy \n"
-"jött-e új memo üzenet, beállítja a szükséges szoba \n"
-"módokat, (ModeonID)és frissíti a vhostod, az userflagjeid\n"
-"(utolsó fellépés, stb.)"
-
-msgid "Updating databases."
-msgstr "Adatbázis mentve."
-
-#, c-format
-msgid "Uplink capab: %s"
-msgstr "Uplink capab: %s"
-
-#, c-format
-msgid "Uplink server: %s"
-msgstr "Uplink server: %s"
-
-#, c-format
-msgid "Use the %s ALL command to list all commands and their descriptions."
-msgstr ""
-
-msgid "Used on"
-msgstr ""
-
-#, fuzzy
-msgid "Used to manage channels"
-msgstr "%s váltóztatott a módodon."
-
-#, fuzzy
-msgid "Used to manage the list of privileged users"
-msgstr " ACCESS A szoba hozzáférési listájának beállítása"
-
-msgid "Used to modify the channel status of you or other users"
-msgstr ""
-
-#, fuzzy
-msgid "User has been banned from the channel"
-msgstr "%s csatornán a tiltást levetetted magadról."
-
-#, fuzzy, c-format
-msgid "User limit for %s removed."
-msgstr "%s vhosztja törölve lett."
-
-#, fuzzy, c-format
-msgid "User limit for %s set to %d."
-msgstr "%s maximálisan fogadható üzeneteinek száma: %d."
-
-#, fuzzy
-msgid "Users"
-msgstr "Botok listája:"
-
-#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, fuzzy
-msgid "Users list:"
-msgstr "Botok listája:"
-
-msgid "VHost"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "VHost for %s set to %s."
-msgstr "%s vhostja erre változott: %s."
-
-#, fuzzy, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "%s vhostja erre változott: %s@%s."
-
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s."
-msgstr "A %s csoport vhostja %s lett."
-
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "A %s csoport vhostja erre változott: %s@%s."
-
-msgid "VIEW host"
-msgstr ""
-
-#, fuzzy
-msgid "VIEW [mask | list | id]"
-msgstr "LIST [#szoba] [list | NEW ]"
-
-msgid "VIEW [mask | list]"
-msgstr ""
-
-msgid "Value"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Value of %s:%s changed to %s"
-msgstr "A megadott csatorna (%s) új foundere: %s."
-
-msgid "Vhost"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Vhost for %s removed."
-msgstr "%s vhosztja törölve lett."
-
-#, fuzzy
-msgid "View and change Services Operators"
-msgstr "%s is a services operator of type %s."
-
-msgid "View and change configuration file settings"
-msgstr ""
-
-#, fuzzy
-msgid "View the list of host sessions"
-msgstr " SESSION Olvassa a sessionok hoszt listáját"
-
-msgid "Voices protection"
-msgstr "Voices védelme"
-
-msgid "Watch your language!"
-msgstr "Figyelj a stílusra kiskomám!"
-
-#, c-format
-msgid ""
-"When private is set, the channel will not appear in\n"
-"%s's %s command."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Without a parameter, displays information on the number of\n"
-"memos you have, how many of them are unread, and how many\n"
-"total memos you can receive.\n"
-" \n"
-"With a channel parameter, displays the same information for\n"
-"the given channel.\n"
-" \n"
-"With a nickname parameter, displays the same information\n"
-"for the given nickname. This is limited to Services\n"
-"Operators."
-msgstr ""
-"Syntax: INFO [nick| #szoba]\n"
-"\n"
-"Paraméter nélkül kiirja az információt, hogy hány\n"
-"üzeneted van, ebböl hány olvasatlan, és összesen\n"
-"hány üzenetet fogadhatsz.\n"
-"\n"
-"A szoba paraméterrel, a csatornáról kapod meg \n"
-"ezeket az információkat\t\n"
-"A nicknév paraméterrel a megadott nicknévröl jeléeníti\n"
-"meg ezeket az információkat.Enek használat korlátozva \n"
-"Szervíz adminra."
-
-#, fuzzy
-msgid ""
-"Without a parameter, reverses the effect of the IDENTIFY\n"
-"command, i.e. make you not recognized as the real owner of the nick\n"
-"anymore. Note, however, that you won't be asked to reidentify\n"
-"yourself.\n"
-" \n"
-"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
-"to re-identify. This is limited to Services Operators."
-msgstr ""
-"Syntax: LOGOUT [nicknév [REVALIDATE]]\n"
-"\n"
-"Kilépési paraméter, megfordítja az IDENTIFY parancs\n"
-"hatását, azaz nem leszel beazonosítva a nickedre, mint a \n"
-"valódi tulajdonosa a nickednek.\n"
-"\n"
-"A paraméter ugyanezt teszi a megadott nickkel.\n"
-"Ha megadod a REVALIDATE opciót, akkor a nicktől\n"
-"a szerviz újraazonosítást fog kérni. \n"
-"\n"
-"Használat korlátozva Szervíz adminoknak."
-
-#, fuzzy
-msgid ""
-"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
-" \n"
-"With the AKILL option, displays the current size of the\n"
-"AKILL list and the current default expiry time.\n"
-" \n"
-"The RESET option currently resets the maximum user count\n"
-"to the number of users currently present on the network.\n"
-" \n"
-"The UPLINK option displays information about the current\n"
-"server Anope uses as an uplink to the network.\n"
-" \n"
-"The HASH option displays information about the hash maps.\n"
-" \n"
-"The ALL option displays all of the above statistics."
-msgstr ""
-"Syntax: STATS [AKILL | ALL | RESET]\n"
-"\n"
-"Ha választasz valamit, megmutatja az aktuális\n"
-"felhasználók számát, a bejelentkezett IRCopokat (szervizek\n"
-"nélkül), legmagasabb felhasználószámot a szervíz indulása\n"
-"óta, és az időt amióta fut a szerver.\t\n"
-"Az AKILL beállítással, kijelzi az aktuális maxot az\n"
-"AKILL listán és az aktuális lejárati időt.\n"
-"\n"
-"Az ALL beállítást csak szervíz adminok használhatják és\n"
-"kiírja a szervíz memória használatának információját. Ez a\n"
-"beállítás lefagyaszthatja a szervízt egy rövid időre nagy\n"
-"hálózat esetén, így nem lehet használni azt.\t\n"
-"\n"
-"A RESET beállítás nullázza az aktuális felhasználók max.\n"
-"számát átírja a jelenlegi felhasználó számra\t"
-
-msgid "Word"
-msgstr ""
-
-#, c-format
-msgid "You are already a member of the group of %s."
-msgstr "Már tagja vagy ennek a csoportnak: %s."
-
-msgid "You are already identified."
-msgstr "Már be vagy azonosítva. :-)"
-
-#, fuzzy, c-format
-msgid "You are already in %s!"
-msgstr "You are already in %s! "
-
-#, fuzzy
-msgid "You are no longer a super admin."
-msgstr "Te nem vagy már Szuper-Admin"
-
-#, fuzzy
-msgid "You are not identified."
-msgstr "Már be vagy azonosítva. :-)"
-
-#, fuzzy
-msgid "You are not permitted to be on this channel."
-msgstr "Nem változtathatod meg a max. fogadható üzenetek számát."
-
-msgid "You are not permitted to change your memo limit."
-msgstr "Nem változtathatod meg a max. fogadható üzenetek számát."
-
-#, fuzzy
-msgid "You are not using a client certificate."
-msgstr "Már be vagy azonosítva. :-)"
-
-#, fuzzy
-msgid "You are now a super admin."
-msgstr "Most már Szuper-Admin vagy"
-
-msgid "You are now an IRC Operator."
-msgstr "Most már IRC Operátor vagy!"
-
-#, fuzzy
-msgid "You are now identified for your nick. Change your password now."
-msgstr "You are now identified for your nick. Change your password now."
-
-#, c-format
-msgid "You are now in the group of %s."
-msgstr "Mostantól tagja vagy a %scsoportnak."
-
-#, fuzzy, c-format
-msgid ""
-"You are over your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
-msgstr ""
-"Figyelem: Fogadható üzenetek maximális számát (%d).\n"
-"Nem fogadhatsz több üzenetet, amíg törölsz néhányat."
-
-msgid "You can not NOOP Services."
-msgstr ""
-
-msgid ""
-"You can not disable the founder privilege because it would be impossible to "
-"reenable it at a later time."
-msgstr ""
-
-#, fuzzy
-msgid "You can not jupe an already juped server."
-msgstr "You can not jupe your services server or your uplink server."
-
-#, fuzzy
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "You can not jupe your services server or your uplink server."
-
-#, c-format
-msgid "You can not reload this module directly, instead reload %s."
-msgstr ""
-
-msgid "You can not request a receipt when sending a memo to yourself."
-msgstr "You can not request a receipt when sending a memo to yourself."
-
-#, fuzzy, c-format
-msgid "You can't %s yourself!"
-msgstr "Nem ghostolhatod ki magad!"
-
-#, fuzzy
-msgid "You can't add a channel to its own access list."
-msgstr "Nincs ilyen bejegyzés a (%s) csatorna hozzáférési listáján."
-
-#, fuzzy, c-format
-msgid "You can't logout %s, they are a Services Operator."
-msgstr "%s nem tud kijelentkezni, mert ő egy Services Operator."
-
-#, fuzzy, c-format
-msgid "You cannot %s on this network."
-msgstr "Nem törölheted ezen a hálózaton az e-mail címed."
-
-#, fuzzy, c-format
-msgid "You cannot set the %c flag."
-msgstr "You cannot use this command."
-
-#, c-format
-msgid "You cannot set the memo limit for %s higher than %d."
-msgstr "%s max. bejövő üzenetek száma nem lehet több, mint %d."
-
-#, c-format
-msgid "You cannot set your memo limit higher than %d."
-msgstr "A max. bejövő üzenetek száma nem lehet több, mint %d."
-
-#, fuzzy
-msgid "You cannot unassign bots while persist is set on the channel."
-msgstr "You can not unassign bots while persist is set on the channel."
-
-msgid "You cannot unset the e-mail on this network."
-msgstr "Nem törölheted ezen a hálózaton az e-mail címed."
-
-msgid "You cannot use this command."
-msgstr "You cannot use this command."
-
-#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Van %d üzeneted, ebből %d olvasatlan."
-
-#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Van %d üzeneted, ebből 1 olvasatlan."
-
-#, c-format
-msgid "You currently have %d memos."
-msgstr "Van %d üzeneted."
-
-#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Van %d üzeneted; és mind olvasatlan."
-
-msgid "You currently have 1 memo, and it has not yet been read."
-msgstr "Van 1 olvasatlan üzeneted."
-
-msgid "You currently have 1 memo."
-msgstr "Van 1 üzeneted."
-
-msgid "You currently have no memos."
-msgstr "Jelenleg nincs üzeneted."
-
-#, c-format
-msgid "You do not have access to set mode %c."
-msgstr ""
-
-#, c-format
-msgid "You do not have the access to change %s's modes."
-msgstr ""
-
-#, c-format
-msgid "You found me, %s!"
-msgstr ""
-
-#, c-format
-msgid "You have %d new memos."
-msgstr "%d darab új üzeneted van."
-
-msgid "You have 1 new memo."
-msgstr "Van egy új üzeneted."
-
-#, fuzzy, c-format
-msgid ""
-"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
-msgstr "Használd a /msg %s READ %d parancsot."
-
-#, fuzzy, c-format
-msgid "You have been invited to %s by %s."
-msgstr "You have been invited to %s."
-
-#, c-format
-msgid "You have been invited to %s."
-msgstr "You have been invited to %s."
-
-#, fuzzy, c-format
-msgid "You have been logged in as %s."
-msgstr "A nicked sikeresen kijelentkezett."
-
-#, fuzzy
-msgid "You have been logged out."
-msgstr "A nicked sikeresen kijelentkezett."
-
-#, c-format
-msgid "You have been unbanned from %s."
-msgstr "%s csatornán a tiltást levetetted magadról."
-
-#, fuzzy, c-format
-msgid "You have been unbanned from %d channels."
-msgstr "%s csatornán a tiltást levetetted magadról."
-
-msgid "You have no limit on the number of memos you may keep."
-msgstr "Korlátlan számú üzenetet fogadhatsz."
-
-#, fuzzy
-msgid "You have no memos."
-msgstr "%d darab új üzeneted van."
-
-#, fuzzy
-msgid "You have no new memos."
-msgstr "%d darab új üzeneted van."
-
-#, fuzzy, c-format
-msgid ""
-"You have reached your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
-msgstr ""
-"Figyelem: Fogadható üzenetek maximális száma (%d).\n"
-"Nem fogadhatsz több üzenetet, amíg nem törölsz néhányat."
-
-#, fuzzy, c-format
-msgid "You have regained control of %s."
-msgstr "You have been invited to %s."
-
-#, fuzzy
-msgid "You may drop any nick within your group."
-msgstr " DELALL Törli a vhosztot a nickekröl a csoportban"
-
-#, c-format
-msgid "You may not (un)lock mode %c."
-msgstr ""
-
-#, fuzzy
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "Nem törölheted ezen a hálózaton az e-mail címed."
-
-#, fuzzy
-msgid "You may not change the email of an unconfirmed account."
-msgstr "Nem törölheted ezen a hálózaton az e-mail címed."
-
-#, fuzzy
-msgid "You may not change the password of other Services Operators."
-msgstr "%s nem tud kijelentkezni, mert ő egy Services Operator."
-
-#, fuzzy
-msgid "You may not drop other Services Operators' nicknames."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "You may not get the password of other Services Operators."
-msgstr "%s nem tud kijelentkezni, mert ő egy Services Operator."
-
-#, fuzzy
-msgid "You may not suspend other Services Operators' nicknames."
-msgstr "%s nem tud kijelentkezni, mert ő egy Services Operator."
-
-#, fuzzy
-msgid ""
-"You may view but not modify the access list of other Services Operators."
-msgstr "%s nem tud kijelentkezni, mert ő egy Services Operator."
-
-#, fuzzy
-msgid ""
-"You may view but not modify the certificate list of other Services Operators."
-msgstr "%s nem tud kijelentkezni, mert ő egy Services Operator."
-
-#, c-format
-msgid "You might see yourself in the mirror, %s."
-msgstr ""
-
-msgid "You must assign a bot to the channel before using this command."
-msgstr ""
-
-msgid "You must be a channel operator to register the channel."
-msgstr "A csatornán operátornak kell lenned, hogy regisztrálhasd."
-
-#, fuzzy, c-format
-msgid "You must be in %s to use this command."
-msgstr "You need to be identified to use this command."
-
-#, fuzzy
-msgid "You must confirm your account before you can register a channel."
-msgstr "A csatornán operátornak kell lenned, hogy regisztrálhasd."
-
-#, fuzzy
-msgid "You must confirm your account before you may request a vhost."
-msgstr "A csatornán operátornak kell lenned, hogy regisztrálhasd."
-
-#, fuzzy
-msgid "You must confirm your account before you may send a memo."
-msgstr "A csatornán operátornak kell lenned, hogy regisztrálhasd."
-
-#, c-format
-msgid ""
-"You must enter the channel name twice as a confirmation that you wish to drop"
-" %s."
-msgstr ""
-
-#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr ""
-"A nicked regisztrálásához %d másodpercnél régebben kell csatlakozva lenned."
-
-#, fuzzy, c-format
-msgid "You must have the %s(ME) privilege on the channel to use this command."
-msgstr "You need to be identified to use this command."
-
-msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
-"case you forget it."
-msgstr "Be kell állítanod egy E-mail címet a nicknevedhez."
-
-msgid "You need to be identified to use this command."
-msgstr "You need to be identified to use this command."
-
-#, fuzzy
-msgid "You will be notified by message and by mail when new memos arrive."
-msgstr "Értesítést kapsz új üzenetek érkezésekor."
-
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon and when they arrive, and by mail "
-"when they arrive."
-msgstr "Értesítést kapsz új üzenetek érkezéséről csatlakozáskor."
-
-msgid "You will be notified of new memos at logon and when they arrive."
-msgstr "Értesítést kapsz új üzenetek érkezéséről csatlakozáskor."
-
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon, and by mail when they arrive."
-msgstr "Értesítést kapsz új üzenetek érkezéséről csatlakozáskor."
-
-msgid "You will be notified of new memos at logon."
-msgstr "Értesítést kapsz az új üzeneteidről,ha fellépsz az IRC-re."
-
-msgid "You will be notified when new memos arrive."
-msgstr "Értesítést kapsz új üzenetek érkezésekor."
-
-msgid "You will no longer be able to receive memos."
-msgstr "Ezentúl nem tudsz üzeneteket fogadni."
-
-msgid "You will no longer be informed via email."
-msgstr "Már nem kapsz értesítést emailben."
-
-msgid "You will not be notified of new memos."
-msgstr "Nem kapsz értesítést az új üzeneteidről."
-
-msgid "You will now be informed about new memos via email."
-msgstr "Az új memo üzeneteidről emailben kapsz értesítést."
-
-msgid "Your IRCd does not support SVSJOIN."
-msgstr ""
-
-msgid "Your IRCd does not support SVSNICK."
-msgstr ""
-
-msgid "Your IRCd does not support SVSPART."
-msgstr ""
-
-msgid ""
-"Your IRCd does not support vIdent's, if this is incorrect, please report "
-"this as a possible bug"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Your account %s has been successfully created."
-msgstr "A %s nevű bot törölve."
-
-#, fuzzy
-msgid "Your account is already confirmed."
-msgstr "Már be vagy azonosítva. :-)"
-
-#, fuzzy, c-format
-msgid "Your account will expire, if not confirmed, in %s."
-msgstr "Már be vagy azonosítva. :-)"
-
-#, fuzzy, c-format
-msgid "Your email address has been changed to %s."
-msgstr "E-mail address for %s changed to %s."
-
-#, fuzzy
-msgid "Your email address is not allowed, choose a different one."
-msgstr "Összes O:lines %s módosítva."
-
-msgid ""
-"Your email address is not confirmed. To confirm it, follow the instructions "
-"that were emailed to you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Your email address of %s has been confirmed."
-msgstr "Összes O:lines %s módosítva."
-
-#, fuzzy, c-format
-msgid "Your email has been updated to %s"
-msgstr "E-mail address for %s changed to %s."
-
-#, fuzzy, c-format
-msgid "Your email has been updated to %s."
-msgstr "E-mail address for %s changed to %s."
-
-msgid "Your memo limit has been disabled."
-msgstr "Ezentúl korlátlan számú üzenetet fogadhatsz."
-
-#, c-format
-msgid "Your memo limit has been set to %d."
-msgstr "A max. bejövő üzenetek számanak új értéke: %d."
-
-#, c-format
-msgid "Your memo limit is %d, and may not be changed."
-msgstr "A max. bejövő üzentek száma: %d,ez fix érték."
-
-#, c-format
-msgid "Your memo limit is %d."
-msgstr "A maximálisan fogadható üzentek száma: %d."
-
-msgid "Your memo limit is 0; you will not receive any new memos."
-msgstr "A max. bejövő üzentek száma: 0; és több nem jöhet."
-
-#, fuzzy
-msgid ""
-"Your memo limit is 0; you will not receive any new memos. You cannot change "
-"this limit."
-msgstr ""
-"A max. bejövő üzentek száma: 0; és nem köhet több. \n"
-"Ez nem változtatható meg."
-
-msgid "Your nick has been logged out."
-msgstr "A nicked sikeresen kijelentkezett."
-
-#, fuzzy
-msgid "Your nick is already registered."
-msgstr "A nicked már regisztrált; írd be /msg %s DROP először."
-
-msgid "Your nick is not grouped to anything, you can't ungroup it."
-msgstr "Your nick is not grouped to anything, you can't ungroup it."
-
-#, fuzzy
-msgid "Your nick isn't registered."
-msgstr "Nickname %s registered."
-
-#, c-format
-msgid "Your nickname is now being changed to %s"
-msgstr "A nickneved most meg lesz változtatva: %s."
-
-msgid "Your oper block doesn't require logging in."
-msgstr ""
-
-#, c-format
-msgid "Your passcode has been re-sent to %s."
-msgstr "A kód újra el lett küldve erre a címre: %s."
-
-#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Jelszavad: %s - jegyezd meg a későbbi használathoz!"
-
-#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr ""
-
-msgid "Your password reset request has expired."
-msgstr "Your password request has expired."
-
-#, fuzzy
-msgid "Your vHost has been requested."
-msgstr "A %s nevű bot törölve."
-
-#, c-format
-msgid "Your vhost of %s is now activated."
-msgstr "A %s virtuális hosztod aktiválva."
-
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "A %s@%s virtuális hosztod aktiválva."
-
-msgid "Your vhost was removed and the normal cloaking restored."
-msgstr "Your vhost was removed and the normal cloaking restored."
-
-#, fuzzy
-msgid "Zone"
-msgstr "Nincs"
-
-#, fuzzy, c-format
-msgid "Zone %s already exists."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy, c-format
-msgid "Zone %s does not exist."
-msgstr "%s nevű bot már létezik."
-
-#, fuzzy, c-format
-msgid "Zone %s removed."
-msgstr "%s vhosztja törölve lett."
-
-#, fuzzy
-msgid "[1|2|3|4|5]"
-msgstr "DEFCON [1|2|3|4|5]"
-
-#, c-format
-msgid "[Logon News - %s] %s"
-msgstr "[Fellépési Hír] - %s %s"
-
-#, c-format
-msgid "[Oper News - %s] %s"
-msgstr "[Oper Hír] - %s %s"
-
-#, c-format
-msgid "[Random News - %s] %s"
-msgstr "[Véletlenszerű Hír] - %s %s"
-
-#, fuzzy
-msgid "[account] password"
-msgstr "IDENTIFY jelszó"
-
-#, fuzzy
-msgid "[channel [nick]]"
-msgstr "OP #channel [nick]"
-
-#, fuzzy
-msgid "[channel] ADD entry"
-msgstr "AOP #szoba { ADD | DEL | LIST | CLEAR } [ nick | sorszám ]"
-
-#, fuzzy
-msgid "[channel] DEL entry"
-msgstr "MODE szoba mód"
-
-#, fuzzy
-msgid "[channel] LIST"
-msgstr "DROP #szoba"
-
-#, fuzzy
-msgid "[channel] [list | NEW]"
-msgstr "LIST [#szoba] [list | NEW ]"
-
-#, fuzzy
-msgid "[channel] [nick]"
-msgstr "OP #channel [nick]"
-
-#, fuzzy
-msgid "[channel] {num | list | LAST | ALL}"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-#, fuzzy
-msgid "[channel] {num | list | LAST | NEW | ALL}"
-msgstr "DEL [#szoba] { szám | list | ALL}"
-
-msgid "[key|#X-Y]"
-msgstr ""
-
-#, fuzzy
-msgid "[nick | channel]"
-msgstr "CANCEL {nick | #szoba}"
-
-#, fuzzy
-msgid "[nick]"
-msgstr "INFO nick"
-
-msgid "[nickname [REVALIDATE]]"
-msgstr ""
-
-#, fuzzy
-msgid "[nickname]"
-msgstr "CHECK nicknév "
-
-msgid "[parameter]"
-msgstr ""
-
-msgid "[+daysd] [+limitl] pattern"
-msgstr ""
-
-#, fuzzy
-msgid "[+expiry] channel reason"
-msgstr "CHANKILL [+lejárat] {#szoba} [indok]"
-
-msgid "[Hostname hidden]"
-msgstr ""
-
-msgid "[Suspended]"
-msgstr ""
-
-msgid "[Unconfirmed]"
-msgstr ""
-
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been approved."
-msgstr "[auto-memo] A memo, amit %s számára küldtél meg lett tekintve."
-
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been rejected."
-msgstr "[auto-memo] A memo, amit %s számára küldtél meg lett tekintve."
-
-#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "%s részére küldött utolsó memo üzenet visszavonva."
-
-msgid "[{pattern | channel} [INVISIBLE]]"
-msgstr ""
-
-msgid "[{pattern | nick} [SECRET]]"
-msgstr ""
-
-msgid "day"
-msgstr ""
-
-msgid "days"
-msgstr ""
-
-#, fuzzy
-msgid "does not expire"
-msgstr " %s (does not expire)"
-
-#, c-format
-msgid "expires in %d day"
-msgstr "elévül %d nap múlva"
-
-#, c-format
-msgid "expires in %d days"
-msgstr "elévül %d nap múlva"
-
-#, c-format
-msgid "expires in %d hour, %d minute"
-msgstr "elévül %d óra, %d perc múlva"
-
-#, c-format
-msgid "expires in %d hour, %d minutes"
-msgstr "elévül %d óra, %d perc múlva"
-
-#, c-format
-msgid "expires in %d hours, %d minute"
-msgstr "elévül %d óra, %d perc múlva"
-
-#, c-format
-msgid "expires in %d hours, %d minutes"
-msgstr "elévül %d óra, %d perc múlva"
-
-#, c-format
-msgid "expires in %d minute"
-msgstr "elévül %d perc múlva"
-
-#, c-format
-msgid "expires in %d minutes"
-msgstr "elévül %d perc múlva"
-
-#, fuzzy
-msgid "expires momentarily"
-msgstr "elévül %d nap múlva"
-
-msgid "hour"
-msgstr ""
-
-msgid "hours"
-msgstr ""
-
-#, c-format
-msgid "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
-
-msgid "minute"
-msgstr ""
-
-msgid "minutes"
-msgstr ""
-
-msgid "not assigned yet"
-msgstr ""
-
-msgid "second"
-msgstr ""
-
-#, fuzzy
-msgid "seconds"
-msgstr "%s parancsok:"
-
-#, fuzzy, c-format
-msgid "vHost for %s has been activated."
-msgstr "A %s virtuális hosztod aktiválva."
-
-#, fuzzy, c-format
-msgid "vHost for %s has been rejected."
-msgstr "A %s nevű bot törölve."
-
-msgid "vhost"
-msgstr ""
-
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "A %s csoport vhostja törölve."
-
-msgid "year"
-msgstr ""
-
-msgid "years"
-msgstr ""
-
-msgid "{MODIFY|VIEW} [block name item name item value]"
-msgstr ""
-
-#, fuzzy
-msgid "{channel | nickname}"
-msgstr "UNBAN #szoba [nick]"
-
-#, fuzzy
-msgid "{nick | channel}"
-msgstr "CANCEL {nick | #szoba}"
-
-#, fuzzy
-msgid "{nick | channel} memo-text"
-msgstr "SEND {nick | #szoba} memo-szöveg"
diff --git a/language/anope.it_IT.po b/language/anope.it_IT.po
index 8ddadbeb1..d36979342 100644
--- a/language/anope.it_IT.po
+++ b/language/anope.it_IT.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-10-04 13:57+0200\n"
-"PO-Revision-Date: 2023-10-04 14:01+0200\n"
+"POT-Creation-Date: 2024-02-22 16:34+0000\n"
+"PO-Revision-Date: 2024-02-22 16:38+0000\n"
"Last-Translator: Dragone2 <dragone2@risposteinformatiche.it>\n"
"Language-Team: Italian\n"
"Language: it_IT\n"
@@ -16,7 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 3.0.1\n"
+"X-Generator: Poedit 3.4\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
@@ -210,6 +210,10 @@ msgid "%s disabled on channel %s."
msgstr "%s disabilitato sul canale %s."
#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr "%s non desidera essere aggiunto agli elenchi di accesso ai canali."
+
+#, c-format
msgid "%s has been invited to %s."
msgstr "%s è stato invitato in %s."
@@ -521,7 +525,7 @@ msgid "channel text"
msgstr "canale testo"
msgid "channel time"
-msgstr "canale tempo"
+msgstr "canale durata"
msgid "channel user reason"
msgstr "canale utente motivo"
@@ -529,11 +533,11 @@ msgstr "canale utente motivo"
msgid "channel what"
msgstr "canale cosa"
-msgid "channel ADD mask"
-msgstr "canale ADD mashera"
+msgid "channel ADD mask level [description]"
+msgstr "canale ADD maschera livello [descrizione]"
-msgid "channel ADD mask level"
-msgstr "canale ADD maschera livello"
+msgid "channel ADD mask [description]"
+msgstr "canale ADD maschera [descrizione]"
msgid "channel ADD message"
msgstr "canale ADD messaggio"
@@ -560,13 +564,13 @@ msgid "channel DEL num"
msgstr "canale DEL num"
msgid "channel DEL {mask | entry-num | list}"
-msgstr "canale DEL {maschera | num-voce | list}"
+msgstr "canale DEL {maschera | num-voce | lista}"
msgid "channel DEL {nick | mask | entry-num | list}"
-msgstr "canale DEL {nick | maschera | num-voce | list}"
+msgstr "canale DEL {nick | maschera | num-voce | lista}"
msgid "channel DEL {word | entry-num | list}"
-msgstr "canale DEL {parola | num-voce | list}"
+msgstr "canale DEL {parola | num-voce | lista}"
msgid "channel ENFORCE"
msgstr "canale ENFORCE"
@@ -575,10 +579,10 @@ msgid "channel LIST"
msgstr "canale LIST"
msgid "channel LIST [mask | entry-num | list]"
-msgstr "canale LIST [maschera | num-voce | list]"
+msgstr "canale LIST [maschera | num-voce | lista]"
msgid "channel LIST [mask | list]"
-msgstr "canale LIST [maschera | list]"
+msgstr "canale LIST [maschera | lista]"
msgid "channel LIST [mask | +flags]"
msgstr "canale LIST [maschera | +flag]"
@@ -596,10 +600,10 @@ msgid "channel SET type level"
msgstr "canale SET tipo livello"
msgid "channel VIEW [mask | entry-num | list]"
-msgstr "canale VIEW [maschera | num-voce | list]"
+msgstr "canale VIEW [maschera | num-voce | lista]"
msgid "channel VIEW [mask | list]"
-msgstr "canale VIEW [maschera | list]"
+msgstr "canale VIEW [maschera | lista]"
msgid "channel [description]"
msgstr "canale [descrizione]"
@@ -619,8 +623,8 @@ msgstr "canale [+scadenza] [motivo]"
msgid "channel [+expiry] {nick | mask} [reason]"
msgstr "canale [+scadenza] {nick | maschera} [motivo]"
-msgid "channel [MODIFY] mask changes"
-msgstr "canale MODIFY maschera modifiche"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr "canale [MODIFY] maschera modifiche [descrizione]"
msgid "channel [SET] [topic]"
msgstr "canale SET [topic]"
@@ -682,9 +686,6 @@ msgstr "nick canale"
msgid "nick channel [reason]"
msgstr "nick canale [motivo]"
-msgid "nick flags"
-msgstr "nick flag"
-
msgid "nick hostmask"
msgstr "nick maschera-host"
@@ -843,12 +844,12 @@ msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
" \n"
"Gli account che non sono più usati sono soggetti a\n"
"cancellazione automatica, saranno quindi eliminati\n"
-"dopo %d giorni di inutilizzo."
+"dopo %lu giorni di inutilizzo."
msgid ""
" \n"
@@ -945,12 +946,12 @@ msgstr ""
#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
" \n"
-"Tieni presente che i canali che non vengono utilizzati per %d\n"
+"Tieni presente che i canali che non vengono utilizzati per %lu\n"
"giorni (cioè in quei canali in cui non entra nessun utente\n"
"che si trova nella relativa lista di accesso) saranno\n"
"automaticamente de-registrati."
@@ -1272,11 +1273,11 @@ msgid "%-8s %s"
msgstr "%-8s %s"
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "%2lu %-16s lettere: %s, parole: %s, linee: %s, faccine: %s, azioni: %s"
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr "%2d %-16s lettere: %s, parole: %s, linee: %s, faccine: %s, azioni: %s"
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr "%b %d %H:%M:%S %Y %Z"
+msgid "%b %d %Y %H:%M:%S %Z"
+msgstr "%b %d %Y %H:%M:%S %Z"
#, c-format
msgid "%c is an unknown status mode."
@@ -1303,10 +1304,6 @@ msgid "%d modules loaded."
msgstr "%d moduli caricati."
#, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nickname nel gruppo."
-
-#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
msgstr "%lu nick sono memorizzati nel database, utilizzando: %.2Lf kB di memoria."
@@ -1403,6 +1400,14 @@ msgid "%s bad words list is empty."
msgstr "La lista delle parolacce di %s è vuota."
#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr "%s non può più essere aggiunto agli elenchi di accesso ai canali."
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr "%s ora può essere aggiunto agli elenchi di accesso ai canali."
+
+#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
msgstr "%s non può essere il successore del canale %s perché ne è il fondatore."
@@ -1415,20 +1420,20 @@ msgid "%s coverage is too wide; Please use a more specific mask."
msgstr "La copertura di %s è troppo ampia; usa una maschera più specifica."
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s ha %d memo, di cui %d non sono stati ancora letti."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr "%s ha %zu memo, di cui %zu non sono stati ancora letti."
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s ha %d memo, di cui 1 non è stato ancora letto."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr "%s ha %zu memo, di cui 1 non è stato ancora letto."
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s ha %d memo."
+msgid "%s currently has %zu memos."
+msgstr "%s ha %zu memo."
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s ha %d memo, nessuno dei quali è stato letto."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr "%s ha %zu memo, nessuno dei quali è stato letto."
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
@@ -1631,6 +1636,10 @@ msgid "%s's memo limit is %d."
msgstr "Il limite dei memo di %s è %d."
#, c-format
+msgid "%zu nickname(s) in the group."
+msgstr "%zu nickname nel gruppo."
+
+#, c-format
msgid "(%s ago)"
msgstr "(%s fa)"
@@ -1712,8 +1721,8 @@ msgstr "Sarà anche inviato un memo che informerà l'utente."
#, c-format
msgid ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
+"A notification memo has been sent to %s informing them you have\n"
+"read their memo."
msgstr ""
"Un memo di notifica è stato mandato a %s informandolo/a che hai\n"
"letto il suo memo."
@@ -1963,31 +1972,31 @@ msgstr "Tutti i vHost nel gruppo %s sono stati impostati a %s."
msgid "All vhosts in the group %s have been set to %s@%s."
msgstr "Tutti i vHost nel gruppo %s sono stati impostati a %s@%s."
-msgid "Allowed to (de)halfop him/herself"
+msgid "Allowed to (de)halfop themself"
msgstr "Autorizzato a dare o rimuovere lo stato di halfop a sé stesso"
msgid "Allowed to (de)halfop users"
msgstr "Autorizzato a dare o rimuovere lo stato di halfop agli utenti"
-msgid "Allowed to (de)op him/herself"
+msgid "Allowed to (de)op themself"
msgstr "Autorizzato a dare o rimuovere lo stato di op a sé stesso"
msgid "Allowed to (de)op users"
msgstr "Autorizzato a dare o rimuovere lo stato di op agli utenti"
-msgid "Allowed to (de)owner him/herself"
+msgid "Allowed to (de)owner themself"
msgstr "Autorizzato a dare o rimuovere lo stato di owner a sé stesso"
msgid "Allowed to (de)owner users"
msgstr "Autorizzato a dare o rimuovere lo stato di owner agli utenti"
-msgid "Allowed to (de)protect him/herself"
+msgid "Allowed to (de)protect themself"
msgstr "Autorizzato a dare o rimuovere lo stato di protect a sé stesso"
msgid "Allowed to (de)protect users"
msgstr "Autorizzato a dare o rimuovere lo stato di protect agli utenti"
-msgid "Allowed to (de)voice him/herself"
+msgid "Allowed to (de)voice themself"
msgstr "Autorizzato a dare o rimuovere lo stato di voice a sé stesso"
msgid "Allowed to (de)voice users"
@@ -2020,6 +2029,9 @@ msgstr "Autorizzato alla lettura dei memo del canale"
msgid "Allowed to set channel settings"
msgstr "Autorizzato ad impostare i impostazioni del canale"
+msgid "Allowed to unban themself"
+msgstr ""
+
msgid "Allowed to unban users"
msgstr "Autorizzato a rimuovere i ban sugli utenti"
@@ -2113,23 +2125,13 @@ msgstr ""
"usando, verrà automaticamente disconnesso."
msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Permette ai Services Operators di impostare le Operflag\n"
-"per qualsiasi utente. Le flag devono essere introdotte\n"
-"da \"+\" o \"-\". Per rimuovere tutte le flag, è sufficiente\n"
-"usare \"-\" senza altri parametri."
-
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
@@ -2142,15 +2144,15 @@ msgstr ""
"h per le ore e d per i giorni. \n"
"La combinazione di queste unità non è permessa. Per far\n"
"ignorare ai Services un utente in modo permanente, usa 0 come durata.\n"
-"Se viene aggiunta una maschera, deve essere nel formato user@host\n"
-"o nick!user@host, ogni altro formato sarà considerato come un nick.\n"
+"Se viene aggiunta una maschera, deve essere nel formato nick!user@host,\n"
+"ogni altro formato sarà considerato come un nick.\n"
"L'uso di Wildcard è permesso.\n"
"\n"
"Nota: non sarà forzato sugli IRC Operators."
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2170,9 +2172,9 @@ msgid ""
"current AKILL default expiry time can be found with the\n"
"STATS AKILL command."
msgstr ""
-"Permette ai Services operator di manipolare la lista AKILL.\n"
+"Permette ai Services Operator di manipolare la lista AKILL.\n"
"Se un utente che si trova nella lista AKILL cerca di connettersi,\n"
-"i Services invieranno un KILL per quell'utente e, se supportato,\n"
+"i services invieranno un KILL per quell'utente e, se supportato,\n"
"indicheranno a tutti i server di aggiungere una K:line per la\n"
"maschera che corrispondeva all'utente.\n"
" \n"
@@ -2191,7 +2193,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
"Permette ai Services Operators di manipolare la lista delle SNLINE. Se\n"
@@ -2202,7 +2204,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
@@ -2213,8 +2215,10 @@ msgstr ""
"un utente con un nick corrispondente una maschera in SQLINE prova a\n"
"connettersi, i Services non gli permetteranno di proseguire\n"
"la sua sessione su IRC.\n"
-"Se il primo carattere della maschera è #, i servizi\n"
-"impediranno l'uso dei canali corrispondenti."
+"Se il primo carattere della maschera è #, i Services\n"
+"impediranno l'uso dei canali corrispondenti. Se la maschera è una\n"
+"espressione regolare, l'espressione verrà confrontata\n"
+"anche con i canali."
msgid ""
"Allows Services Operators to manipulate the list of hosts that\n"
@@ -2340,22 +2344,22 @@ msgstr ""
" MODIFY nickserv forcemail no"
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
-"Permette di scegliere la modalità in cui i Services comunicano\n"
-"con il nick fornito. Se MSG è attivo, i Services useranno i messaggi (query),\n"
+"Ti permette di scegliere la modalità con cui i Services comunicheranno\n"
+"con l'utente specificato. Se MSG è attivo, i Services useranno i messaggi privati,\n"
"altrimenti useranno i notice."
#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
-"Ti permette di scegliere la modalità in cui i Services comunicano\n"
-"con te. Se %s è attivo, i Services useranno i messaggi (query),\n"
+"Ti permette di scegliere la modalità con cui i Services comunicheranno\n"
+"con te. Se %s è attivo, i Services useranno i messaggi privati,\n"
"altrimenti useranno i notice."
msgid ""
@@ -2633,15 +2637,15 @@ msgid "Bot bans will no longer automatically expire."
msgstr "I ban del bot non scadranno automaticamente."
#, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Gli host dei bot possono contenere solamente %d caratteri."
+msgid "Bot hosts may only be %zu characters long."
+msgstr "Gli host dei bot possono contenere solamente %zu caratteri."
msgid "Bot hosts may only contain valid host characters."
msgstr "Gli host dei bot possono contenere unicamente caratteri validi."
#, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Le ident dei bot possono contenere solamente %d caratteri."
+msgid "Bot idents may only be %zu characters long."
+msgstr "Le ident dei bot possono contenere solamente %zu caratteri."
msgid "Bot idents may only contain valid ident characters."
msgstr "Le ident dei bot possono contenere unicamente caratteri validi."
@@ -2657,8 +2661,8 @@ msgid "Bot nick"
msgstr "Bot nick"
#, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "I nick dei Bot possono contenere solamente %d caratteri."
+msgid "Bot nicks may only be %zu characters long."
+msgstr "I nick dei Bot possono contenere solamente %zu caratteri."
msgid "Bot nicks may only contain valid nick characters."
msgstr "I nick dei bot possono contenere unicamente caratteri validi."
@@ -2791,46 +2795,45 @@ msgid "Caps kicker"
msgstr "Espulsione per maiuscole"
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
msgstr ""
-"Termina immediatamente i Services senza salvarne i\n"
-"database. Questo comando non deve mai essere usato,\n"
+"Fa terminare immediatamente i Services senza salvarne i\n"
+"database. Questo comando non deve mai essere usato,\n"
"se non in caso di danni alla copia in memoria dei\n"
"database, per evitare che la copia danneggiata venga\n"
"salvata."
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
-"Rilegge il file di configurazione dei Services. Alcune\n"
-"impostazioni contenute nel file richiedono il riavvio\n"
-"effettivo dei Services per essere attivate (ad esempio\n"
-"il cambio dei nick dei Services, l'attivazione della\n"
-"limitazione delle sessioni, eccetera)."
+"Fa rileggere il file di configurazione dei Services. Si noti che\n"
+"alcune impostazioni richiedono l'effettivo riavvio dei Services\n"
+"per essere applicate (ad esempio\n"
+" il cambio dei nick dei Services,\n"
+"l'attivazione della limitazione delle sessioni, eccetera)."
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr ""
-"Salva i database su disco e riavvia i Services\n"
-"(uscita con immediato ri-esecuzione dell'eseguibile)."
+"Fa salvare i database e riavviare i Services\n"
+"(es: uscita con immediata ri-esecuzione dell'eseguibile)."
-msgid "Causes Services to save all databases and then shut down."
-msgstr "Salva i database su disco e termina i Services."
+msgid "Causes services to save all databases and then shut down."
+msgstr "Fa salvare i database e terminare i Services."
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr ""
-"Forza la scrittura su disco immediata dei database dei\n"
-"Services nello stesso istante in cui il comando viene\n"
-"inviato."
+"Fa aggiornare immediatamente i file di database dei\n"
+"Services non appena il comando viene inviato."
#, c-format
msgid "Certificate list for %s:"
@@ -2842,7 +2845,7 @@ msgstr "ChanServ è richiesto per abilitare la persistenza su questo network."
msgid "Change channel modes"
msgstr "Cambia le modalità del canale"
-msgid "Change the communication method of Services"
+msgid "Change the communication method of services"
msgstr "Cambia il metodo di comunicazione usato dai Services"
msgid "Change user modes"
@@ -2854,16 +2857,16 @@ msgstr "Modalità utente di %s modificate in %s."
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
-"Imposta il nome con cui i Services fanno riferimento al tuo\n"
+"Imposta il nome con cui i services fanno riferimento al tuo\n"
"gruppo. Il nuovo nome DEVE essere un nick del gruppo."
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
-"Imposta il nome con cui i Services si riferiscono al tuo\n"
+"Imposta il nome con cui i services si riferiscono al tuo\n"
"gruppo. Il nuovo nome DEVE essere un nick del gruppo."
msgid ""
@@ -2874,24 +2877,24 @@ msgstr ""
"deve essere registrato."
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Cambia la lingua utilizzata dai Services per inviarti\n"
-"i messaggi, ad esempio per rispondere a un comando che invii.\n"
+"Cambia la lingua utilizzata dai Services per inviare messaggi\n"
+"all'utente specificato (ad esempio per rispondere a un comando che invia).\n"
"La lingua può essere scelta dalla seguente lista di\n"
"lingue supportate:"
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Cambia la lingua utilizzata dai Services per inviarti\n"
-"i messaggi, ad esempio per rispondere a un comando che invii.\n"
+"Cambia la lingua utilizzata dai Services per inviarti messaggi\n"
+"(ad esempio per rispondere a un comando che invii).\n"
"La lingua può essere scelta dalla seguente lista di\n"
"lingue supportate:"
@@ -3027,8 +3030,8 @@ msgid "Channels that %s has access on:"
msgstr "Canali su cui %s ha accesso:"
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Canali: %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Canali: %zu voci, %zu bucket, la catena più lunga è %zu"
msgid "Chanstats"
msgstr "Statistiche canale"
@@ -3180,20 +3183,20 @@ msgid "Current module list:"
msgstr "Lista moduli attuali:"
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Numero attuale di AKILL: %d"
+msgid "Current number of AKILLs: %zu"
+msgstr "Numero attuale di AKILL: %zu"
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Numero attuale di SNLINE: %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr "Numero attuale di SNLINE: %zu"
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Numero attuale di SQLINE: %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr "Numero attuale di SQLINE: %zu"
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Utenti correnti: %d (%d operatori)"
+msgid "Current users: %zu (%d ops)"
+msgstr "Utenti correnti: %zu (%d operatori)"
msgid "DEL oper"
msgstr "DEL oper"
@@ -3365,7 +3368,7 @@ msgstr "Eliminati %d record dalla lista delle eccezioni."
#, c-format
msgid "Deleted %d entries from the %s list."
-msgstr "Eliminati %d record dalla lista %s."
+msgstr "Eliminati %d record dalla lista %s."
#, c-format
msgid "Deleted %d entries from the AKILL list."
@@ -3461,7 +3464,7 @@ msgstr "La descrizione di %s è stata impostata a %s."
#, c-format
msgid "Description of %s unset."
-msgstr "La descrizione di %s è stata rimossa."
+msgstr "La descrizione di %s è stata rimossa."
msgid "Disabled"
msgstr "Disattivato"
@@ -3723,7 +3726,7 @@ msgid ""
"Enables or disables the peace option for a channel.\n"
"When peace is set, a user won't be able to kick,\n"
"ban or remove a channel status of a user that has\n"
-"a level superior or equal to his via %s commands."
+"a level superior or equal to theirs via %s commands."
msgstr ""
"Attiva o disattiva l'opzione \"pace\" per il canale.\n"
"Quando l'opzione è attiva, gli utenti non potranno\n"
@@ -3853,8 +3856,8 @@ msgid "End of entry message list."
msgstr "Fine della lista dei messaggi di ingresso."
#, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Fine della lista forbid - %d/%d risultati mostrati."
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr "Fine della lista forbid - %zu/%zu risultati mostrati."
msgid "End of forbid list."
msgstr "Fine della lista forbid."
@@ -3939,12 +3942,12 @@ msgid "Error reloading configuration file: %s"
msgstr "Errore durante il ricaricamento del file di configurazione: %s"
#, c-format
-msgid "Error! The vHost ident is too long, please use an ident shorter than %d characters."
-msgstr "Errore! L'ident del vHost è troppo lunga, usa una ident più corta di %d caratteri."
+msgid "Error! The vHost ident is too long, please use an ident shorter than %zu characters."
+msgstr "Errore! L'ident del vHost è troppo lunga, usa una ident più corta di %zu caratteri."
#, c-format
-msgid "Error! The vHost is too long, please use a hostname shorter than %d characters."
-msgstr "Errore! Il vHost è troppo lungo, usa un hostname più corto di %d caratteri."
+msgid "Error! The vHost is too long, please use a hostname shorter than %zu characters."
+msgstr "Errore! Il vHost è troppo lungo, usa un hostname più corto di %zu caratteri."
msgid ""
"Examples:\n"
@@ -4045,7 +4048,7 @@ msgstr "Il forbid su %s non è stato trovato."
msgid "Forbid usage of nicknames, channels, and emails"
msgstr "Vieta l'uso di nickname, canali e indirizzi email"
-msgid "Force the Services databases to be updated immediately"
+msgid "Force the services databases to be updated immediately"
msgstr "Forza l'aggiornamento immediato del database dei Services"
msgid "Forcefully change a user's nickname"
@@ -4073,15 +4076,9 @@ msgstr "Fondatore"
msgid "Founder of %s changed to %s."
msgstr "Il fondatore del canale %s adesso è %s."
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "Il comando GETPASS non è disponibile perché è in uso la criptazione dei dati."
-
msgid "Ghost with your nick has been killed."
msgstr "La connessione fantasma con il tuo nick è stata disconnessa."
-msgid "Give Operflags to a certain user"
-msgstr "Imposta le operflag di un utente"
-
#, c-format
msgid ""
"Gives %s status to the selected nick on a channel. If nick is\n"
@@ -4279,8 +4276,8 @@ msgid "LIMIT enforced by "
msgstr "LIMIT forzato da "
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr "LIMIT forzato su %s, %d utenti rimossi."
+msgid "LIMIT enforced on %s, %zu users removed."
+msgstr "LIMIT forzato su %s, %zu utenti rimossi."
msgid "LIST threshold"
msgstr "LIST soglia"
@@ -4907,6 +4904,10 @@ msgstr "Memo %d da %s (%s)."
msgid "Memo %d has been deleted."
msgstr "Il memo %d è stato cancellato."
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr "Il memo %zu è stato cancellato."
+
msgid "Memo ignore list is empty."
msgstr "La lista ignorati dei memo è vuota."
@@ -5025,9 +5026,6 @@ msgstr ""
"lista dei certificati degli altri utenti.\n"
" \n"
-msgid "Modify the Services ignore list"
-msgstr "Modifica la lista ignorati dei Services"
-
#, c-format
msgid "Modify the list of %s users"
msgstr "Modifica la lista degli utenti %s"
@@ -5041,6 +5039,9 @@ msgstr "Modifica la lista degli utenti con privilegi"
msgid "Modify the nickname client certificate list"
msgstr "Modifica la lista dei certificati del client per il nickname"
+msgid "Modify the services ignore list"
+msgstr "Modifica la lista ignorati dei Services"
+
msgid "Modify the session-limit exception list"
msgstr "Modifica la lista delle eccezioni del limite delle sessioni"
@@ -5091,6 +5092,9 @@ msgstr "Statistiche network per %s:"
msgid "Never"
msgstr "Mai"
+msgid "Never-op"
+msgstr "Mai-op"
+
msgid "Nick"
msgstr "Nick"
@@ -5139,8 +5143,8 @@ msgid "Nick %s isn't registered."
msgstr "Il nick %s non è registrato."
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Il nick %s è stato troncato a %d caratteri."
+msgid "Nick %s was truncated to %zu characters."
+msgstr "Il nick %s è stato troncato a %zu caratteri."
#, c-format
msgid "Nick %s will expire."
@@ -5183,8 +5187,8 @@ msgid "Nick %s is now suspended."
msgstr "Il nick %s è ora sospeso."
#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr "Nick troppo lungo, lunghezza massima consentita %u caratteri."
+msgid "Nick too long, max length is %zu characters."
+msgstr "Nick troppo lungo, lunghezza massima consentita %zu caratteri."
#, c-format
msgid "Nickname %s has been dropped."
@@ -5376,14 +5380,6 @@ msgid "Oper type %s has not been configured."
msgstr "Il tipo di operatore %s non è stato configurato."
#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "Le operflags %s sono state aggiunte a %s."
-
-#, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "Le operflags %s sono state rimosse a %s."
-
-#, c-format
msgid "Opertype %s has no allowed commands."
msgstr "Il tipo di oper %s non ha comandi permessi."
@@ -5414,17 +5410,9 @@ msgid "Password accepted."
msgstr "Password accettata."
#, c-format
-msgid "Password for %s changed to %s."
-msgstr "La password di %s è stata cambiata in %s."
-
-#, c-format
msgid "Password for %s changed."
msgstr "La password di %s è stata cambiata."
-#, c-format
-msgid "Password for %s is %s."
-msgstr "La password di %s è %s."
-
msgid "Password incorrect."
msgstr "Password errata."
@@ -5450,13 +5438,14 @@ msgid "Please contact an Operator to get a vHost assigned to this nick."
msgstr "Per favore contatta un Operatore per avere un vHost assegnato a questo nick."
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
-"Attenzione, prova di nuovo con una password più sicura. Le password devono essere lunghe almeno\n"
-"5 caratteri, non devono essere facilmente intuibili (ad es. il proprio nome o nick)\n"
-"e non possono contenere i caratteri di spazio e di tabulazione."
+"Attenzione, prova di nuovo con una password più sicura. Le password non \n"
+"devono essere facilmente intuibili (ad es. il proprio nome o nick)\n"
+" e \n"
+"non possono contenere i caratteri di spazio e di tabulazione.\n"
msgid "Please use a valid server name when juping."
msgstr "Utilizza un nome server valido per eseguire il \"jupe\"."
@@ -5465,24 +5454,24 @@ msgid "Please use the symbol of # when attempting to register."
msgstr "Per favore usa il simbolo # davanti al nome del canale per poter procedere con la registrazione."
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Attendi %d secondi e riprova."
+msgid "Please wait %lu seconds and retry."
+msgstr "Attendi %lu secondi e riprova."
#, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Attendi %d secondi prima di richiedere un nuovo vHost."
+msgid "Please wait %lu seconds before requesting a new vHost."
+msgstr "Attendi %lu secondi prima di richiedere un nuovo vHost."
#, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Attendi %d secondi prima di usare di nuovo il comando %s."
+msgid "Please wait %lu seconds before using the %s command again."
+msgstr "Attendi %lu secondi prima di usare di nuovo il comando %s."
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Per favore attendi %d secondi prima di usare di nuovo il comando GROUP."
+msgid "Please wait %lu seconds before using the GROUP command again."
+msgstr "Per favore attendi %lu secondi prima di usare di nuovo il comando GROUP."
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "Per favore attendi %d secondi prima di usare di nuovo il comando REGISTER."
+msgid "Please wait %lu seconds before using the REGISTER command again."
+msgstr "Per favore attendi %lu secondi prima di usare di nuovo il comando REGISTER."
#, c-format
msgid "Pooled %s."
@@ -5512,7 +5501,7 @@ msgstr "Nasconde il nickname dall'output del comando LIST"
msgid "Prevent the nickname from expiring"
msgstr "Impedisce ad un nickname di scadere"
-msgid "Prevents users being kicked by Services"
+msgid "Prevents users being kicked by services"
msgstr "Impedisce agli utenti di essere espulsi dai Services"
msgid "Private"
@@ -5670,16 +5659,16 @@ msgid "Registered"
msgstr "Registrato"
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Canali registrati: %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Canali registrati: %zu voci, %zu bucket, la catena più lunga è %zu"
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Gruppi di nick registrati: %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Gruppi di nick registrati: %zu voci, %zu bucket, la catena più lunga è %zu"
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Nickname registrati: %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Nickname registrati: %zu voci, %zu bucket, la catena più lunga è %zu"
#, c-format
msgid "Registered only enforced on %s."
@@ -5697,16 +5686,16 @@ msgid ""
"\"founder\" of the channel. The channel founder is allowed\n"
"to change all of the channel settings for the channel;\n"
"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel."
+"channel operator privileges when they enter the channel."
msgstr ""
-"Registra un canale nel database di %s. Per poter usare\n"
+"Registra un canale nel database di %s. Per poter usare\n"
"questo commando, prima di tutto, devi essere operatore (op)\n"
"del canale che intendi registrare. La descrizione, che deve\n"
"essere specificata, è una descrizione generica dello scopo\n"
"del canale.\n"
" \n"
"Quando registri un canale, vieni registrato come \"fondatore\"\n"
-"del canale. Il fondatore di un canale può modificare tutte le'\n"
+"del canale. Il fondatore di un canale può modificare tutte le'\n"
"impostazioni del canale e riceverà automaticamente da %s\n"
"i privilegi di operatore del canale quando vi accede."
@@ -5727,7 +5716,7 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
"Registra il tuo nick nel database di %s. Quando il\n"
@@ -5748,7 +5737,7 @@ msgstr ""
"anche peggiore, infatti %s non ti permetterà di farlo.\n"
"Inoltre, le password brevi sono facili da indovinare con\n"
"meno tentativi, pertanto è necessario scegliere una password \n"
-"di almeno 5 caratteri. Infine, gli spazi non possono essere \n"
+"di almeno %u caratteri. Infine, gli spazi non possono essere \n"
"usati all'interno di una password."
msgid "Registration is currently disabled."
@@ -5871,9 +5860,6 @@ msgstr "Mantiene il modi quando il canale non è in uso"
msgid "Retain topic when channel is not in use"
msgstr "Mantiene il topic quando il canale non è in uso"
-msgid "Retrieve the password for a nickname"
-msgstr "Recupera la password di un nickname"
-
msgid "Retrieves the vhost requests"
msgstr "Recupera le richieste di vHost"
@@ -5890,18 +5876,6 @@ msgid "Returns the owner status of the given nickname"
msgstr "Indica lo stato di proprietario del nickname specificato"
msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Restituisce la password del nick specificato.\n"
-"Da notare che quando questo comando viene usato,\n"
-"verrà inviato un WALLOPS o GLOBOPS ad indicare la\n"
-"persona che l'ha utilizzato e su quale nick è stato\n"
-"utilizzato."
-
-msgid ""
"Returns whether the user using the given nickname is\n"
"recognized as the owner of the nickname. The response has\n"
"this format:\n"
@@ -5963,8 +5937,8 @@ msgstr "Solo SSL forzato su %s."
msgid "SSLONLY enforced by "
msgstr "SSLONLY forzato da "
-msgid "Save databases and restart Services"
-msgstr "Salva i database e riavvia i Services"
+msgid "Save databases and restart services"
+msgstr "Salva i database e riavvia i services"
msgid "Searches logs for a matching pattern"
msgstr "Cerca nei log per la chiave specificata corrispondente"
@@ -6067,7 +6041,7 @@ msgstr "Invia un memo contenente testo-memo a tutto lo staff dei servizi."
msgid ""
"Sends the named nick or channel a memo containing\n"
"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
+"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered."
msgstr ""
"Invia un memo che contiene il testo-memo al nick\n"
@@ -6079,10 +6053,10 @@ msgstr ""
msgid ""
"Sends the named nick or channel a memo containing\n"
"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
+"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered.\n"
"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
+"memo will be sent to the sender informing them that the memo\n"
"has been read."
msgstr ""
"Invia un memo contenente testo-memo al nick o canale\n"
@@ -6261,8 +6235,8 @@ msgid "Session limiting is disabled."
msgstr "Il limite delle sessioni è disabilitato."
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Sessioni: %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Sessioni: %zu voci, %zu bucket, la catena più lunga è %zu"
msgid "Set SET-options on another nickname"
msgstr "Imposta le opzioni SET su un altro nickname"
@@ -6270,8 +6244,8 @@ msgstr "Imposta le opzioni SET su un altro nickname"
msgid "Set channel options and information"
msgstr "Imposta le opzioni e le informazioni di un canale"
-msgid "Set how Services make bans on the channel"
-msgstr "Imposta il tipo di ban che sarà usato dai Services"
+msgid "Set how services make bans on the channel"
+msgstr "Imposta il modo in cui i Services effettuano i ban sul canale"
msgid "Set options related to memos"
msgstr "Imposta le opzioni relative ai memo"
@@ -6285,14 +6259,14 @@ msgstr "Imposta il canale come permanente"
msgid "Set the channel description"
msgstr "Imposta la descrizione del canale"
-msgid "Set the display of your group in Services"
+msgid "Set the display of your group in services"
msgstr "Imposta il nome del tuo gruppo"
msgid "Set the founder of a channel"
msgstr "Imposta il fondatore del canale"
-msgid "Set the language Services will use when messaging you"
-msgstr "Imposta la lingua utilizzata dai Services"
+msgid "Set the language services will use when messaging you"
+msgstr "Imposta la lingua utilizzata dai Services per inviarti messaggi"
msgid "Set the nickname password"
msgstr "Imposta la password del nick"
@@ -6306,7 +6280,7 @@ msgstr "Imposta il vHost per tutti i nick di un gruppo"
msgid "Set the vhost of another user"
msgstr "Imposta il vHost di un altro utente"
-msgid "Set various global Services options"
+msgid "Set various global services options"
msgstr "Imposta varie opzioni globali dei Services"
msgid "Set your nickname password"
@@ -6556,7 +6530,7 @@ msgstr ""
"oltre che il vHost."
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -6564,7 +6538,7 @@ msgid ""
" SUPERADMIN Activate or deactivate super admin mode\n"
" LIST List the options"
msgstr ""
-"Imposta varie opzioni globali dei Services. Le opzioni\n"
+"Imposta varie opzioni globali dei Services. Le opzioni\n"
"configurabili sono:\n"
" READONLY Imposta la modalità sola-lettura o lettura-scrittura\n"
" DEBUG Attiva o disattiva la modalità di debug\n"
@@ -6608,6 +6582,9 @@ msgstr ""
"Imposta se il canale scadrà o meno in caso di inutilizzo. Se\n"
"l'opzione è impostata a ON, il canale non scadrà."
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr "Imposta se il nickname specificato può essere aggiunto a un elenco di accesso al canale."
+
#, c-format
msgid ""
"Sets whether the given nickname will be given its status modes\n"
@@ -6628,6 +6605,9 @@ msgstr ""
"Imposta se il nickname specificato scadrà. Impostandolo su\n"
"ON eviterà che il nickname scada."
+msgid "Sets whether you can be added to a channel access list."
+msgstr "Imposta se puoi essere aggiunto a un elenco di accesso ai canali."
+
#, c-format
msgid ""
"Sets whether you will be given your channel status modes automatically.\n"
@@ -6659,12 +6639,12 @@ msgstr "Il parametro dell'opzione super admin deve essere ON o OFF."
msgid "Should services automatically give status to users"
msgstr "Abilita/disabilita l'impostazione automatica dello stato agli utenti"
-msgid "Show status of Services and network"
+msgid "Show status of services and network"
msgstr "Mostra lo stato dei Services e della rete"
#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr "Mostrati %d/%d risultati per %s."
+msgid "Showed %zu/%zu matches for %s."
+msgstr "Mostrati %zu/%zu risultati per %s."
msgid "Sign kicks that are done with the KICK command"
msgstr "Firma i kick effettuati con il comando KICK"
@@ -7042,13 +7022,13 @@ msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
+"users will not be allowed to modify any services data,\n"
"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
@@ -7135,8 +7115,8 @@ msgstr ""
"livello di accesso 5 o superiori sul canale."
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7146,7 +7126,7 @@ msgid ""
msgstr ""
"Fa sì che i Services blocchino un server, creando un server\n"
"\"fasullo\" connesso ai Services per evitare che il server reale\n"
-"possa connettersi alla rete. Questo blocco può essere rimosso\n"
+"possa connettersi alla rete. Questo blocco può essere rimosso\n"
"utilizzando il comando standard SQUIT. Se viene indicato\n"
"un motivo, questo sarà utilizzato nel campo delle informazioni\n"
"del server, altrimenti, le informazioni conterranno il testo\n"
@@ -7156,8 +7136,8 @@ msgstr ""
msgid "Tells you about the last time a user was seen"
msgstr "Ti informa sull'ultima volta che un utente è stato visto online"
-msgid "Terminate Services WITHOUT saving"
-msgstr "Termina i Services senza salvare i database"
+msgid "Terminate services WITHOUT saving"
+msgstr "Termina i Services SENZA salvare"
msgid "Terminate services with save"
msgstr "Termina i Services salvando i database"
@@ -7326,7 +7306,7 @@ msgid ""
"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
"disables an automatic feature or disallows access to a\n"
"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it). Use LEVELS SET founder to make a level\n"
+"can always re-enable it). Use LEVELS SET founder to make a level\n"
"founder only.\n"
" \n"
"LEVELS LIST shows the current levels for each function or\n"
@@ -7585,8 +7565,8 @@ msgstr ""
"per far rilasciare il blocco dei servizi sul tuo nick."
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "Ci sono %d memo sul canale %s."
+msgid "There are %zu memos on channel %s."
+msgstr "Ci sono %zu memo sul canale %s."
msgid ""
"There are no bots available at this time.\n"
@@ -7610,16 +7590,16 @@ msgid "There currently are no logging configurations for %s."
msgstr "Attualmente non è presente alcuna configurazione per il logging su %s."
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "C'è %d memo sul canale %s."
+msgid "There is %zu memo on channel %s."
+msgstr "C'è %zu memo sul canale %s."
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
+"Type %s%s READ %s %zu to read it."
msgstr ""
"C'è un nuovo memo sul canale %s.\n"
-"Digita %s%s READ %s %d per leggerlo."
+"Digita %s%s READ %s %zu per leggerlo."
#, c-format
msgid "There is no bot assigned to %s anymore."
@@ -7832,7 +7812,7 @@ msgid "This command retrieves the vhost requests."
msgstr "Questo comando recupera le richieste di vHosts."
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -7845,10 +7825,12 @@ msgid ""
" containing Anope and lists the most recent 500 of them."
msgstr ""
"Questo comando effettua una ricerca nel file di log dei Services\n"
-"utilizzando il pattern specificato. Gli argomenti day e limit possono essere usati per specificare fino a quanti giorni\n"
-"estendere la ricerca nei log e il limite dei risultati da mostrare.\n"
-"Come impostazione predefinita questo comando recupera una settimana di\n"
-"log e limita i risultati a 50.\n"
+"utilizzando il pattern specificato. Gli argomenti day e limit possono\n"
+"essere usati per specificare fino a quanti giorni estendere la ricerca\n"
+"nei log e il limite dei risultati da mostrare.\n"
+" Come impostazione\n"
+"predefinita questo comando recupera una settimana di log e limita\n"
+"i risultati a 50.\n"
" \n"
"Per esempio:\n"
" LOGSEARCH +21d +500l Anope\n"
@@ -8302,12 +8284,12 @@ msgid "Users"
msgstr "Utenti"
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Utenti (nick): %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Utenti (nick): %lu voci, %lu bucket, la catena più lunga è %zu"
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Utenti (uid): %lu voci, %lu bucket, la catena più lunga è %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Utenti (uid): %lu voci, %lu bucket, la catena più lunga è %zu"
msgid "Users list:"
msgstr "Lista utenti:"
@@ -8335,10 +8317,10 @@ msgid "VIEW host"
msgstr "VIEW host"
msgid "VIEW [mask | list | id]"
-msgstr "VIEW [maschera | list | id]"
+msgstr "VIEW [maschera | lista | id]"
msgid "VIEW [mask | list]"
-msgstr "VIEW [maschera | list]"
+msgstr "VIEW [maschera | lista]"
msgid "Value"
msgstr "Valore"
@@ -8407,7 +8389,7 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
"Senza nessun parametro, annulla l'effetto del comando IDENTIFY,\n"
@@ -8416,14 +8398,14 @@ msgstr ""
"di nuovo.\n"
" \n"
"Con un parametro, il funzionamento è identico ma viene applicato\n"
-"al nick specificato. Se si indica anche REVALIDATE, i Services\n"
+"al nick specificato. Se si indica anche REVALIDATE, i Services\n"
"chiederanno al nick specificato di re-identificarsi.\n"
-"Questo modo di utilizzo è limitato ai Services Operator."
+"Questo utilizzo è limitato ai Services Operator."
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -8488,9 +8470,6 @@ msgstr "Non stai usando un certificato del client."
msgid "You are now a super admin."
msgstr "Ora sei un Super Admin."
-msgid "You are now an IRC Operator."
-msgstr "Ora sei un IRC Operator."
-
msgid "You are now identified for your nick. Change your password now."
msgstr "Adesso sei identificato per il tuo nick. Cambia la tua password adesso."
@@ -8502,17 +8481,17 @@ msgstr "Adesso sei nel gruppo %s."
msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr "Attenzione: Hai superato il numero massimo di memo (%d). Non potrai ricevere nuovi memo finché non ne eliminerai alcuni dal tuo archivio."
-msgid "You can not NOOP Services."
-msgstr "Non puoi usare NOOP sui Services."
+msgid "You can not NOOP services."
+msgstr "Non puoi usare NOOP sui services."
-msgid "You can not disable the founder privilege because it would be impossible to reenable it at a later time."
+msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
msgstr "Non puoi disabilitare il privilegio di fondatore perché in seguito sarebbe impossibile riabilitarlo."
msgid "You can not jupe an already juped server."
msgstr "Non puoi bloccare un server già bloccato."
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "Non puoi bloccare lo pseudo-server dei Services o il tuo uplink."
+msgid "You can not jupe your services' pseudoserver or your uplink server."
+msgstr "Non puoi bloccare lo pseudo-server dei services o il tuo uplink."
#, c-format
msgid "You can not reload this module directly, instead reload %s."
@@ -8558,20 +8537,20 @@ msgid "You cannot use this command."
msgstr "Non puoi usare questo comando."
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Hai %d memo, di cui %d non sono stati ancora letti."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr "Hai %zu memo, di cui %zu non sono stati ancora letti."
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Hai %d memo, di cui 1 non è stato ancora letto."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr "Hai %zu memo, di cui 1 non è stato ancora letto."
#, c-format
-msgid "You currently have %d memos."
-msgstr "Hai %d memo."
+msgid "You currently have %zu memos."
+msgstr "Hai %zu memo."
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Hai %d memo, nessuno di questi è stato letto."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr "Hai %zu memo, nessuno di questi è stato letto."
msgid "You currently have 1 memo, and it has not yet been read."
msgstr "Hai 1 memo, e non è stato ancora letto."
@@ -8604,10 +8583,10 @@ msgstr "Hai un nuovo memo."
#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
+"Type %s%s READ %zu to read it."
msgstr ""
"Hai un nuovo memo da %s.\n"
-"Digita %s%s READ %d per leggerlo."
+"Digita %s%s READ %zu per leggerlo."
#, c-format
msgid "You have been invited to %s by %s."
@@ -8668,9 +8647,6 @@ msgstr "Non puoi cambiare la password di altri Services Operators."
msgid "You may not drop other Services Operators' nicknames."
msgstr "Non puoi de-registrare il nickname di altri Services Operators."
-msgid "You may not get the password of other Services Operators."
-msgstr "Non puoi richiedere la password di altri Services Operators."
-
msgid "You may not suspend other Services Operators' nicknames."
msgstr "Non uoi sospendere il nickname di altri Services Operators."
@@ -8711,8 +8687,8 @@ msgid "You must enter the channel name twice as a confirmation that you wish to
msgstr "È necessario specificare il nome del canale due volte come conferma che vuoi de-registrare %s."
#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr "È necessario aver usato questo nick per almeno %d secondi prima di poterlo registrare."
+msgid "You must have been using this nick for at least %lu seconds to register."
+msgstr "È necessario aver usato questo nick per almeno %lu secondi prima di poterlo registrare."
#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
@@ -8850,12 +8826,12 @@ msgid "Your passcode has been re-sent to %s."
msgstr "Il codice di attivazione è stato re-inviato a %s."
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "La tua password è %s - non dimenticarla."
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr "La password scelta è troppo lunga. Non deve superare %u caratteri."
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr "La password scelta è troppo lunga. Non deve superare %u caratteri."
+msgid "Your password is too short. It must be longer than %u characters."
+msgstr "La password scelta è troppo corta. Deve contenere almeno %u caratteri."
msgid "Your password reset request has expired."
msgstr "La tua richiesta di reset della password è scaduta."
@@ -8920,16 +8896,16 @@ msgid "[channel] LIST"
msgstr "[canale] LIST"
msgid "[channel] [list | NEW]"
-msgstr "[canale] [list | NEW]"
+msgstr "[canale] [lista | NEW]"
msgid "[channel] [nick]"
msgstr "[canale] [nick]"
msgid "[channel] {num | list | LAST | ALL}"
-msgstr "[canale] {num | list | LAST | ALL}"
+msgstr "[canale] {num | lista | LAST | ALL}"
msgid "[channel] {num | list | LAST | NEW | ALL}"
-msgstr "[canale] {num | list | LAST | NEW | ALL}"
+msgstr "[canale] {num | lista | LAST | NEW | ALL}"
msgid "[key|#X-Y]"
msgstr "[chiave|#X-Y]"
diff --git a/language/anope.nl_NL.po b/language/anope.nl_NL.po
index c34311cda..f4adda980 100644
--- a/language/anope.nl_NL.po
+++ b/language/anope.nl_NL.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-01-30 03:35+0100\n"
-"PO-Revision-Date: 2024-01-31 05:26+0100\n"
+"POT-Creation-Date: 2024-02-22 16:34+0000\n"
+"PO-Revision-Date: 2024-02-22 16:39+0000\n"
"Last-Translator: Robby <robby@chatbelgie.be>\n"
"Language-Team: Dutch\n"
"Language: nl_NL\n"
@@ -16,6 +16,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.4\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
@@ -210,6 +211,10 @@ msgid "%s disabled on channel %s."
msgstr "%s uitgeschakeld op kanaal %s."
#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr "%s wenst niet toegevoegd te worden aan kanaal toegangslijsten."
+
+#, c-format
msgid "%s has been invited to %s."
msgstr "%s werd uitgenodigd naar %s."
@@ -527,11 +532,11 @@ msgstr "kanaal nick reden"
msgid "channel what"
msgstr "kanaal wat"
-msgid "channel ADD mask"
-msgstr "kanaal ADD masker"
+msgid "channel ADD mask level [description]"
+msgstr "kanaal ADD masker niveau [beschrijving]"
-msgid "channel ADD mask level"
-msgstr "kanaal ADD masker niveau"
+msgid "channel ADD mask [description]"
+msgstr "kanaal ADD masker [beschrijving]"
msgid "channel ADD message"
msgstr "kanaal ADD bericht"
@@ -617,8 +622,8 @@ msgstr "kanaal [+verlooptijd] [reden]"
msgid "channel [+expiry] {nick | mask} [reason]"
msgstr "kanaal [+verlooptijd] {nick | masker} [reden]"
-msgid "channel [MODIFY] mask changes"
-msgstr "kanaal [MODIFY] masker wijzigingen"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr "kanaal [MODIFY] masker wijzigingen [beschrijving]"
msgid "channel [SET] [topic]"
msgstr "kanaal [SET] [topic]"
@@ -680,9 +685,6 @@ msgstr "nick kanaal"
msgid "nick channel [reason]"
msgstr "nick kanaal [reden]"
-msgid "nick flags"
-msgstr "nick vlaggen"
-
msgid "nick hostmask"
msgstr "nick hostmasker"
@@ -841,12 +843,12 @@ msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
" \n"
"Nicknames die niet meer gebruikt worden zullen na een tijd\n"
"automatisch verlopen, oftewel: ze zullen verwijderd worden na\n"
-"%d dagen van onbruik."
+"%lu dagen van onbruik."
msgid ""
" \n"
@@ -944,12 +946,12 @@ msgstr ""
#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
" \n"
-"Merk op dat elk kanaal dat %d dagen ongebruikt is (d.w.z. dat\n"
+"Merk op dat elk kanaal dat %lu dagen ongebruikt is (d.w.z. dat\n"
"er geen gebruiker die op de toegangslijst staat in die periode\n"
"het kanaal binnen is gekomen) automatisch zal worden verwijderd."
@@ -1269,11 +1271,11 @@ msgid "%-8s %s"
msgstr "%-8s %s"
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "%2lu %-16s letters: %s, woorden: %s, lijnen: %s, smileys: %s, acties: %s"
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr "%2d %-16s letters: %s, woorden: %s, lijnen: %s, smileys: %s, acties: %s"
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr "%b %d %H:%M:%S %Y %Z"
+msgid "%b %d %Y %H:%M:%S %Z"
+msgstr "%b %d %Y %H:%M:%S %Z"
#, c-format
msgid "%c is an unknown status mode."
@@ -1300,10 +1302,6 @@ msgid "%d modules loaded."
msgstr "%d modules geladen."
#, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nick(s) in de groep."
-
-#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
msgstr "%lu nicks zijn opgeslagen in de database, geheugenverbruik is %.2Lf kB."
@@ -1400,6 +1398,14 @@ msgid "%s bad words list is empty."
msgstr "%s slechtewoordenlijst is leeg."
#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr "%s kan niet langer meer toegevoegd worden aan kanaal toegangslijsten."
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr "%s kan vanaf nu toegevoegd worden aan kanaal toegangslijsten."
+
+#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
msgstr "%s kan de opvolger niet zijn op kanaal %s omdat die de stichter is."
@@ -1412,20 +1418,20 @@ msgid "%s coverage is too wide; Please use a more specific mask."
msgstr "%s is te breed; gelieve een meer specifiek masker te gebruiken."
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s heeft momenteel %d memo's, waarvan er %d ongelezen zijn."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr "%s heeft momenteel %zu memo's, waarvan er %zu ongelezen zijn."
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s heeft momenteel %d memo's, waarvan er 1 ongelezen is."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr "%s heeft momenteel %zu memo's, waarvan er 1 ongelezen is."
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s heeft momenteel %d memo's."
+msgid "%s currently has %zu memos."
+msgstr "%s heeft momenteel %zu memo's."
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s heeft momenteel %d memo's; allemaal zijn ze ongelezen."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr "%s heeft momenteel %zu memo's; allemaal zijn ze ongelezen."
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
@@ -1628,6 +1634,10 @@ msgid "%s's memo limit is %d."
msgstr "%s's memolimiet is %d."
#, c-format
+msgid "%zu nickname(s) in the group."
+msgstr "%zu nick(s) in de groep."
+
+#, c-format
msgid "(%s ago)"
msgstr "(%s geleden)"
@@ -1960,31 +1970,31 @@ msgstr "Alle vHosts in de groep %s zijn gewijzigd naar %s."
msgid "All vhosts in the group %s have been set to %s@%s."
msgstr "Alle vHosts in de groep %s zijn gewijzigd naar %s@%s."
-msgid "Allowed to (de)halfop him/herself"
+msgid "Allowed to (de)halfop themself"
msgstr "Kan zichzelf (de)halfop'en"
msgid "Allowed to (de)halfop users"
msgstr "Kan gebruikers (de)halfop'en"
-msgid "Allowed to (de)op him/herself"
+msgid "Allowed to (de)op themself"
msgstr "Kan zichzelf (de)op'en"
msgid "Allowed to (de)op users"
msgstr "Kan gebruikers (de)op'en"
-msgid "Allowed to (de)owner him/herself"
+msgid "Allowed to (de)owner themself"
msgstr "Kan zichzelf (de)owner'en"
msgid "Allowed to (de)owner users"
msgstr "Kan gebruikers (de)owner'en"
-msgid "Allowed to (de)protect him/herself"
+msgid "Allowed to (de)protect themself"
msgstr "Kan zichzelf (de)protect'en"
msgid "Allowed to (de)protect users"
msgstr "Kan gebruikers (de)protect'en"
-msgid "Allowed to (de)voice him/herself"
+msgid "Allowed to (de)voice themself"
msgstr "Kan zichzelf (de)voice'en"
msgid "Allowed to (de)voice users"
@@ -2017,6 +2027,9 @@ msgstr "Kan kanaalmemo's lezen"
msgid "Allowed to set channel settings"
msgstr "Kan kanaalinstellingen wijzigen"
+msgid "Allowed to unban themself"
+msgstr "Kan bans op zichzelf verwijderen"
+
msgid "Allowed to unban users"
msgstr "Kan bans op gebruikers verwijderen"
@@ -2113,23 +2126,13 @@ msgstr ""
"gebruiker worden gekillt."
msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Stelt Services Operators in staat om Opervlaggen te geven\n"
-"aan een gebruiker. Vlaggen moeten worden vooraf\n"
-"gegaan door een \"+\" of een \"-\". Om alle vlaggen te verwijderen\n"
-"kun je simpelweg een \"-\" typen in de plaats van de vlaggen."
-
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
@@ -2151,7 +2154,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2197,7 +2200,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
"Stelt Services Operators in staat de SNLINE lijst te beheren.\n"
@@ -2208,7 +2211,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
@@ -2350,8 +2353,8 @@ msgstr ""
" MODIFY nickserv forcemail no"
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
"Laat je toe te bepalen hoe services berichten naar de gegeven\n"
@@ -2360,8 +2363,8 @@ msgstr ""
#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
"Laat je toe te bepalen hoe services berichten naar jou\n"
@@ -2641,15 +2644,15 @@ msgid "Bot bans will no longer automatically expire."
msgstr "Bot bans zullen niet langer automatisch verlopen."
#, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Bot hosts mogen maximaal %d karakters bevatten."
+msgid "Bot hosts may only be %zu characters long."
+msgstr "Bot hosts mogen maximaal %zu karakters bevatten."
msgid "Bot hosts may only contain valid host characters."
msgstr "Bot hosts mogen alleen geldige host-karakters bevatten."
#, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Bot idents mogen maximaal %d karakters bevatten."
+msgid "Bot idents may only be %zu characters long."
+msgstr "Bot idents mogen maximaal %zu karakters bevatten."
msgid "Bot idents may only contain valid ident characters."
msgstr "Bot idents mogen alleen geldige ident-karakters bevatten."
@@ -2665,8 +2668,8 @@ msgid "Bot nick"
msgstr "Bot nick"
#, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Bot nicks mogen maximaal %d karakters bevatten."
+msgid "Bot nicks may only be %zu characters long."
+msgstr "Bot nicks mogen maximaal %zu karakters bevatten."
msgid "Bot nicks may only contain valid nick characters."
msgstr "Bot nicks mogen alleen geldige nick-karakters bevatten."
@@ -2799,7 +2802,7 @@ msgid "Caps kicker"
msgstr "Hoofdletterskicker"
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
@@ -2810,9 +2813,9 @@ msgstr ""
"wordt gevreesd en ze niet moeten worden opgeslagen."
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
"Zorgt ervoor dat services het configuratiebestand opnieuw\n"
@@ -2821,17 +2824,17 @@ msgstr ""
"services' nicknames, activatie van de sessielimiet, etc.)."
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr ""
"Zorgt ervoor dat services alle databases opslaat en dan\n"
"zichzelf opnieuw opstart."
-msgid "Causes Services to save all databases and then shut down."
+msgid "Causes services to save all databases and then shut down."
msgstr "Zorgt ervoor dat services alle databases opslaat en dan afsluit."
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr ""
"Zorgt ervoor dat services alle database bestanden bijwerkt zodra je\n"
@@ -2847,7 +2850,7 @@ msgstr "ChanServ is vereist om PERSIST te activeren op dit netwerk."
msgid "Change channel modes"
msgstr "Wijzig kanaalmodes"
-msgid "Change the communication method of Services"
+msgid "Change the communication method of services"
msgstr "Verander de communicatiemethode van services"
msgid "Change user modes"
@@ -2859,14 +2862,14 @@ msgstr "Gebruikersmodes van %s veranderd naar %s."
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
"Verandert de weergegeven nick van de nick-groep in services.\n"
"De nieuwe weergave MOET een nick in de groep zijn."
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
"Verandert de weergegeven nick van je nick-groep in services.\n"
"De nieuwe weergave MOET een nick in je groep zijn."
@@ -2879,7 +2882,7 @@ msgstr ""
"een geregistreerde nick zijn."
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
@@ -2890,7 +2893,7 @@ msgstr ""
"worden uit de volgende lijst van ondersteunde talen:"
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
@@ -3034,8 +3037,8 @@ msgid "Channels that %s has access on:"
msgstr "Kanalen waar %s toegang op heeft:"
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kanalen: %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Kanalen: %zu vermeldingen, %zu emmers, langste ketting is %zu"
msgid "Chanstats"
msgstr "Kanaalstatistieken"
@@ -3188,20 +3191,20 @@ msgid "Current module list:"
msgstr "Huidige modulelijst:"
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Huidig aantal AKILLs: %d"
+msgid "Current number of AKILLs: %zu"
+msgstr "Huidig aantal AKILLs: %zu"
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Huidig aantal SNLINEs: %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr "Huidig aantal SNLINEs: %zu"
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Huidig aantal SQLINEs: %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr "Huidig aantal SQLINEs: %zu"
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Huidig aantal gebruikers: %d (%d ops)"
+msgid "Current users: %zu (%d ops)"
+msgstr "Huidig aantal gebruikers: %zu (%d ops)"
msgid "DEL oper"
msgstr "DEL oper"
@@ -3865,8 +3868,8 @@ msgid "End of entry message list."
msgstr "Einde van berichtenlijst."
#, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Einde van verbodslijst - %d/%d resultaten weergegeven."
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr "Einde van verbodslijst - %zu/%zu resultaten weergegeven."
msgid "End of forbid list."
msgstr "Einde van verbodslijst."
@@ -3951,12 +3954,12 @@ msgid "Error reloading configuration file: %s"
msgstr "Fout bij laden configuratiebestand: %s"
#, c-format
-msgid "Error! The vHost ident is too long, please use an ident shorter than %d characters."
-msgstr "Fout! De vHost ident is te lang, gelieve een ident korter dan %d karakters op te geven."
+msgid "Error! The vHost ident is too long, please use an ident shorter than %zu characters."
+msgstr "Fout! De vHost ident is te lang, gelieve een ident korter dan %zu karakters op te geven."
#, c-format
-msgid "Error! The vHost is too long, please use a hostname shorter than %d characters."
-msgstr "Fout! De vHost is te lang, gelieve een host korter dan %d karakters op te geven."
+msgid "Error! The vHost is too long, please use a hostname shorter than %zu characters."
+msgstr "Fout! De vHost is te lang, gelieve een host korter dan %zu karakters op te geven."
msgid ""
"Examples:\n"
@@ -4056,7 +4059,7 @@ msgstr "Verbod op %s werd niet gevonden."
msgid "Forbid usage of nicknames, channels, and emails"
msgstr "Verbied gebruik van nicks, kanalen en e-mails"
-msgid "Force the Services databases to be updated immediately"
+msgid "Force the services databases to be updated immediately"
msgstr "Forceer dat de services databases onmiddellijk worden geüpdatet"
msgid "Forcefully change a user's nickname"
@@ -4084,15 +4087,9 @@ msgstr "Stichter"
msgid "Founder of %s changed to %s."
msgstr "Stichter van %s veranderd naar %s."
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "GETPASS commando is onbeschikbaar omdat encryptie aan staat."
-
msgid "Ghost with your nick has been killed."
msgstr "Ghost met jouw nick is gekilld."
-msgid "Give Operflags to a certain user"
-msgstr "Geef Operflags aan een bepaalde gebruiker"
-
#, c-format
msgid ""
"Gives %s status to the selected nick on a channel. If nick is\n"
@@ -4290,8 +4287,8 @@ msgid "LIMIT enforced by "
msgstr "LIMIT afgedwongen door "
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr "LIMIT afgedwongen op %s, %d gebruikers werden verwijderd."
+msgid "LIMIT enforced on %s, %zu users removed."
+msgstr "LIMIT afgedwongen op %s, %zu gebruikers werden verwijderd."
msgid "LIST threshold"
msgstr "LIST aantal"
@@ -4921,6 +4918,10 @@ msgstr "Memo %d van %s (%s)."
msgid "Memo %d has been deleted."
msgstr "Memo %d werd verwijderd."
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr "Memo %zu werd verwijderd."
+
msgid "Memo ignore list is empty."
msgstr "Memo-negeerlijst is leeg."
@@ -5039,9 +5040,6 @@ msgstr ""
"anderen hun certificaatlijst aan te passen.\n"
" \n"
-msgid "Modify the Services ignore list"
-msgstr "Wijzig de services negeerlijst"
-
#, c-format
msgid "Modify the list of %s users"
msgstr "Wijzig de lijst van %s's"
@@ -5055,6 +5053,9 @@ msgstr "Wijzig de lijst van gebruikers met privileges"
msgid "Modify the nickname client certificate list"
msgstr "Wijzig de certificaatlijst"
+msgid "Modify the services ignore list"
+msgstr "Wijzig de services negeerlijst"
+
msgid "Modify the session-limit exception list"
msgstr "Wijzig de uitzonderingenlijst voor sessielimieten"
@@ -5105,6 +5106,9 @@ msgstr "Netwerkstatistieken voor %s:"
msgid "Never"
msgstr "Nooit"
+msgid "Never-op"
+msgstr "Nooit-op"
+
msgid "Nick"
msgstr "Nick"
@@ -5153,8 +5157,8 @@ msgid "Nick %s isn't registered."
msgstr "Nick %s is niet geregistreerd."
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Nick %s werd verkort naar %d tekens."
+msgid "Nick %s was truncated to %zu characters."
+msgstr "Nick %s werd verkort naar %zu karakters."
#, c-format
msgid "Nick %s will expire."
@@ -5197,8 +5201,8 @@ msgid "Nick %s is now suspended."
msgstr "Nick %s is nu geschorst."
#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr "Nick te lang, maximum lengte is %u karakters."
+msgid "Nick too long, max length is %zu characters."
+msgstr "Nick te lang, maximum lengte is %zu karakters."
#, c-format
msgid "Nickname %s has been dropped."
@@ -5391,14 +5395,6 @@ msgid "Oper type %s has not been configured."
msgstr "Opertype %s werd niet ingesteld."
#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "Opervlaggen %s zijn toegevoegd voor %s."
-
-#, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "Opervlaggen %s zijn verwijderd van %s."
-
-#, c-format
msgid "Opertype %s has no allowed commands."
msgstr "Opertype %s heeft geen toegestane commando's."
@@ -5429,17 +5425,9 @@ msgid "Password accepted."
msgstr "Wachtwoord aanvaard."
#, c-format
-msgid "Password for %s changed to %s."
-msgstr "Wachtwoord voor %s gewijzigd naar %s."
-
-#, c-format
msgid "Password for %s changed."
msgstr "Wachtwoord voor %s gewijzigd."
-#, c-format
-msgid "Password for %s is %s."
-msgstr "Wachtwoord voor %s is %s."
-
msgid "Password incorrect."
msgstr "Fout wachtwoord."
@@ -5465,14 +5453,13 @@ msgid "Please contact an Operator to get a vHost assigned to this nick."
msgstr "Gelieve een Operator te contacteren om een vHost aan je nick toegewezen te krijgen."
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
"Gelieve opnieuw te proberen met een moeilijker wachtwoord. Wachtwoorden\n"
-"moeten tenminste 5 karakters lang zijn, iets dat niet makkelijk geraden kan\n"
-"worden (zoals bijvoorbeeld je echte naam of nick), en kan geen spaties of tab-\n"
-"karakters bevatten."
+"mogen niet iets zijn dat makkelijk geraden kan worden (zoals bijvoorbeeld je\n"
+"echte naam of nick), en kan geen spaties of tab-karakters bevatten.\n"
msgid "Please use a valid server name when juping."
msgstr "Gelieve een geldige servernaam te gebruiken bij het blokkeren."
@@ -5481,24 +5468,24 @@ msgid "Please use the symbol of # when attempting to register."
msgstr "Gelieve het #-symbool te gebruiken bij het registreren."
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Gelieve %d seconden te wachten en opnieuw te proberen."
+msgid "Please wait %lu seconds and retry."
+msgstr "Gelieve %lu seconden te wachten en opnieuw te proberen."
#, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Gelieve %d seconden te wachten alvorens een nieuwe vHost aan te vragen."
+msgid "Please wait %lu seconds before requesting a new vHost."
+msgstr "Gelieve %lu seconden te wachten alvorens een nieuwe vHost aan te vragen."
#, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Gelieve %d seconden te wachten alvorens het %s commando opnieuw te gebruiken."
+msgid "Please wait %lu seconds before using the %s command again."
+msgstr "Gelieve %lu seconden te wachten alvorens het %s commando opnieuw te gebruiken."
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Gelieve %d seconden te wachten alvorens het GROUP commando opnieuw te gebruiken."
+msgid "Please wait %lu seconds before using the GROUP command again."
+msgstr "Gelieve %lu seconden te wachten alvorens het GROUP commando opnieuw te gebruiken."
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "Gelieve %d seconden te wachten alvorens het REGISTER commando opnieuw te gebruiken."
+msgid "Please wait %lu seconds before using the REGISTER command again."
+msgstr "Gelieve %lu seconden te wachten alvorens het REGISTER commando opnieuw te gebruiken."
#, c-format
msgid "Pooled %s."
@@ -5528,7 +5515,7 @@ msgstr "Voorkom dat de nick in het LIST commando verschijnt"
msgid "Prevent the nickname from expiring"
msgstr "Voorkom dat de nick verloopt"
-msgid "Prevents users being kicked by Services"
+msgid "Prevents users being kicked by services"
msgstr "Voorkomt dat gebruikers gekickt worden door services"
msgid "Private"
@@ -5686,16 +5673,16 @@ msgid "Registered"
msgstr "Geregistreerd"
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Geregistreerde kanalen: %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Geregistreerde kanalen: %zu vermeldingen, %zu emmers, langste ketting is %zu"
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Geregistreerde nickgroepen: %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Geregistreerde nickgroepen: %zu vermeldingen, %zu emmers, langste ketting is %zu"
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Geregistreerde nicks: %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Geregistreerde nicks: %zu vermeldingen, %zu emmers, langste ketting is %zu"
#, c-format
msgid "Registered only enforced on %s."
@@ -5744,7 +5731,7 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
"Registreert je nick in de %s database. Wanneer je nick\n"
@@ -5763,7 +5750,7 @@ msgstr ""
"nick als een wachtwoord gebruiken is een veel slechter idee ;)\n"
"en in feite, %s staat het niet toe. Bovendien zijn korte wachtwoorden\n"
"kwetsbaar voor zoekacties, dus kies je best een wachtwoord\n"
-"dat minstens 5 karakters lang is. Als laatste, de spatie kan niet\n"
+"dat minstens %u karakters lang is. Als laatste, de spatie kan niet\n"
"gebruikt worden in wachtwoorden."
msgid "Registration is currently disabled."
@@ -5886,9 +5873,6 @@ msgstr "Onthoud modes wanneer het kanaal niet in gebruik is"
msgid "Retain topic when channel is not in use"
msgstr "Onthoud het topic wanneer het kanaal niet in gebruik is"
-msgid "Retrieve the password for a nickname"
-msgstr "Vraag het wachtwoord van een nick op"
-
msgid "Retrieves the vhost requests"
msgstr "Vraag de vHost-aanvraaglijst op"
@@ -5905,18 +5889,6 @@ msgid "Returns the owner status of the given nickname"
msgstr "Geeft de eigenaarsstatus van de gegeven nick weer"
msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Geeft het wachtwoord van de opgegeven nick weer. Merk op\n"
-"dat wanneer je dit commando gebruikt er een bericht met de\n"
-"persoon die het commando heeft uitgevoerd en de nick waarop\n"
-"het is gebruikt zal worden gelogd en verstuurd zal worden\n"
-"als WALLOPS/GLOBOPS."
-
-msgid ""
"Returns whether the user using the given nickname is\n"
"recognized as the owner of the nickname. The response has\n"
"this format:\n"
@@ -5976,7 +5948,7 @@ msgstr "SSLONLY afgedwongen op %s."
msgid "SSLONLY enforced by "
msgstr "SSLONLY afgedwongen door "
-msgid "Save databases and restart Services"
+msgid "Save databases and restart services"
msgstr "Sla de databases op en herstart services"
msgid "Searches logs for a matching pattern"
@@ -6272,8 +6244,8 @@ msgid "Session limiting is disabled."
msgstr "Sessielimitering is uitgeschakeld."
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Sessies: %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Sessies: %zu vermeldingen, %zu emmers, langste ketting is %zu"
msgid "Set SET-options on another nickname"
msgstr "Stel SET-opties in op een andere nick"
@@ -6281,7 +6253,7 @@ msgstr "Stel SET-opties in op een andere nick"
msgid "Set channel options and information"
msgstr "Stel kanaalopties en informatie in"
-msgid "Set how Services make bans on the channel"
+msgid "Set how services make bans on the channel"
msgstr "Stelt in hoe services bans op het kanaal maken"
msgid "Set options related to memos"
@@ -6296,13 +6268,13 @@ msgstr "Stel het kanaal als permanent in"
msgid "Set the channel description"
msgstr "Stelt de kanaalbeschrijving in"
-msgid "Set the display of your group in Services"
+msgid "Set the display of your group in services"
msgstr "Stel de weergave van je groep in services in"
msgid "Set the founder of a channel"
msgstr "Stelt de stichter van een kanaal in"
-msgid "Set the language Services will use when messaging you"
+msgid "Set the language services will use when messaging you"
msgstr "Selecteer de taal die services zal gebruiken voor het versturen van berichten naar jou"
msgid "Set the nickname password"
@@ -6317,7 +6289,7 @@ msgstr "Stel de vHost voor alle nicks in een groep in"
msgid "Set the vhost of another user"
msgstr "Stel de vHost van een andere gebruiker in"
-msgid "Set various global Services options"
+msgid "Set various global services options"
msgstr "Stel verschillende globale services opties in"
msgid "Set your nickname password"
@@ -6561,7 +6533,7 @@ msgstr ""
"voor een gebruiker aan te passen tegelijk met de host."
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -6612,6 +6584,9 @@ msgstr ""
"Stelt in of het gegeven kanaal zal verlopen. Door deze optie\n"
"AAN te zetten kun je verhinderen dat het kanaal verloopt."
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr "Stelt in of de gegeven nick kan toegevoegd worden aan een kanaal toegangslijst."
+
#, c-format
msgid ""
"Sets whether the given nickname will be given its status modes\n"
@@ -6632,6 +6607,9 @@ msgstr ""
"Stelt in of de gegeven nick zal verlopen of niet.\n"
"Dit aan zetten voorkomt dat de nick zal verlopen."
+msgid "Sets whether you can be added to a channel access list."
+msgstr "Stelt in of je toegevoegd kan worden aan een kanaal toegangslijst."
+
#, c-format
msgid ""
"Sets whether you will be given your channel status modes automatically.\n"
@@ -6663,12 +6641,12 @@ msgstr "Instelling voor super administrator moet ON of OFF zijn."
msgid "Should services automatically give status to users"
msgstr "Moet services automatisch status modes geven aan gebruikers"
-msgid "Show status of Services and network"
+msgid "Show status of services and network"
msgstr "Geef de status van services en het netwerk weer"
#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr "%d/%d overeenkomsten getoond voor %s."
+msgid "Showed %zu/%zu matches for %s."
+msgstr "%zu/%zu overeenkomsten getoond voor %s."
msgid "Sign kicks that are done with the KICK command"
msgstr "Onderteken kicks die worden uitgevoerd met het KICK commando"
@@ -7040,13 +7018,13 @@ msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
+"users will not be allowed to modify any services data,\n"
"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
@@ -7130,8 +7108,8 @@ msgstr ""
"niveau 5 of hoger op het kanaal."
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7151,7 +7129,7 @@ msgstr ""
msgid "Tells you about the last time a user was seen"
msgstr "Vertelt je wanneer iemand het laatst gezien is"
-msgid "Terminate Services WITHOUT saving"
+msgid "Terminate services WITHOUT saving"
msgstr "Sluit services af ZONDER de databases op te slaan"
msgid "Terminate services with save"
@@ -7585,8 +7563,8 @@ msgstr ""
"opnieuw om services' blokkade op jouw nick op te heffen."
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "Er zijn %d memo's op kanaal %s."
+msgid "There are %zu memos on channel %s."
+msgstr "Er zijn %zu memo's op kanaal %s."
msgid ""
"There are no bots available at this time.\n"
@@ -7610,16 +7588,16 @@ msgid "There currently are no logging configurations for %s."
msgstr "Er zijn momenteel geen log instellingen voor %s."
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "Er is %d memo op kanaal %s."
+msgid "There is %zu memo on channel %s."
+msgstr "Er is %zu memo op kanaal %s."
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
+"Type %s%s READ %s %zu to read it."
msgstr ""
"Er is een nieuwe memo op kanaal %s.\n"
-"Typ %s%s READ %s %d om het te lezen."
+"Typ %s%s READ %s %zu om het te lezen."
#, c-format
msgid "There is no bot assigned to %s anymore."
@@ -7834,7 +7812,7 @@ msgid "This command retrieves the vhost requests."
msgstr "Dit commando toont de aangevraagde vHosts."
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -8309,12 +8287,12 @@ msgid "Users"
msgstr "Gebruikers"
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Gebruikers (nick): %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Gebruikers (nick): %lu vermeldingen, %lu emmers, langste ketting is %zu"
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Gebruikers (uid): %lu vermeldingen, %lu emmers, langste ketting is %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Gebruikers (uid): %lu vermeldingen, %lu emmers, langste ketting is %zu"
msgid "Users list:"
msgstr "Gebruikerslijst:"
@@ -8414,7 +8392,7 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
"Zonder een parameter keert dit command het effect van het\n"
@@ -8429,8 +8407,8 @@ msgstr ""
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -8494,9 +8472,6 @@ msgstr "Je gebruikt geen certificaat."
msgid "You are now a super admin."
msgstr "Je bent nu een super administrator."
-msgid "You are now an IRC Operator."
-msgstr "Je bent nu een IRC Operator."
-
msgid "You are now identified for your nick. Change your password now."
msgstr "Je bent nu geïdentificeerd voor je nick. Wijzig nu je wachtwoord."
@@ -8508,7 +8483,7 @@ msgstr "Je zit nu in de groep van %s."
msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr "Je hebt je maximum aantal memo's overschreden (%d). Je kan geen nieuwe memo's ontvangen totdat je enkele van je huidige memo's verwijdert."
-msgid "You can not NOOP Services."
+msgid "You can not NOOP services."
msgstr "Je kan geen NOOP doen op services."
msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
@@ -8517,7 +8492,7 @@ msgstr "Je kan de stichter privilege niet uitschakelen, want het zou onmogelijk
msgid "You can not jupe an already juped server."
msgstr "Je kan geen reeds geblokkeerde server blokkeren."
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
+msgid "You can not jupe your services' pseudoserver or your uplink server."
msgstr "Je kan services' pseudoserver of je uplink server niet blokkeren."
#, c-format
@@ -8564,20 +8539,20 @@ msgid "You cannot use this command."
msgstr "Je kan dit commando niet gebruiken."
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Je hebt momenteel %d memo's, waarvan er %d ongelezen zijn."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr "Je hebt momenteel %zu memo's, waarvan er %zu ongelezen zijn."
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Je hebt momenteel %d memo's, waarvan er 1 ongelezen is."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr "Je hebt momenteel %zu memo's, waarvan er 1 ongelezen is."
#, c-format
-msgid "You currently have %d memos."
-msgstr "Je hebt momenteel %d memo's."
+msgid "You currently have %zu memos."
+msgstr "Je hebt momenteel %zu memo's."
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Je hebt momenteel %d memo's; allemaal zijn ze ongelezen."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr "Je hebt momenteel %zu memo's; allemaal zijn ze ongelezen."
msgid "You currently have 1 memo, and it has not yet been read."
msgstr "Je hebt momenteel 1 memo, en deze is nog niet gelezen."
@@ -8610,10 +8585,10 @@ msgstr "Je hebt 1 nieuwe memo."
#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
+"Type %s%s READ %zu to read it."
msgstr ""
"Je hebt een nieuwe memo van %s.\n"
-"Typ %s%s READ %d om het te lezen."
+"Typ %s%s READ %zu om het te lezen."
#, c-format
msgid "You have been invited to %s by %s."
@@ -8674,9 +8649,6 @@ msgstr "Je mag het wachtwoord van andere Services Operators niet wijzigen."
msgid "You may not drop other Services Operators' nicknames."
msgstr "Je mag de nickregistraties van andere Services Operators niet verwijderen."
-msgid "You may not get the password of other Services Operators."
-msgstr "Je mag het wachtwoord van andere Services Operators niet opvragen."
-
msgid "You may not suspend other Services Operators' nicknames."
msgstr "Je kan de nicks van andere Services Operators niet schorsen."
@@ -8717,8 +8689,8 @@ msgid "You must enter the channel name twice as a confirmation that you wish to
msgstr "Je moet de kanaalnaam twee keer opgeven als bevestiging dat je de registratie van %s wenst ongedaan te maken."
#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr "Je moet deze nick tenminste %d seconden gebruiken om te registreren."
+msgid "You must have been using this nick for at least %lu seconds to register."
+msgstr "Je moet deze nick tenminste %lu seconden gebruiken om te registreren."
#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
@@ -8856,12 +8828,12 @@ msgid "Your passcode has been re-sent to %s."
msgstr "Je bevestingscode is opnieuw gestuurd naar %s."
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Je wachtwoord is %s - onthoudt dit voor later gebruik."
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr "Je wachtwoord is te lang. Het moet korter zijn dan %u karakters."
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr "Je wachtwoord is te lang. Het mag niet langer zijn dan %u karakters."
+msgid "Your password is too short. It must be longer than %u characters."
+msgstr "Je wachtwoord is te kort. Het moet langer zijn dan %u karakters."
msgid "Your password reset request has expired."
msgstr "Je wachtwoord-reset aanvraag is verlopen."
diff --git a/language/anope.pl_PL.po b/language/anope.pl_PL.po
index de50d7aa5..c08884887 100644
--- a/language/anope.pl_PL.po
+++ b/language/anope.pl_PL.po
@@ -7,17 +7,16 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-03 18:52+0100\n"
-"PO-Revision-Date: 2022-01-03 19:01+0100\n"
-"Last-Translator: Adam <adam@anope.org>\n"
+"POT-Creation-Date: 2024-02-22 16:34+0000\n"
+"PO-Revision-Date: 2024-02-22 16:42+0000\n"
+"Last-Translator: k4be <k4be@pirc.pl>\n"
"Language-Team: Polish\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n"
-"%100>=20) ? 1 : 2);\n"
-"X-Generator: Poedit 2.2.4\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Poedit 3.4\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
@@ -218,6 +217,10 @@ msgid "%s disabled on channel %s."
msgstr "%s wyłączono na kanale %s."
#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr "%s nie życzy sobie bycia dodawanym do list dostępowych na kanałach."
+
+#, c-format
msgid "%s has been invited to %s."
msgstr "%s został zaproszony na %s."
@@ -321,20 +324,15 @@ msgstr "%s jest założycielem %s."
#, c-format
msgid "%s matches access entry %s (from entry %s), which has privilege %s."
-msgstr ""
-"%s pasuje do wpisu %s (na podstawie %s) na liście dostępu, posiadającego "
-"uprawnienia %s."
+msgstr "%s pasuje do wpisu %s (na podstawie %s) na liście dostępu, posiadającego uprawnienia %s."
#, c-format
msgid "%s matches access entry %s, which has privilege %s."
msgstr "%s pasuje do wpisu %s na liście dostępu, posiadającego uprawnienia %s."
#, c-format
-msgid ""
-"%s matches an except on %s and cannot be banned until the except has been removed."
-msgstr ""
-"%s pasuje do wyjątku na %s i nie może być zbanowany, dopóki ten wyjątek nie "
-"zostanie usunięty."
+msgid "%s matches an except on %s and cannot be banned until the except has been removed."
+msgstr "%s pasuje do wyjątku na %s i nie może być zbanowany, dopóki ten wyjątek nie zostanie usunięty."
#, c-format
msgid "%s matches auto kick entry %s on %s (%s)."
@@ -369,11 +367,8 @@ msgid "%s not found on ignore list."
msgstr "%s nie znaleziono na liście ignorowanych."
#, c-format
-msgid ""
-"%s not found on session list, but has a limit of %d because it matches entry: %s."
-msgstr ""
-"%s nie został znaleziony na liście sesji, ale jego limit to %d z uwagi na to, że "
-"pasuje do wpisu: %s."
+msgid "%s not found on session list, but has a limit of %d because it matches entry: %s."
+msgstr "%s nie został znaleziony na liście sesji, ale jego limit to %d z uwagi na to, że pasuje do wpisu: %s."
#, c-format
msgid "%s not found on session-limit exception list."
@@ -538,11 +533,11 @@ msgstr "kanał nick powód"
msgid "channel what"
msgstr "kanał co"
-msgid "channel ADD mask"
-msgstr "kanał ADD maska"
+msgid "channel ADD mask level [description]"
+msgstr "kanał ADD maska poziom [opis]"
-msgid "channel ADD mask level"
-msgstr "kanał ADD maska poziom"
+msgid "channel ADD mask [description]"
+msgstr "kanał ADD maska [opis]"
msgid "channel ADD message"
msgstr "kanał ADD wiadomość"
@@ -628,8 +623,8 @@ msgstr "kanał [+czas] [powód]"
msgid "channel [+expiry] {nick | mask} [reason]"
msgstr "kanał [+czas] {nick | maska} [powód]"
-msgid "channel [MODIFY] mask changes"
-msgstr "kanał [MODIFY] maska zmiany"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr "kanał [MODIFY] maska zmiany [opis]"
msgid "channel [SET] [topic]"
msgstr "kanał [SET] [temat]"
@@ -691,9 +686,6 @@ msgstr "nick kanał"
msgid "nick channel [reason]"
msgstr "nick kanał [powód]"
-msgid "nick flags"
-msgstr "nick flagi"
-
msgid "nick hostmask"
msgstr "nick maska-hosta"
@@ -822,7 +814,7 @@ msgstr ""
msgid ""
" \n"
-"SQLINE ADD adds the given (nick's) mask to the SQLINE\n"
+"SQLINE ADD adds the given (nick/channel) mask to the SQLINE\n"
"list for the given reason (which must be given).\n"
"expiry is specified as an integer followed by one of d\n"
"(days), h (hours), or m (minutes). Combinations (such as\n"
@@ -835,28 +827,29 @@ msgid ""
"STATS AKILL command."
msgstr ""
" \n"
-"SQLINE ADD adds the given (nick's) mask to the SQLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SQLINE which does not expire, use +0.\n"
-"If the mask to be added starts with a +, an expiry time\n"
-"must be given, even if it is the same as the default. The\n"
-"current SQLINE default expiry time can be found with the\n"
-"STATS AKILL command."
+"SQLINE ADD dodaje podaną maskę nicka/kanału do listy\n"
+"SQLINE, z podanym powodem (którego wpisanie jest wymagane).\n"
+"wygasa - jest to czas wprowadzany jako liczba całkowita,\n"
+"po której należy określić jednostkę, jedną z następujących: d\n"
+"(dni), h (godziny), or m (minuty). Kombinacje, typu \n"
+"1h30m, nie są dozwolone. Jeśli jednostka nie zostanie wpisana,\n"
+"domyślnie użyty zostaje dzień (więc samo +30 oznacza 30 dni).\n"
+"Aby dodać SQLINE, który nie wygaśnie, należy użyć +0.\n"
+"Jeśli dodawana maska zaczyna się od znaku +, czas wygaśnięcia\n"
+"musi zostać podany, nawet, jeśli ma być on taki sam, jak wartość\n"
+"domyślna. Aktualną domyślną wartość czasu wygasania SQLINE\n"
+"można sprawdzić za pomocą komendy STATS AKILL"
#, c-format
msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
" \n"
"Konta nieużywane przez dłuższy czas są automatycznie\n"
-"usuwane po %d dniach od ostatniej identyfikacji.\n"
+"usuwane po %lu dniach od ostatniej identyfikacji.\n"
"Wszelkie ustawienia oraz uprawnienia zostają usunięte."
msgid ""
@@ -952,12 +945,12 @@ msgstr ""
#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
" \n"
-"Uwaga! Kanał który nie był używany przez %d dni\n"
+"Uwaga! Kanał który nie był używany przez %lu dni\n"
"(np. nie odwiedził go żaden użytkownik umieszczony\n"
"na liście dostępu kanału w tym czasie) zostanie\n"
"automatycznie odrejestrowany."
@@ -1276,11 +1269,11 @@ msgid "%-8s %s"
msgstr "%-8s %s"
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "%2lu %-16s liter: %s, słów: %s, linii: %s, emotikon: %s, akcji: %s"
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr "%2d %-16s liter: %s, słów: %s, linii: %s, emotikon: %s, akcji: %s"
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr "%b %d %H:%M:%S %Y %Z"
+msgid "%b %d %Y %H:%M:%S %Z"
+msgstr "%d %b %Y %H:%M:%S %Z"
#, c-format
msgid "%c is an unknown status mode."
@@ -1307,13 +1300,8 @@ msgid "%d modules loaded."
msgstr "Załadowanych modułów: %d."
#, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nicków w grupie."
-
-#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
-msgstr ""
-"%lu nicków jest zapisanych w bazie danych, zajmując przy tym %.2Lf kB pamięci."
+msgstr "%lu nicków jest zapisanych w bazie danych, zajmując przy tym %.2Lf kB pamięci."
#, c-format
msgid "%s %s list is empty."
@@ -1408,6 +1396,14 @@ msgid "%s bad words list is empty."
msgstr "Lista zakazanych słów dla kanału %s jest pusta."
#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr "Od teraz %s nie można już dodać do kanałowych list dostępu."
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr "%s można teraz dodawać do kanałowych list dostępu."
+
+#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
msgstr "%s nie może być zastępcą na kanale %s, ponieważ jest jego właścicielem."
@@ -1420,20 +1416,20 @@ msgid "%s coverage is too wide; Please use a more specific mask."
msgstr "Zakres %s jest zbyt szeroki; proszę użyć dokładniejszej maski."
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s ma aktualnie %d wiadomości, z czego %d jest nieprzeczytanych."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr "%s ma aktualnie %zu wiadomości, z czego %zu jest nieprzeczytanych."
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s ma aktualnie %d wiadomości, w tym jedną nieprzeczytaną."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr "%s ma aktualnie %zu wiadomości, w tym jedną nieprzeczytaną."
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s ma aktualnie %d wiadomości."
+msgid "%s currently has %zu memos."
+msgstr "%s ma aktualnie %zu wiadomości."
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s ma aktualnie %d nieprzeczytanych wiadomości."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr "%s ma aktualnie %zu nieprzeczytanych wiadomości."
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
@@ -1602,15 +1598,12 @@ msgid "%s will now notify you of memos when they are sent to you."
msgstr "%s będzie powiadamiał Cię o nowych wiadomościach w momencie ich nadejścia."
#, c-format
-msgid ""
-"%s will now notify you of memos when you log on and when they are sent to you."
-msgstr ""
-"%s powiadomi Cię o wiadomościach podczas logowania i w momencie ich nadejścia."
+msgid "%s will now notify you of memos when you log on and when they are sent to you."
+msgstr "%s powiadomi Cię o wiadomościach podczas logowania i w momencie ich nadejścia."
#, c-format
msgid "%s will now notify you of memos when you log on or unset /AWAY."
-msgstr ""
-"%s powiadomi Cię o wiadomościach podczas logowania oraz po wyłączeniu /away."
+msgstr "%s powiadomi Cię o wiadomościach podczas logowania oraz po wyłączeniu /away."
#, c-format
msgid "%s!%s@%s (%s) added to the bot list."
@@ -1641,6 +1634,10 @@ msgid "%s's memo limit is %d."
msgstr "%s ma limit wiadomości %d."
#, c-format
+msgid "%zu nickname(s) in the group."
+msgstr "%zu nicków w grupie."
+
+#, c-format
msgid "(%s ago)"
msgstr "(%s temu)"
@@ -1708,9 +1705,7 @@ msgid "<unknown>"
msgstr "<nieznany>"
#, c-format
-msgid ""
-"A confirmation e-mail has been sent to %s. Follow the instructions in it to "
-"change your e-mail address."
+msgid "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
msgstr ""
"Wiadomość potwierdzająca została wysłana na e-mail %s.\n"
"Postępuj według instrukcji w niej, aby dokończyć procedurę rejestracji."
@@ -1718,20 +1713,16 @@ msgstr ""
msgid "A massmemo has been sent to all registered users."
msgstr "Wiadomość została wysłana do wszystkich zarejestrowanych użytkowników."
-msgid ""
-"A memo informing the user will also be sent, which includes the reason for the "
-"rejection if supplied."
-msgstr ""
-"Wysłana zostanie także wiadomość informująca użytkownika. Jeśli podano przyczynę "
-"odrzucenia, informacja ta zostanie dołączona."
+msgid "A memo informing the user will also be sent, which includes the reason for the rejection if supplied."
+msgstr "Wysłana zostanie także wiadomość informująca użytkownika. Jeśli podano przyczynę odrzucenia, informacja ta zostanie dołączona."
msgid "A memo informing the user will also be sent."
msgstr "Wysłana zostanie także wiadomość informująca użytkownika."
#, c-format
msgid ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
+"A notification memo has been sent to %s informing them you have\n"
+"read their memo."
msgstr "Powiadomienie o przeczytaniu wiadomości zostało wysłane do %s."
msgid "A vHost ident must be in the format of a valid ident."
@@ -1829,17 +1820,14 @@ msgid "Access list for %s:"
msgstr "Lista dostępu dla %s:"
#, c-format
-msgid ""
-"Access to this command requires the permission %s to be present in your opertype."
-msgstr ""
-"Dostęp do tego polecenia wymaga ustawienia uprawnienia %s w twoim bloku operatora."
+msgid "Access to this command requires the permission %s to be present in your opertype."
+msgstr "Dostęp do tego polecenia wymaga ustawienia uprawnienia %s w twoim bloku operatora."
msgid "Account"
msgstr "Konto"
#, c-format
-msgid ""
-"Account %s has already reached the maximum number of simultaneous logins (%u)."
+msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
msgstr "Konto %s już osiągnęło maksymalną ilość równoczesnych logowań (%u)."
msgid "Activate security features"
@@ -1954,12 +1942,8 @@ msgstr "Wszystkie wiadomości kanału %s zostały usunięte."
msgid "All modes cleared on %s."
msgstr "Skasowano wszystkie tryby na %s."
-msgid ""
-"All new accounts must be validated by an administrator. Please wait for your "
-"registration to be confirmed."
-msgstr ""
-"Wszystkie nowe konta muszą zostać zweryfikowane przez administratora. Poczekaj "
-"proszę na potwierdzenie Twojej rejestracji."
+msgid "All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."
+msgstr "Wszystkie nowe konta muszą zostać zweryfikowane przez administratora. Poczekaj proszę na potwierdzenie Twojej rejestracji."
msgid "All of your memos have been deleted."
msgstr "Wszystkie Twoje wiadomości zostały usunięte."
@@ -1990,36 +1974,31 @@ msgstr "Wszystkie vhosty w grupie %s zostały zmienione na %s."
msgid "All vhosts in the group %s have been set to %s@%s."
msgstr "Wszystkie vhosty w grupie %s zostały zmienione na %s@%s."
-msgid "Allowed to (de)halfop him/herself"
+msgid "Allowed to (de)halfop themself"
msgstr "Uprawniony do ustawiania/kasowania własnego statusu półoperatora (halfop)"
msgid "Allowed to (de)halfop users"
-msgstr ""
-"Uprawniony do ustawiania/kasowania statusu półoperatora (halfop) użytkowników"
+msgstr "Uprawniony do ustawiania/kasowania statusu półoperatora (halfop) użytkowników"
-msgid "Allowed to (de)op him/herself"
+msgid "Allowed to (de)op themself"
msgstr "Uprawniony do ustawiania/kasowania własnego statusu operatora (op)"
msgid "Allowed to (de)op users"
msgstr "Uprawniony do ustawiania/kasowania statusu operatora (op) użytkowników"
-msgid "Allowed to (de)owner him/herself"
+msgid "Allowed to (de)owner themself"
msgstr "Uprawniony do ustawiania/kasowania własnego statusu właściciela (owner)"
msgid "Allowed to (de)owner users"
msgstr "Uprawniony do ustawiania/kasowania statusu właściciela (owner) użytkowników"
-msgid "Allowed to (de)protect him/herself"
-msgstr ""
-"Uprawniony do ustawiania/kasowania własnego statusu administratora/chronionego "
-"(protect)"
+msgid "Allowed to (de)protect themself"
+msgstr "Uprawniony do ustawiania/kasowania własnego statusu administratora/chronionego (protect)"
msgid "Allowed to (de)protect users"
-msgstr ""
-"Uprawniony do ustawiania/kasowania statusu administratora/chronionego (protect) "
-"użytkowników"
+msgstr "Uprawniony do ustawiania/kasowania statusu administratora/chronionego (protect) użytkowników"
-msgid "Allowed to (de)voice him/herself"
+msgid "Allowed to (de)voice themself"
msgstr "Uprawniony do ustawiania/kasowania własnego prawa głosu (voice)"
msgid "Allowed to (de)voice users"
@@ -2052,6 +2031,9 @@ msgstr "Uprawniony do czytania wiadomości MEMO dla kanału"
msgid "Allowed to set channel settings"
msgstr "Uprawniony do zmiany ustawień kanału"
+msgid "Allowed to unban themself"
+msgstr "Uprawniony do usuwania banów"
+
msgid "Allowed to unban users"
msgstr "Uprawniony do usuwania banów"
@@ -2143,23 +2125,13 @@ msgstr ""
"zostanie on wtedy skillowany."
msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Pozwala Services Operators na nadanie wskazanemu\n"
-"użytkownikowi uprawnień irc operatora z określonymi\n"
-"flagami. Flagi powinny być poprzedzone znakami \"+\" lub \"-\". \n"
-"Aby usunąć wszystkie flagi wystarczy podać \"-\"."
-
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
@@ -2179,7 +2151,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2218,7 +2190,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
"Pozwala Operatorom Serwisów manipulować listą SNLINE.\n"
@@ -2228,7 +2200,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
@@ -2236,7 +2208,7 @@ msgid ""
"channels too."
msgstr ""
"Pozwala Operatorom Serwisów na manipulowanie listą SQLINE.\n"
-"Jeżeli użytkownik, którego nick pasuje do maski SQLINE próbuje\n"
+"Jeżeli użytkownik, którego nick pasuje do maski SQLINE, próbuje\n"
"się połączyć, serwisy nie pozwolą na stworzenie tej sesji IRC.\n"
"Jeśli pierwszy znak maski to #, serwisy zabronią używania pasujących\n"
"kanałów. Jeśli maska jest wyrażeniem regularnym, wyrażenie to będzie\n"
@@ -2295,8 +2267,7 @@ msgid ""
"the given topic to the existing topic.\n"
" \n"
"LOCK and UNLOCK may be used to enable and disable topic lock. When\n"
-"topic lock is set, the channel topic will be unchangeable by users who do not "
-"have\n"
+"topic lock is set, the channel topic will be unchangeable by users who do not have\n"
"the TOPIC privilege."
msgstr ""
"Pozwala na manipulowanie tematem określonego kanału.\n"
@@ -2365,19 +2336,19 @@ msgstr ""
" MODIFY nickserv forcemail no"
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
"Pozwala wybrać sposób, w jaki serwisy będą pisać do\n"
-"Ciebie. Kiedy opcja MSG jest włączona, serwisy będą\n"
-"wysyłać wiadomości prywatne (query), w przeciwnym\n"
-"wypadku będą wysyłać powiadomienia (notice)."
+"podanego użytkownika. Kiedy opcja MSG jest włączona,\n"
+"serwisy będą wysyłać wiadomości prywatne (query),\n"
+"w przeciwnym wypadku będą to powiadomienia (notice)."
#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
"Pozwala wybrać sposób, w jaki serwisy będą pisać do\n"
@@ -2464,8 +2435,8 @@ msgid ""
"Alternative methods of modifying channel access lists are\n"
"available."
msgstr ""
-"Alternatywne sposoby na modyfikację kanałowych list dostępu\n"
-"są dostępne."
+"Dostępne są alternatywne sposoby na modyfikację kanałowych\n"
+"list dostępu."
msgid "Approve the requested vHost of a user"
msgstr "Akceptuje prośbę o vhost wskazanego użytkownika"
@@ -2661,15 +2632,15 @@ msgid "Bot bans will no longer automatically expire."
msgstr "Bany zakładane przez bota nie będą już się przedawniały."
#, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Host bota może się składać maksymalnie z %d znaków."
+msgid "Bot hosts may only be %zu characters long."
+msgstr "Host bota może się składać maksymalnie z %zu znaków."
msgid "Bot hosts may only contain valid host characters."
msgstr "Host bota może zawierać tylko prawidłowe znaki."
#, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Ident bota może się składać maksymalnie z %d znaków."
+msgid "Bot idents may only be %zu characters long."
+msgstr "Ident bota może się składać maksymalnie z %zu znaków."
msgid "Bot idents may only contain valid ident characters."
msgstr "Ident bota może zawierać tylko prawidłowe znaki."
@@ -2685,8 +2656,8 @@ msgid "Bot nick"
msgstr "Nick bota"
#, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Nick bota może się składać maksymalnie z %d znaków."
+msgid "Bot nicks may only be %zu characters long."
+msgstr "Nick bota może się składać maksymalnie z %zu znaków."
msgid "Bot nicks may only contain valid nick characters."
msgstr "Nick bota może zawierać tylko prawidłowe znaki."
@@ -2820,7 +2791,7 @@ msgid "Caps kicker"
msgstr "Kopanie za capsa"
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
@@ -2828,13 +2799,12 @@ msgstr ""
"Wymusza na serwisach natychmiastowe zakończenie pracy bez\n"
"zapisywania baz. To polecenie powinno być użyte jedynie,\n"
"gdy zachodzi podejrzenie uszkodzenia baz, które serwisy\n"
-"przechowują w pamięci. Do normalnego zakończenia pracy\n"
-"serwisów należy użyć polecenia SHUTDOWN."
+"przechowują w pamięci, pozwalając uniknąć ich zapisania."
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
"Wymusza ponowne załadowanie pliku konfiguracyjnego.\n"
@@ -2842,15 +2812,15 @@ msgstr ""
"(zmiana nicków serwisów, aktywacja limitów sesji itd.)."
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr "Wymusza zapisanie baz, a następnie restartuje serwisy."
-msgid "Causes Services to save all databases and then shut down."
+msgid "Causes services to save all databases and then shut down."
msgstr "Wymusza zapisanie baz danych, a następnie wyłącza serwisy."
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr "Wymusza natychmiastowy zapis baz danych na dysku."
@@ -2864,7 +2834,7 @@ msgstr "ChanServ jest wymagany, aby włączyć nieusuwalność w tej sieci."
msgid "Change channel modes"
msgstr "Zmienia flagi kanału"
-msgid "Change the communication method of Services"
+msgid "Change the communication method of services"
msgstr "Zmienia sposób komunikacji serwisów"
msgid "Change user modes"
@@ -2876,7 +2846,7 @@ msgstr "Zmieniono flagi użytkownika dla %s na %s."
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
"Zmienia nazwę reprezentującą grupę nicków w\n"
"serwisach na nową. Nazwa MUSI być jednym z nicków\n"
@@ -2884,7 +2854,7 @@ msgstr ""
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
"Zmienia nazwę reprezentującą Twoją grupę nicków w\n"
"serwisach na nową. Nazwa MUSI być jednym z nicków\n"
@@ -2898,7 +2868,7 @@ msgstr ""
"Nowy nick musi być zarejestrowany."
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
@@ -2909,7 +2879,7 @@ msgstr ""
"wybrany z poniższej listy obsługiwanych języków:"
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
@@ -3051,8 +3021,8 @@ msgid "Channels that %s has access on:"
msgstr "Kanały, na których %s jest na liście dostępu:"
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kanały: %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Kanały: %zu wpisów, %zu pakietów, najdłuższy łańcuch to %zu"
msgid "Chanstats"
msgstr "Statystyki kanałów"
@@ -3204,20 +3174,20 @@ msgid "Current module list:"
msgstr "Aktualna lista modułów:"
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Aktualna ilość wpisów AKILL: %d"
+msgid "Current number of AKILLs: %zu"
+msgstr "Aktualna ilość wpisów AKILL: %zu"
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Aktualna ilość wpisów SNLINE: %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr "Aktualna ilość wpisów SNLINE: %zu"
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Aktualna ilość wpisów SQLINE: %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr "Aktualna ilość wpisów SQLINE: %zu"
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Użytkowników : %d (%d operatorów)"
+msgid "Current users: %zu (%d ops)"
+msgstr "Użytkowników : %zu (%d operatorów)"
msgid "DEL oper"
msgstr "DEL oper"
@@ -3739,7 +3709,7 @@ msgid ""
"Enables or disables the peace option for a channel.\n"
"When peace is set, a user won't be able to kick,\n"
"ban or remove a channel status of a user that has\n"
-"a level superior or equal to his via %s commands."
+"a level superior or equal to theirs via %s commands."
msgstr ""
"Włącza lub wyłącza opcję PEACE dla kanału.\n"
"Włączenie tej opcji uniemożliwia wykopanie,\n"
@@ -3870,8 +3840,8 @@ msgid "End of entry message list."
msgstr "Koniec listy wiadomości powitalnych."
#, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Koniec listy zakazów - %d/%d wpisów wyświetlono."
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr "Koniec listy zakazów - %zu/%zu wpisów wyświetlono."
msgid "End of forbid list."
msgstr "Koniec listy zakazów."
@@ -3956,18 +3926,12 @@ msgid "Error reloading configuration file: %s"
msgstr "Błąd przeładowywania pliku konfiguracyjnego: %s"
#, c-format
-msgid ""
-"Error! The vHost ident is too long, please use an ident shorter than %d "
-"characters."
-msgstr ""
-"Błąd: podany wirtualny ident jest zbyt długi. Proszę użyć nazwy krótszej niż %d "
-"znaków."
+msgid "Error! The vHost ident is too long, please use an ident shorter than %zu characters."
+msgstr "Błąd: podany wirtualny ident jest zbyt długi. Proszę użyć nazwy krótszej niż %zu znaków."
#, c-format
-msgid ""
-"Error! The vHost is too long, please use a hostname shorter than %d characters."
-msgstr ""
-"Błąd: podany vHost jest zbyt długi. Proszę użyć nazwy krótszej niż %d znaków."
+msgid "Error! The vHost is too long, please use a hostname shorter than %zu characters."
+msgstr "Błąd: podany vHost jest zbyt długi. Proszę użyć nazwy krótszej niż %zu znaków."
msgid ""
"Examples:\n"
@@ -4068,7 +4032,7 @@ msgstr "Zakaz %s nie znaleziony."
msgid "Forbid usage of nicknames, channels, and emails"
msgstr "Zakaz użycia nicków, kanałów i adresów e-mail"
-msgid "Force the Services databases to be updated immediately"
+msgid "Force the services databases to be updated immediately"
msgstr "Wymusza natychmiastowy zapis baz na dysku"
msgid "Forcefully change a user's nickname"
@@ -4096,15 +4060,9 @@ msgstr "Właściciel"
msgid "Founder of %s changed to %s."
msgstr "Właścicielem kanału %s jest teraz %s."
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "Komenda GETPASS nie działa, bo hasła są szyfrowane."
-
msgid "Ghost with your nick has been killed."
msgstr "Nick został usunięty z sieci."
-msgid "Give Operflags to a certain user"
-msgstr "Daje flagi operatora wybranemu użytkownikowi"
-
#, c-format
msgid ""
"Gives %s status to the selected nick on a channel. If nick is\n"
@@ -4223,9 +4181,7 @@ msgstr "Niewłaściwy czas trwania %s, używam %d dni."
msgid "Invalid expiry time."
msgstr "Błędny czas przedawnienia."
-msgid ""
-"Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched "
-"against nicks or usernames."
+msgid "Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames."
msgstr "Nieprawidłowa maska. Tylko rzeczywiste maski są prawidłowe jako wyjątki."
#, c-format
@@ -4233,16 +4189,13 @@ msgid "Invalid limit %s, using %d."
msgstr "Błędny limit %s, stosuję %d."
msgid "Invalid passcode has been entered, please check the e-mail again, and retry."
-msgstr ""
-"Wpisano niewłaściwy kod. Proszę o ponowne sprawdzenie e-mail i ponowną próbę."
+msgstr "Wpisano niewłaściwy kod. Proszę o ponowne sprawdzenie e-mail i ponowną próbę."
msgid "Invalid passcode."
msgstr "Niewłaściwy kod."
#, c-format
-msgid ""
-"Invalid session limit. It must be a valid integer greater than or equal to zero "
-"and less than %d."
+msgid "Invalid session limit. It must be a valid integer greater than or equal to zero and less than %d."
msgstr "Nieprawidłowy limit sesji. Musi być liczbą nieujemną i mniejszą niż %d."
msgid "Invalid threshold value. It must be a valid integer greater than 1."
@@ -4307,8 +4260,8 @@ msgid "LIMIT enforced by "
msgstr "LIMIT wymuszony przez "
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr "LIMIT wymuszony na %s, wyrzucono %d użytkowników."
+msgid "LIMIT enforced on %s, %zu users removed."
+msgstr "LIMIT wymuszony na %s, wyrzucono %zu użytkowników."
msgid "LIST threshold"
msgstr "LIST wartość-progowa"
@@ -4648,8 +4601,7 @@ msgstr "Logowanie dla polecenia %s na %s metodą %s%s%s zostało usunięte."
#, c-format
msgid "Logging is now active for command %s on %s, using log method %s%s%s."
-msgstr ""
-"Logowanie jest teraz aktywne dla polecenia %s na %s, przy użyciu metody %s%s%s."
+msgstr "Logowanie jest teraz aktywne dla polecenia %s na %s, przy użyciu metody %s%s%s."
#, c-format
msgid "Login to %s"
@@ -4696,21 +4648,17 @@ msgstr "Ej, szukasz siebie, %s?"
#, c-format
msgid ""
-"Mainly controls mode locks and mode access (which is different from channel "
-"access)\n"
+"Mainly controls mode locks and mode access (which is different from channel access)\n"
"on a channel.\n"
" \n"
"The %s LOCK command allows you to add, delete, and view mode locks on a channel.\n"
-"If a mode is locked on or off, services will not allow that mode to be changed. "
-"The SET\n"
-"command will clear all existing mode locks and set the new one given, while ADD "
-"and DEL\n"
+"If a mode is locked on or off, services will not allow that mode to be changed. The SET\n"
+"command will clear all existing mode locks and set the new one given, while ADD and DEL\n"
"modify the existing mode lock.\n"
"Example:\n"
" MODE #channel LOCK ADD +bmnt *!*@*aol*\n"
" \n"
-"The %s SET command allows you to set modes through services. Wildcards * and ? "
-"may\n"
+"The %s SET command allows you to set modes through services. Wildcards * and ? may\n"
"be given as parameters for list and status modes.\n"
"Example:\n"
" MODE #channel SET +v *\n"
@@ -4720,26 +4668,20 @@ msgid ""
" Clears all extended bans that start with ~c:\n"
" \n"
"The %s CLEAR command is an easy way to clear modes on a channel. what may be\n"
-"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and "
-"voices. If what\n"
+"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If what\n"
"is not given then all basic modes are removed."
msgstr ""
-"Kontroluje przede wszystkim blokady trybów i uprawnienia do trybów (które różnią "
-"się od uprawnień\n"
+"Kontroluje przede wszystkim blokady trybów i uprawnienia do trybów (które różnią się od uprawnień\n"
"do kanałów).\n"
" \n"
-"Polecenie %s LOCK pozwala na dodawanie, usuwanie i podglądanie blokad trybów na "
-"kanale.\n"
-"Gdy flaga jest zablokowana jako włączona lub wyłączona, serwisy uniemożliwią jej "
-"zmianę.\n"
-"Polecenie SET usunie wszystkie aktualne blokady trybów, i ustawi tylko podane, "
-"natomiast\n"
+"Polecenie %s LOCK pozwala na dodawanie, usuwanie i podglądanie blokad trybów na kanale.\n"
+"Gdy flaga jest zablokowana jako włączona lub wyłączona, serwisy uniemożliwią jej zmianę.\n"
+"Polecenie SET usunie wszystkie aktualne blokady trybów, i ustawi tylko podane, natomiast\n"
"komendy ADD i DEL zmodyfikują istniejącą blokadę.\n"
"Przykład:\n"
" MODE #kanał LOCK ADD +bmnt *!*@*neostrada*\n"
" \n"
-"Komenda %s SET pozwala na ustawianie trybów za pomocą serwisów. Znaki * oraz ? "
-"mogą\n"
+"Komenda %s SET pozwala na ustawianie trybów za pomocą serwisów. Znaki * oraz ? mogą\n"
"być podawane jako parametry dla list i trybów użytkowników.\n"
"Przykład:\n"
" MODE #kanał SET +v *\n"
@@ -4748,10 +4690,8 @@ msgstr ""
" MODE #kanał SET -b ~c:*\n"
" Kasuje wszystkie bany rozszerzone, zaczynające się od ~c:\n"
" \n"
-"Komenda %s CLEAR jest łatwą metodą na usunięcie trybów kanałowych. Opcją co może "
-"być\n"
-"dowolna flaga. Do przykładów można zaliczyć bany, wyjątki banów, wyjątki "
-"zaproszeń, statusy opa, halfopa,\n"
+"Komenda %s CLEAR jest łatwą metodą na usunięcie trybów kanałowych. Opcją co może być\n"
+"dowolna flaga. Do przykładów można zaliczyć bany, wyjątki banów, wyjątki zaproszeń, statusy opa, halfopa,\n"
"Jeśli nie podano co, zostaną wyczyszczone wszystkie podstawowe tryby."
msgid "Maintain the AutoKick list"
@@ -4927,8 +4867,7 @@ msgid "Mask must be in the form user@host."
msgstr "Maska musi mieć postać user@host."
msgid "Masks and unregistered users may not be on access lists."
-msgstr ""
-"Maski ani niezarejestrowane nicki nie mogą znajdować się na listach dostępowych."
+msgstr "Maski ani niezarejestrowane nicki nie mogą znajdować się na listach dostępowych."
msgid "Matches and returns all users that registered using given email"
msgstr "Wyświetla użytkowników zarejestrowanych z podanym adresem e-mail"
@@ -4949,6 +4888,10 @@ msgstr "Wiadomość %d od %s (%s)."
msgid "Memo %d has been deleted."
msgstr "Wiadomość %d została usunięta."
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr "Wiadomość %zu została usunięta."
+
msgid "Memo ignore list is empty."
msgstr "Lista ignorowanych jest pusta."
@@ -5066,9 +5009,6 @@ msgstr ""
"zalogowany. Operatorzy serwisów mogą podać nick, aby modyfikować\n"
"listy certyfikatów innych użytkowników. \n"
-msgid "Modify the Services ignore list"
-msgstr "Zarządza listą ignorowanych przez serwisy"
-
#, c-format
msgid "Modify the list of %s users"
msgstr "Zarządza listą %s"
@@ -5082,6 +5022,9 @@ msgstr "Zarządza listą uprawnionych użytkowników"
msgid "Modify the nickname client certificate list"
msgstr "Modyfikuje listę certyfikatów klienta dla nicka"
+msgid "Modify the services ignore list"
+msgstr "Zarządza listą ignorowanych przez serwisy"
+
msgid "Modify the session-limit exception list"
msgstr "Zarządza listą wyjątków dla limitów sesji"
@@ -5132,6 +5075,9 @@ msgstr "Statystyki sieciowe dla %s:"
msgid "Never"
msgstr "Nigdy"
+msgid "Never-op"
+msgstr "Nigdy"
+
msgid "Nick"
msgstr "Nick"
@@ -5180,8 +5126,8 @@ msgid "Nick %s isn't registered."
msgstr "Nick %s nie jest zarejestrowany."
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Nick %s został skrócony do %d znaków."
+msgid "Nick %s was truncated to %zu characters."
+msgstr "Nick %s został skrócony do %zu znaków."
#, c-format
msgid "Nick %s will expire."
@@ -5224,8 +5170,8 @@ msgid "Nick %s is now suspended."
msgstr "Nick %s został zawieszony."
#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr "Zbyt długi nick. Maksymalna długość to %u znaków."
+msgid "Nick too long, max length is %zu characters."
+msgstr "Zbyt długi nick. Maksymalna długość to %zu znaków."
#, c-format
msgid "Nickname %s has been dropped."
@@ -5388,12 +5334,8 @@ msgid "Online from"
msgstr "Jest online z"
#, c-format
-msgid ""
-"Oper %s is configured in the configuration file(s) and can not be removed by this "
-"command."
-msgstr ""
-"Operator %s jest dodany w pliku konfiguracyjnym, więc nie można usunąć go tym "
-"poleceniem."
+msgid "Oper %s is configured in the configuration file(s) and can not be removed by this command."
+msgstr "Operator %s jest dodany w pliku konfiguracyjnym, więc nie można usunąć go tym poleceniem."
msgid "Oper Info"
msgstr "Informacje Oper"
@@ -5422,14 +5364,6 @@ msgid "Oper type %s has not been configured."
msgstr "Typ operatora %s nie jest skonfigurowany."
#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "Flagi operatora %s zostały przyznane dla %s."
-
-#, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "Flagi operatora %s zostały zabrane %s."
-
-#, c-format
msgid "Opertype %s has no allowed commands."
msgstr "Typ operatora %s nie posiada żadnych dozwolonych komend."
@@ -5460,17 +5394,9 @@ msgid "Password accepted."
msgstr "Hasło przyjęte."
#, c-format
-msgid "Password for %s changed to %s."
-msgstr "Hasło dla %s zmieniono na %s"
-
-#, c-format
msgid "Password for %s changed."
msgstr "Hasło dla %s zmienione."
-#, c-format
-msgid "Password for %s is %s."
-msgstr "Hasło dla %s to %s."
-
msgid "Password incorrect."
msgstr "Nieprawidłowe hasło."
@@ -5496,14 +5422,13 @@ msgid "Please contact an Operator to get a vHost assigned to this nick."
msgstr "Proszę o kontakt z operatorem, aby uzyskać vHosta dla tego nicka."
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab "
-"characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
-"Proszę spróbować ponownie, używając trudniejszego hasła. Hasło powinno\n"
-"składać się co najmniej z 5 znaków, nie powinno być łatwe do odgadnięcia\n"
-"(na przykład Twoje imię bądź nick), i nie może zawierać spacji albo znaków Tab."
+"Proszę spróbować ponownie, używając trudniejszego hasła. Hasło nie powinno\n"
+"być łatwe do odgadnięcia (na przykład Twoje imię bądź nick), i nie może zawierać\n"
+"spacji, ani znaków Tab.\n"
msgid "Please use a valid server name when juping."
msgstr "Proszę użyć prawidłowej nazwy serwera."
@@ -5512,24 +5437,24 @@ msgid "Please use the symbol of # when attempting to register."
msgstr "Proszę używać symbolu # przy próbie rejestracji."
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Proszę odczekać %d sekund(y) i ponowić próbę."
+msgid "Please wait %lu seconds and retry."
+msgstr "Proszę odczekać %lu sekund(y) i ponowić próbę."
#, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Odczekaj %d sekund(y) przed ponowną prośbą o vHosta."
+msgid "Please wait %lu seconds before requesting a new vHost."
+msgstr "Odczekaj %lu sekund(y) przed ponowną prośbą o vHosta."
#, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Odczekaj %d sekund(y) przed ponownym użyciem komendy %s."
+msgid "Please wait %lu seconds before using the %s command again."
+msgstr "Odczekaj %lu sekund(y) przed ponownym użyciem komendy %s."
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Odczekaj %d sekund przed ponownym użyciem komendy GROUP."
+msgid "Please wait %lu seconds before using the GROUP command again."
+msgstr "Odczekaj %lu sekund przed ponownym użyciem komendy GROUP."
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "Odczekaj %d sekund przed ponownym użyciem komendy REGISTER."
+msgid "Please wait %lu seconds before using the REGISTER command again."
+msgstr "Odczekaj %lu sekund przed ponownym użyciem komendy REGISTER."
#, c-format
msgid "Pooled %s."
@@ -5559,7 +5484,7 @@ msgstr "Zapobiega wyświetlaniu nicka po wydaniu polecenia LIST"
msgid "Prevent the nickname from expiring"
msgstr "Zapobiega wygaśnięciu nicka"
-msgid "Prevents users being kicked by Services"
+msgid "Prevents users being kicked by services"
msgstr "Zabrania kopania użytkowników przez serwisy"
msgid "Private"
@@ -5717,17 +5642,16 @@ msgid "Registered"
msgstr "Zarejestrowano"
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Zarejestrowane kanały: %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Zarejestrowane kanały: %zu wpisów, %zu pakietów, najdłuższy łańcuch to %zu"
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-"Zarejestrowane grupy nicków: %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Zarejestrowane grupy nicków: %zu wpisów, %zu pakietów, najdłuższy łańcuch to %zu"
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Zarejestrowane nicki: %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Zarejestrowane nicki: %zu wpisów, %zu pakietów, najdłuższy łańcuch to %zu"
#, c-format
msgid "Registered only enforced on %s."
@@ -5745,7 +5669,7 @@ msgid ""
"\"founder\" of the channel. The channel founder is allowed\n"
"to change all of the channel settings for the channel;\n"
"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel."
+"channel operator privileges when they enter the channel."
msgstr ""
"Rejestruje kanał w bazie %s. Aby użyć tego polecenia,\n"
"musisz być operatorem na kanale, który chcesz zarejestrować.\n"
@@ -5773,7 +5697,7 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
"Rejestruje aktualnie używany nick w bazie %s.\n"
@@ -5790,7 +5714,7 @@ msgstr ""
"jako haseł jest niewskazane. Nie wolno użyć hasła takiego\n"
"samego, jak nick (a %s na to nie pozwoli). Bardzo krótkie\n"
"hasło może zostać odgadnięte metodą prób i błędów.\n"
-"Twoje hasło musi mieć długość co najmniej 5 znaków.\n"
+"Twoje hasło musi mieć długość co najmniej %u znaków.\n"
"Znak spacji nie może być użyty w haśle."
msgid "Registration is currently disabled."
@@ -5913,9 +5837,6 @@ msgstr "Zapamiętuje flagi kiedy kanał jest pusty"
msgid "Retain topic when channel is not in use"
msgstr "Zapamiętuje temat kiedy kanał jest pusty"
-msgid "Retrieve the password for a nickname"
-msgstr "Podaje hasło do wskazanego nicka"
-
msgid "Retrieves the vhost requests"
msgstr "Wyświetla prośby o vHosta"
@@ -5932,16 +5853,6 @@ msgid "Returns the owner status of the given nickname"
msgstr "Podaje status właściciela podanego nicka"
msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Zwraca hasło dla wskazanego nicka.\n"
-"UWAGA: użycie tej komendy powoduje wysłanie\n"
-"informacji o jej użyciu przy pomocy WALLOP/GLOBOP."
-
-msgid ""
"Returns whether the user using the given nickname is\n"
"recognized as the owner of the nickname. The response has\n"
"this format:\n"
@@ -6004,7 +5915,7 @@ msgstr "Wymuszono SSL na %s."
msgid "SSLONLY enforced by "
msgstr "SSLONLY wymuszony przez "
-msgid "Save databases and restart Services"
+msgid "Save databases and restart services"
msgstr "Zapisuje bazy i restartuje serwisy"
msgid "Searches logs for a matching pattern"
@@ -6109,7 +6020,7 @@ msgstr ""
msgid ""
"Sends the named nick or channel a memo containing\n"
"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
+"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered."
msgstr ""
"Wysyła wiadomość wskazanej osobie lub na podany kanał.\n"
@@ -6120,10 +6031,10 @@ msgstr ""
msgid ""
"Sends the named nick or channel a memo containing\n"
"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
+"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered.\n"
"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
+"memo will be sent to the sender informing them that the memo\n"
"has been read."
msgstr ""
"Wysyła wiadomość wskazanej osobie lub na podany kanał.\n"
@@ -6256,11 +6167,8 @@ msgstr "Serwisy zostały skonfigurowane tak, aby nie wysyłać poczty."
msgid "Services ignore list:"
msgstr "Lista ignorowanych przez serwisy:"
-msgid ""
-"Services is unable to change modes. Are your servers' U:lines configured "
-"correctly?"
-msgstr ""
-"Serwisy nie mogą zmieniać trybów. Czy U-linie serwerów są dobrze skonfigurowane?"
+msgid "Services is unable to change modes. Are your servers' U:lines configured correctly?"
+msgstr "Serwisy nie mogą zmieniać trybów. Czy U-linie serwerów są dobrze skonfigurowane?"
#, c-format
msgid "Services up %s."
@@ -6268,14 +6176,11 @@ msgstr "Serwisy uruchomione: %s."
#, c-format
msgid "Services will from now on set status modes on %s in channels."
-msgstr ""
-"Serwisy będą teraz automatycznie nadawały uprawnienia na kanałach dla użytkownika "
-"%s."
+msgstr "Serwisy będą teraz automatycznie nadawały uprawnienia na kanałach dla użytkownika %s."
#, c-format
msgid "Services will no longer automatically give modes to users in %s."
-msgstr ""
-"Serwisy nie będą już automatycznie nadawały uprawnień dla użytkowników na %s."
+msgstr "Serwisy nie będą już automatycznie nadawały uprawnień dla użytkowników na %s."
#, c-format
msgid "Services will no longer set status modes on %s in channels."
@@ -6307,8 +6212,8 @@ msgid "Session limiting is disabled."
msgstr "Limitowanie sesji jest wyłączone."
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Sesje: %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Sesje: %zu wpisów, %zu pakietów, najdłuższy łańcuch to %zu"
msgid "Set SET-options on another nickname"
msgstr "Ustawia opcje wskazanemu nickowi"
@@ -6316,7 +6221,7 @@ msgstr "Ustawia opcje wskazanemu nickowi"
msgid "Set channel options and information"
msgstr "Modyfikuje ustawienia kanału"
-msgid "Set how Services make bans on the channel"
+msgid "Set how services make bans on the channel"
msgstr "Ustawia sposób banowania przez serwisy"
msgid "Set options related to memos"
@@ -6331,13 +6236,13 @@ msgstr "Ustawia kanał jako \"wieczny\""
msgid "Set the channel description"
msgstr "Ustawia opis kanału"
-msgid "Set the display of your group in Services"
+msgid "Set the display of your group in services"
msgstr "Ustawia nick reprezentujący grupę nicków"
msgid "Set the founder of a channel"
msgstr "Ustawia nick właściciela kanału"
-msgid "Set the language Services will use when messaging you"
+msgid "Set the language services will use when messaging you"
msgstr "Ustawia język, w którym serwisy będą wysyłały komunikaty"
msgid "Set the nickname password"
@@ -6352,7 +6257,7 @@ msgstr "Zmienia vhosty wszystkich nicków w grupie"
msgid "Set the vhost of another user"
msgstr "Zmienia vhost wskazanemu użytkownikowi"
-msgid "Set various global Services options"
+msgid "Set various global services options"
msgstr "Ustawia różne globalne opcje serwisów"
msgid "Set your nickname password"
@@ -6588,7 +6493,7 @@ msgstr ""
"można zmieniać także ident."
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -6627,14 +6532,10 @@ msgstr ""
"%s%s HELP %s opcja"
msgid "Sets various nickname options. option can be one of:"
-msgstr ""
-"Ustawia różne opcje nicka. Dostępne opcje to (jeśli nie widzisz żadnych, zaloguj "
-"się):"
+msgstr "Ustawia różne opcje nicka. Dostępne opcje to (jeśli nie widzisz żadnych, zaloguj się):"
msgid "Sets whether services should set channel status modes on you automatically."
-msgstr ""
-"Pozwala na wybór, czy serwisy będą ustawiały automatycznie Twoje uprawnienia na "
-"kanale."
+msgstr "Pozwala na wybór, czy serwisy będą ustawiały automatycznie Twoje uprawnienia na kanale."
msgid ""
"Sets whether the given channel will expire. Setting this\n"
@@ -6643,6 +6544,9 @@ msgstr ""
"Włącza lub wyłącza automatyczne usunięcie kanału,\n"
"jeśli nie będzie on używany."
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr "Ustawia, czy podany nick może zostać dodany do kanałowych list dostępu."
+
#, c-format
msgid ""
"Sets whether the given nickname will be given its status modes\n"
@@ -6663,6 +6567,9 @@ msgstr ""
"Włącza lub wyłącza automatyczne usunięcie nicka,\n"
"jeśli nie będzie on używany."
+msgid "Sets whether you can be added to a channel access list."
+msgstr "Ustawia, czy możesz być dodany/a do kanałowych list dostępu."
+
#, c-format
msgid ""
"Sets whether you will be given your channel status modes automatically.\n"
@@ -6696,12 +6603,12 @@ msgstr "Parametrem opcji SUPERADMIN musi być ON albo OFF."
msgid "Should services automatically give status to users"
msgstr "Włącza lub wyłącza automatyczne opowanie"
-msgid "Show status of Services and network"
+msgid "Show status of services and network"
msgstr "Pokazuje informacje o serwisach i sieci"
#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr "Wyświetlono %d/%d dopasowań dla %s."
+msgid "Showed %zu/%zu matches for %s."
+msgstr "Wyświetlono %zu/%zu dopasowań dla %s."
msgid "Sign kicks that are done with the KICK command"
msgstr "Podpisuje kicki kiedy użyto komendy KICK"
@@ -6788,9 +6695,7 @@ msgstr "Możesz mieć tylko %d wpisów na kanałowej liście dostępu."
#, c-format
msgid "Sorry, the maximum of %d auto join entries has been reached."
-msgstr ""
-"Przepraszamy, maksymalna liczba %d wpisów automatycznego dołączania została "
-"osiągnięta."
+msgstr "Przepraszamy, maksymalna liczba %d wpisów automatycznego dołączania została osiągnięta."
#, c-format
msgid "Sorry, the maximum of %d certificate entries has been reached."
@@ -6801,11 +6706,8 @@ msgid "Sorry, the memo ignore list for %s is full."
msgstr "Lista ignorowania dla %s jest już pełna."
#, c-format
-msgid ""
-"Sorry, you can only have %d access entries on a channel, including access entries "
-"from other channels."
-msgstr ""
-"Możesz mieć tylko %d wpisów na kanałowej liście dostępu, wliczając inne kanały."
+msgid "Sorry, you can only have %d access entries on a channel, including access entries from other channels."
+msgstr "Możesz mieć tylko %d wpisów na kanałowej liście dostępu, wliczając inne kanały."
#, c-format
msgid "Sorry, you can only have %d autokick masks on a channel."
@@ -7076,13 +6978,13 @@ msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
+"users will not be allowed to modify any services data,\n"
"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
@@ -7094,12 +6996,13 @@ msgstr ""
"opcji powoduje zablokowanie wykonywania zmian w ustawieniach\n"
"serwisów, dotyczy to list dostępu kanału oraz nicka itd.\n"
"Operatorzy serwisów z odpowiednimi uprawnieniami będą\n"
-"mogli modyfikować listę AKILL, usuwać lub blokować nicki\n"
-"oraz kanały, ale żadne z tych zmian nie zostaną zapisane\n"
-"dopóki tryb tylko-do-odczytu nie zostanie wyłączony przed\n"
+"mogli modyfikować listę AKILL, SQLINE, SNLINE, ignore,\n"
+"usuwać lub blokować nicki oraz kanały, zarządzać wiadomościami\n"
+"NEWS,ale żadne z tych zmian nie zostaną zapisane,\n"
+"chyba, że tryb tylko-do-odczytu zostanie wyłączony przed\n"
"restartem lub wyłączeniem serwisów.\n"
"\n"
-"Ta opcja ma taki sam efekt jak argument linii poleceń -readonly."
+"Ta opcja ma taki sam efekt jak argument linii poleceń --readonly."
msgid ""
"Syntax: SUPERADMIN {ON | OFF}\n"
@@ -7166,8 +7069,8 @@ msgstr ""
"uprawnienie AOP, lub tych o poziomie dostępu 5 lub wyższym."
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7179,13 +7082,13 @@ msgstr ""
"sztucznego serwera, co zapobiega podłączaniu prawdziwego\n"
"serwera o tej samej nazwie. Blokadę można zdjąć używając\n"
"standardowego polecenia SQUIT. Jeśli zostanie podany\n"
-"powód będzie on wyświetlany w polu informacyjnym serwera,\n"
+"powód, będzie on wyświetlany w polu informacyjnym serwera,\n"
"w przeciwnym wypadku wyświetlane będzie \"Juped by <nick>\"."
msgid "Tells you about the last time a user was seen"
msgstr "Informuje, kiedy ostatnio widziano użytkownika"
-msgid "Terminate Services WITHOUT saving"
+msgid "Terminate services WITHOUT saving"
msgstr "Wyłącza serwisy NIE zapisując baz"
msgid "Terminate services with save"
@@ -7251,12 +7154,8 @@ msgstr ""
" \n"
"Polecenie ACCESS CLEAR usuwa wszystkie wpisy z listy dostępowej."
-msgid ""
-"The CLEAR command clears the channel access list. This requires channel founder "
-"access."
-msgstr ""
-"Polecenie CLEAR usuwa wszystkie wpisy z listy dostępów kanału. Wymaga to "
-"uprawnień założyciela."
+msgid "The CLEAR command clears the channel access list. This requires channel founder access."
+msgstr "Polecenie CLEAR usuwa wszystkie wpisy z listy dostępów kanału. Wymaga to uprawnień założyciela."
#, c-format
msgid ""
@@ -7355,7 +7254,7 @@ msgid ""
"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
"disables an automatic feature or disallows access to a\n"
"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it). Use LEVELS SET founder to make a level\n"
+"can always re-enable it). Use LEVELS SET founder to make a level\n"
"founder only.\n"
" \n"
"LEVELS LIST shows the current levels for each function or\n"
@@ -7378,6 +7277,7 @@ msgstr ""
"dla wszystkich, wraz Z WŁAŚCICIELEM (ale właściciel może ją włączyć\n"
"ponownie). Użyj komendy LEVELS SET founder aby przydzielić\n"
"podane uprawnienie tylko właścicielowi. \n"
+"\n"
"LEVELS LIST wyświetla bieżącą listę poziomów dla każdej funkcji\n"
"lub grupy funkcji. LEVELS RESET przywraca ustawienia poziomów\n"
"do domyślnych, takich, jakie są one na świeżo stworzonych kanałach.\n"
@@ -7387,10 +7287,8 @@ msgstr ""
msgid ""
"The LIST command allows you to list existing entries on the channel access list.\n"
-"If a mask is given, the mask is wildcard matched against all existing entries on "
-"the\n"
-"access list, and only those entries are returned. If a set of flags is given, "
-"only those\n"
+"If a mask is given, the mask is wildcard matched against all existing entries on the\n"
+"access list, and only those entries are returned. If a set of flags is given, only those\n"
"on the access list with the specified flags are returned."
msgstr ""
"Polecenie LIST pozwala na przeglądanie zawartości kanałowej listy dostępu.\n"
@@ -7401,12 +7299,9 @@ msgid ""
"The MODIFY command allows you to modify the access list. If the mask is\n"
"not already on the access list it is added, then the changes are applied.\n"
"If the mask has no more flags, then the mask is removed from the access list.\n"
-"Additionally, you may use +* or -* to add or remove all flags, respectively. You "
-"are\n"
-"only able to modify the access list if you have the proper permission on the "
-"channel,\n"
-"and even then you can only give other people access to the equivalent of what "
-"your access is."
+"Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n"
+"only able to modify the access list if you have the proper permission on the channel,\n"
+"and even then you can only give other people access to the equivalent of what your access is."
msgstr ""
"Polecenie MODIFY pozwala na zmianę kanałowej listy dostępu.\n"
"Gdy podana maska nie znajduje się już na liście dostępowej, zostanie ona\n"
@@ -7418,9 +7313,7 @@ msgstr ""
"użytkowników na poziomie wyższym niż Twoje."
msgid "The STATS command prints out statistics about stored nicks and memory usage."
-msgstr ""
-"Komenda STATS wyświetla statystyki dotyczące zapisanych nicków i wykorzystania "
-"pamięci."
+msgstr "Komenda STATS wyświetla statystyki dotyczące zapisanych nicków i wykorzystania pamięci."
msgid ""
"The email parameter is optional and will set the email\n"
@@ -7540,11 +7433,8 @@ msgstr ""
"poziomu włącznie."
#, c-format
-msgid ""
-"The host %s currently has %d sessions with a limit of %d because it matches entry:"
-" %s."
-msgstr ""
-"Host %s aktualnie posiada %d sesji z limitem %d, ponieważ pasuje do wpisu: %s."
+msgid "The host %s currently has %d sessions with a limit of %d because it matches entry: %s."
+msgstr "Host %s aktualnie posiada %d sesji z limitem %d, ponieważ pasuje do wpisu: %s."
#, c-format
msgid "The last memo you sent to %s (sent on %s) has been read."
@@ -7630,8 +7520,8 @@ msgstr ""
"przez serwisy."
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "Jest %d wiadomości dla kanału %s."
+msgid "There are %zu memos on channel %s."
+msgstr "Jest %zu wiadomości dla kanału %s."
msgid ""
"There are no bots available at this time.\n"
@@ -7655,16 +7545,16 @@ msgid "There currently are no logging configurations for %s."
msgstr "Aktualnie nie ma logowania skonfigurowanego dla %s."
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "Jest %d wiadomość dla kanału %s."
+msgid "There is %zu memo on channel %s."
+msgstr "Jest %zu wiadomość dla kanału %s."
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
+"Type %s%s READ %s %zu to read it."
msgstr ""
"Jest nowa wiadomość dla kanału %s.\n"
-"Napisz %s%s READ %s %d aby przeczytać."
+"Napisz %s%s READ %s %zu aby przeczytać."
#, c-format
msgid "There is no bot assigned to %s anymore."
@@ -7705,16 +7595,14 @@ msgstr "Ten kanał nie może być używany."
msgid ""
"This command allows managing DNS zones used for controlling what servers users\n"
-"are directed to when connecting. Omitting all parameters prints out the status "
-"of\n"
+"are directed to when connecting. Omitting all parameters prints out the status of\n"
"the DNS zone.\n"
" \n"
"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to this\n"
"zone with the ADDSERVER command.\n"
" \n"
"The ADDSERVER command adds a server to the given zone. When a query is done, the\n"
-"zone in question is served if it exists, else all servers in all zones are "
-"served.\n"
+"zone in question is served if it exists, else all servers in all zones are served.\n"
"A server may be in more than one zone.\n"
" \n"
"The ADDIP command associates an IP with a server.\n"
@@ -7722,18 +7610,14 @@ msgid ""
"The POOL and DEPOOL commands actually add and remove servers to their given zones."
msgstr ""
"To polecenie pozwala na zarządzanie strefami DNS, używanych do sprawdzania,\n"
-"na które serwery trafiają łączący się użytkownicy. Pominięcie wszystkich "
-"parametrów\n"
+"na które serwery trafiają łączący się użytkownicy. Pominięcie wszystkich parametrów\n"
"wyświetli status strefy DNS.\n"
"\n"
-"ADDZONE dodaje strefę, np. pl.twojasiec.net. Następnie do stworzonej strefy "
-"można\n"
+"ADDZONE dodaje strefę, np. pl.twojasiec.net. Następnie do stworzonej strefy można\n"
"dodawać serwery używając komendy ADDSERVER.\n"
" \n"
-"Komenda ADDSERVER dodaje serwer do podanej strefy. Gdy otrzymane zostanie "
-"zapytanie,\n"
-"to gdy strefa istnieje, zostanie ona wykorzystana, a w przeciwnym przypadku "
-"przesłane zostaną\n"
+"Komenda ADDSERVER dodaje serwer do podanej strefy. Gdy otrzymane zostanie zapytanie,\n"
+"to gdy strefa istnieje, zostanie ona wykorzystana, a w przeciwnym przypadku przesłane zostaną\n"
"wszystkie serwery ze wszystkich stref.\n"
" Serwer może znajdować się we więcej niż jednej strefie.\n"
" \n"
@@ -7878,12 +7762,8 @@ msgstr ""
"Operatorzy serwisów mogą podać nicka, aby modyfikować listy\n"
"innych użytkowników."
-msgid ""
-"This command may not be used on this network because nickname ownership is "
-"disabled."
-msgstr ""
-"Tego polecenia nie można użyć w tej sieci, gdyż rejestracja nicków nie jest "
-"dostępna."
+msgid "This command may not be used on this network because nickname ownership is disabled."
+msgstr "Tego polecenia nie można użyć w tej sieci, gdyż rejestracja nicków nie jest dostępna."
msgid "This command reloads the module named modname."
msgstr "To polecenie ponownie ładuje wskazany moduł z katalogu modułów."
@@ -7892,7 +7772,7 @@ msgid "This command retrieves the vhost requests."
msgstr "Ta komenda powoduje wyświetlenie próśb o vHosta."
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -7946,8 +7826,7 @@ msgid "This command unloads the module named modname."
msgstr "To polecenie wyładowuje wskazany moduł."
msgid "This command will resend you the registration confirmation email."
-msgstr ""
-"To polecenie spowoduje ponowne wysłanie e-maila potwierdzającego rejestrację."
+msgstr "To polecenie spowoduje ponowne wysłanie e-maila potwierdzającego rejestrację."
#, c-format
msgid ""
@@ -8370,12 +8249,12 @@ msgid "Users"
msgstr "Użytkownicy"
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Użytkownicy (nicki): %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Użytkownicy (nicki): %lu wpisów, %lu pakietów, najdłuższy łańcuch to %zu"
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Użytkownicy (uid): %lu wpisów, %lu pakietów, najdłuższy łańcuch to %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Użytkownicy (uid): %lu wpisów, %lu pakietów, najdłuższy łańcuch to %zu"
msgid "Users list:"
msgstr "Lista użytkowników:"
@@ -8474,22 +8353,23 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
"Polecenie wydane bez parametrów odwraca działanie\n"
"komendy IDENTIFY - nie będziesz rozpoznawany jako\n"
-"właściciel nicka.\n"
+"właściciel nicka. Zwróć uwagę, że nie otrzymasz wtedy prośby\n"
+"o ponowne zalogowanie.\n"
"\n"
"Administrator serwisów może podać jako parametr nick\n"
"użytkownika, który ma zostać wylogowany. Parametr\n"
-"REVALIDATE powoduje informowanie przez serwisy\n"
+"REVALIDATE powoduje informowanie przez serwisy\n"
"użytkownika o potrzebie ponownej identyfikacji."
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -8505,9 +8385,8 @@ msgid ""
"The ALL option displays all of the above statistics."
msgstr ""
"Polecenie bez parametrów wyświetla bieżącą liczbę \n"
-"użytkowników oraz operatorów podłączonych do sieci (nie\n"
-"licząc serwisów), największą liczbę użytkowników licząc od \n"
-"startu serwisów oraz czas pracy serwisów.\n"
+"użytkowników podłączonych do sieci, największą liczbę\n"
+"użytkowników licząc od startu serwisów, oraz czas pracy serwisów.\n"
"\n"
"Parametr AKILL wyświetla informacje o rozmiarze listy\n"
"AKILL oraz domyślnym czasie wygasania wpisów.\n"
@@ -8554,9 +8433,6 @@ msgstr "Nie korzystasz z certyfikatu klienta."
msgid "You are now a super admin."
msgstr "Jesteś teraz super-administratorem."
-msgid "You are now an IRC Operator."
-msgstr "Jesteś teraz IRC operatorem."
-
msgid "You are now identified for your nick. Change your password now."
msgstr "Jesteś zidentyfikowany. Zmień teraz swoje hasło."
@@ -8565,33 +8441,26 @@ msgid "You are now in the group of %s."
msgstr "Należysz teraz do grupy %s."
#, c-format
-msgid ""
-"You are over your maximum number of memos (%d). You will be unable to receive any "
-"new memos until you delete some of your current ones."
+msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr ""
"Uwaga: Maksymalny limit wiadomości (%d) został osiągnięty.\n"
"Nie będziesz otrzymywać nowych wiadomości jeśli kilku nie usuniesz."
-msgid "You can not NOOP Services."
+msgid "You can not NOOP services."
msgstr "Nie możesz użyć NOOP na serwisach."
-msgid ""
-"You can not disable the founder privilege because it would be impossible to "
-"reenable it at a later time."
-msgstr ""
-"Nie możesz wyłączyć uprawnienia właściciela, gdyż nie dałoby się wtedy ustawić go "
-"ponownie w przyszłości."
+msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
+msgstr "Nie możesz wyłączyć uprawnienia właściciela, gdyż nie dałoby się wtedy ustawić go ponownie w przyszłości."
msgid "You can not jupe an already juped server."
msgstr "Nie można wykluczyć serwera, ponieważ już to zrobiono."
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
+msgid "You can not jupe your services' pseudoserver or your uplink server."
msgstr "Nie można wykluczyć samych serwisów lub uplinka serwisów."
#, c-format
msgid "You can not reload this module directly, instead reload %s."
-msgstr ""
-"Nie możesz bezpośrednio przeładować podanego modułu. Zamiast tego przeładuj %s."
+msgstr "Nie możesz bezpośrednio przeładować podanego modułu. Zamiast tego przeładuj %s."
msgid "You can not request a receipt when sending a memo to yourself."
msgstr "Nie możesz wysyłać wiadomości z potwierdzeniem odbioru do siebie!"
@@ -8633,20 +8502,20 @@ msgid "You cannot use this command."
msgstr "Nie możesz użyć tego polecenia."
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Aktualnie masz %d wiadomości, z czego %d jest nieprzeczytanych."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr "Aktualnie masz %zu wiadomości, z czego %zu jest nieprzeczytanych."
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Aktualnie masz %d wiadomości, w tym jedną nieprzeczytaną."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr "Aktualnie masz %zu wiadomości, w tym jedną nieprzeczytaną."
#, c-format
-msgid "You currently have %d memos."
-msgstr "Aktualnie masz %d wiadomości."
+msgid "You currently have %zu memos."
+msgstr "Aktualnie masz %zu wiadomości."
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Aktualnie masz %d nieprzeczytanych wiadomości."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr "Aktualnie masz %zu nieprzeczytanych wiadomości."
msgid "You currently have 1 memo, and it has not yet been read."
msgstr "Aktualnie masz jedną wiadomość i jest ona nieprzeczytana."
@@ -8679,10 +8548,10 @@ msgstr "Masz jedną nową wiadomość."
#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
+"Type %s%s READ %zu to read it."
msgstr ""
"Masz nową wiadomość od %s.\n"
-"Napisz %s%s READ %d aby przeczytać."
+"Napisz %s%s READ %zu aby przeczytać."
#, c-format
msgid "You have been invited to %s by %s."
@@ -8717,9 +8586,7 @@ msgid "You have no new memos."
msgstr "Nie masz nowych wiadomości."
#, c-format
-msgid ""
-"You have reached your maximum number of memos (%d). You will be unable to receive "
-"any new memos until you delete some of your current ones."
+msgid "You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr ""
"Uwaga: Osiągnięto już limit wiadomości (%d).\n"
"Nie będziesz otrzymywać nowych wiadomości dopóki\n"
@@ -8748,21 +8615,14 @@ msgstr "Nie możesz zmienić hasła innych operatorów serwisów."
msgid "You may not drop other Services Operators' nicknames."
msgstr "Nie możesz skasować nicków innych operatorów serwisów."
-msgid "You may not get the password of other Services Operators."
-msgstr "Nie możesz odczytać hasła innych operatorów serwisów."
-
msgid "You may not suspend other Services Operators' nicknames."
msgstr "Nie możesz zawiesić nicków innych operatorów serwisów."
msgid "You may view but not modify the access list of other Services Operators."
-msgstr ""
-"Możesz podglądać, ale nie modyfikować list dostępowych innych operatorów serwisów."
+msgstr "Możesz podglądać, ale nie modyfikować list dostępowych innych operatorów serwisów."
-msgid ""
-"You may view but not modify the certificate list of other Services Operators."
-msgstr ""
-"Możesz podglądać, ale nie modyfikować list certyfikatów innych operatorów "
-"serwisów."
+msgid "You may view but not modify the certificate list of other Services Operators."
+msgstr "Możesz podglądać, ale nie modyfikować list certyfikatów innych operatorów serwisów."
#, c-format
msgid "You might see yourself in the mirror, %s."
@@ -8791,16 +8651,12 @@ msgid "You must confirm your account before you may send a memo."
msgstr "Musisz potwierdzić swoje konto przed wysłaniem wiadomości."
#, c-format
-msgid ""
-"You must enter the channel name twice as a confirmation that you wish to drop %s."
-msgstr ""
-"Musisz dwukrotnie podać nazwę kanału, aby potwierdzić, że na pewno chcesz "
-"odrejestrować %s."
+msgid "You must enter the channel name twice as a confirmation that you wish to drop %s."
+msgstr "Musisz dwukrotnie podać nazwę kanału, aby potwierdzić, że na pewno chcesz odrejestrować %s."
#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr ""
-"Musisz być połączony(a) dłużej niż %d sekund(y), aby móc zarejestrować nick."
+msgid "You must have been using this nick for at least %lu seconds to register."
+msgstr "Musisz być połączony(a) dłużej niż %lu sekund(y), aby móc zarejestrować nick."
#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
@@ -8822,9 +8678,7 @@ msgstr ""
"Będziesz otrzymywać powiadomienie o nowych wiadomościach\n"
"na IRC i przez e-mail."
-msgid ""
-"You will be notified of new memos at logon and when they arrive, and by mail when "
-"they arrive."
+msgid "You will be notified of new memos at logon and when they arrive, and by mail when they arrive."
msgstr ""
"Będziesz powiadomienie informacje o nowych wiadomościach\n"
"podczas logowania i w momencie ich nadejścia (bezpośrednio\n"
@@ -8867,11 +8721,8 @@ msgstr "Ten IRCd nie obsługuje SVSNICK."
msgid "Your IRCd does not support SVSPART."
msgstr "Ten IRCd nie obsługuje SVSPART."
-msgid ""
-"Your IRCd does not support vIdent's, if this is incorrect, please report this as "
-"a possible bug"
-msgstr ""
-"Ten IRCd nie obsługuje vIdentów. Jeżeli to nieprawda, wyślij zgłoszenie o błędzie."
+msgid "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
+msgstr "Ten IRCd nie obsługuje vIdentów. Jeżeli to nieprawda, wyślij zgłoszenie o błędzie."
#, c-format
msgid "Your account %s has been successfully created."
@@ -8891,12 +8742,8 @@ msgstr "Twój adres e-mail został zmieniony na %s."
msgid "Your email address is not allowed, choose a different one."
msgstr "Twój e-mail nie jest dozwolony. Użyj innego."
-msgid ""
-"Your email address is not confirmed. To confirm it, follow the instructions that "
-"were emailed to you."
-msgstr ""
-"Twój adres e-mail nie jest potwierdzony. Aby to zrobić, postępuj według wysłanych "
-"Tobie instrukcji."
+msgid "Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you."
+msgstr "Twój adres e-mail nie jest potwierdzony. Aby to zrobić, postępuj według wysłanych Tobie instrukcji."
#, c-format
msgid "Your email address of %s has been confirmed."
@@ -8928,12 +8775,8 @@ msgstr "Twój limit wiadomości wynosi %d."
msgid "Your memo limit is 0; you will not receive any new memos."
msgstr "Twój limit wiadomości wynosi 0, nie będziesz otrzymywać nowych."
-msgid ""
-"Your memo limit is 0; you will not receive any new memos. You cannot change this "
-"limit."
-msgstr ""
-"Twój limit wiadomości wynosi 0, nie będziesz odbierać nowych i nie możesz zmienić "
-"tego limitu."
+msgid "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
+msgstr "Twój limit wiadomości wynosi 0, nie będziesz odbierać nowych i nie możesz zmienić tego limitu."
msgid "Your nick has been logged out."
msgstr "Twój nick został pomyślnie wylogowany."
@@ -8942,8 +8785,7 @@ msgid "Your nick is already registered."
msgstr "Twój nick jest już zarejestrowany."
msgid "Your nick is not grouped to anything, you can't ungroup it."
-msgstr ""
-"Nie możesz usunąć swojego nicka z grupy, ponieważ w żadnej się nie znajduje."
+msgstr "Nie możesz usunąć swojego nicka z grupy, ponieważ w żadnej się nie znajduje."
msgid "Your nick isn't registered."
msgstr "Twój nick nie jest zarejestrowany."
@@ -8960,12 +8802,12 @@ msgid "Your passcode has been re-sent to %s."
msgstr "Twój kod rejestracyjny został ponownie wysłany na %s."
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Twoje hasło do nicka to %s"
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr "Twoje hasło jest zbyt długie (max %u znaków)."
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr "Twoje hasło jest zbyt długie (max %u znaków)."
+msgid "Your password is too short. It must be longer than %u characters."
+msgstr "Twoje hasło jest zbyt krótkie. Musi mieć więcej, niż %u znaków."
msgid "Your password reset request has expired."
msgstr "Twoja prośba o reset hasła jest nieaktualna."
@@ -9082,8 +8924,7 @@ msgstr "[wiadomość automatyczna] Twój vHost został odrzucony."
#, c-format
msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr ""
-"[wiadomość automatyczna] Twoja prośba o vHosta została odrzucona. Podany powód: %s"
+msgstr "[wiadomość automatyczna] Twoja prośba o vHosta została odrzucona. Podany powód: %s"
#, c-format
msgid "[auto memo] vHost %s has been requested by %s."
@@ -9196,6 +9037,3 @@ msgstr "{nick | kanał}"
msgid "{nick | channel} memo-text"
msgstr "{nick | kanał} treść"
-
-#~ msgid "Password authentication required for that command."
-#~ msgstr "Ta komenda wymaga zalogowania do zarejestrowanego nicka."
diff --git a/language/anope.pt_PT.po b/language/anope.pt_PT.po
index cb3904628..ccb0b6ee8 100644
--- a/language/anope.pt_PT.po
+++ b/language/anope.pt_PT.po
@@ -1,242 +1,245 @@
# Anope IRC Services language file
-# Copyright (C) 2011
+# Copyright (C) 2014-2024
# This file is distributed under the same license as the Anope IRC Services package.
-# Adam <adam@anope.org>, 2011.
+# Adam <adam@anope.org>, 2014.
#
msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-01-06 18:19+0100\n"
-"PO-Revision-Date: 2010-09-19 21:02-0400\n"
-"Last-Translator: Adam <adam@anope.org>\n"
+"POT-Creation-Date: 2024-11-08 15:36+0100\n"
+"PO-Revision-Date: 2024-11-08 23:51+0100\n"
+"Last-Translator: PeGaSuS <james@ptirc.org>\n"
"Language-Team: Portuguese\n"
"Language: pt_PT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.4.2\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
-msgstr ""
+msgstr "%d canal(is) apagados, e %d canal(is) descartados."
-#, fuzzy, c-format
+#, c-format
msgid "%d nickname(s) dropped."
-msgstr "O registro do seu nick foi cancelado."
+msgstr "%d nickname(s) descartados."
-#, fuzzy, c-format
+#, c-format
msgid "%s added to %s %s list."
-msgstr "%s adicionado à lista de AKILL."
+msgstr "%s adicionado à lista %s de %s."
#, c-format
msgid "%s added to %s access list at level %d."
-msgstr "%s adicionado à lista de acesso do %s com o nível %d."
+msgstr "%s adicionado à lista de acesso de %s com o nível %d."
-#, fuzzy, c-format
+#, c-format
msgid "%s added to %s access list at privilege %s (level %d)"
-msgstr "%s adicionado à lista de acesso do %s com o nível %d."
+msgstr "%s adicionado à lista de acesso de %s com privilégio %s (nível %d)"
#, c-format
msgid "%s added to %s autokick list."
-msgstr "%s adicionado à lista de akick do %s."
+msgstr "%s adicionado à lista de autokick de %s."
#, c-format
msgid "%s added to %s bad words list."
-msgstr "%s adicionado na lista de palavrões do %s."
+msgstr "%s adicionado à lista de palavrões de %s."
-#, fuzzy, c-format
-msgid "%s added to %s's access list."
-msgstr "%s adicionado em sua lista de acesso."
-
-#, fuzzy, c-format
+#, c-format
msgid "%s added to %s's certificate list."
-msgstr "%s adicionado em sua lista de acesso."
+msgstr "%s adicionado à lista de certificados de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s added to ignore list."
-msgstr "%s adicionado em sua lista de acesso."
+msgstr "%s adicionado à lista de ignore."
-#, fuzzy, c-format
+#, c-format
msgid "%s added to the %s list."
-msgstr "%s adicionado à lista de AKILL."
+msgstr "%s adicionado à lista de %s."
#, c-format
msgid "%s added to the AKILL list."
-msgstr "%s adicionado à lista de AKILL."
+msgstr "%s adicionado à lista AKILL."
#, c-format
msgid ""
"%s allows you to execute \"fantasy\" commands in the channel.\n"
"Fantasy commands are commands that can be executed from messaging a\n"
-"channel, and provide a more convenient way to execute commands. Commands "
-"that\n"
+"channel, and provide a more convenient way to execute commands. Commands that\n"
"require a channel as a parameter will automatically have that parameter\n"
"given.\n"
msgstr ""
+"%s permite executar comandos \"fantasia\" no canal.\n"
+"Comandos de fantasia são comandos que podem ser executados a partir de mensagens a\n"
+"um canal e fornecem uma maneira mais conveniente de executar comandos. Comandos que\n"
+"requerem um canal como parâmetro terão automaticamente esse parâmetro\n"
+"fornecido.\n"
+"\n"
-#, fuzzy, c-format
+#, c-format
msgid ""
"%s allows you to have a bot on your own channel.\n"
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
+"below; to use them, type %s command. For\n"
"more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
-"%s permite que você tenha um bot no seu canal.\n"
-"Foi criado para usuários que não tem como hospedar\n"
-"ou configurar um bot, ou para Redes que não permitem\n"
-"aos usuários terem um bot. Os comandos disponíveis \n"
-"estão listados abaixo; para usá-los, digite\n"
-"/msg %s comando. Para informações mais específicas\n"
-"sobre um comando, digite /msg %s HELP comando."
+"%s permite ter um bot no seu próprio canal.\n"
+"Foi criado para utilizadores que não podem alojar ou\n"
+"configurar um bot, ou para utilização em redes que não\n"
+"permitem bots de utilizadores. Os comandos disponíveis estão\n"
+"listado abaixo; para os utilizar, digite %s comando. Para\n"
+"obter mais informações sobre um comando específico, digite\n"
+"%s %s comando.\n"
-#, fuzzy, c-format
+#, c-format
msgid ""
"%s allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
+"nicknames; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
-"%s permite que você \"registre\" um nick e evita que outras\n"
-"pessoas o utilizem. Os seguintes comandos permitem o\n"
-"registro e a manutenção dos nicks; para utilizá-los, digite\n"
-"/msg %s comando. Para mais informações sobre um\n"
-"comando específico, digite /msg %s HELP comando."
+"%s permite que você registe um nickname e\n"
+"evita que outros o utilizem. Os comandos a\n"
+"seguir permitem o registo e manutenção de\n"
+"nicknames; para usa-los, digite %s comando.\n"
+"Para obter mais informações sobre um comando específico, digite\n"
+"%s %s comando.\n"
-#, fuzzy, c-format
+#, c-format
msgid ""
"%s allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
+"accounts; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
-"%s permite que você \"registre\" um nick e evita que outras\n"
-"pessoas o utilizem. Os seguintes comandos permitem o\n"
-"registro e a manutenção dos nicks; para utilizá-los, digite\n"
-"/msg %s comando. Para mais informações sobre um\n"
-"comando específico, digite /msg %s HELP comando."
+"%s permite que você registe uma conta.\n"
+"Os comandos a seguir permitem o registo e manutenção de\n"
+"contas; para usa-los, digite %s comando.\n"
+"Para obter mais informações sobre um comando específico, digite\n"
+"%s %s comando.\n"
-#, fuzzy, c-format
+#, c-format
msgid ""
"%s allows you to register and control various\n"
"aspects of channels. %s can often prevent\n"
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
+"%s command. For more information on a\n"
+"specific command, type %s HELP command.\n"
msgstr ""
-"%s permite que você registre e controle vários\n"
-"aspectos do canal. %s pode prevenir o \"take over\"\n"
-"do canal por usuários maliciosos, limitando quem possui\n"
-"o privilégio de OP do canal. Os comandos disponíveis\n"
-"estão listados abaixo; para usá-los, digite\n"
-"/msg %s comando. Para mais informações sobre\n"
-"um comando específico, digite /msg %s HELP comando."
+"%s permite registar e controlar vários\n"
+"aspetos dos canais. %s pode muitas vezes impedir\n"
+"que utilizadores mal-intencionados \"assumam o controlo\" dos canais, limitando\n"
+"quem tem privilégios de operador de canal. Os comandos\n"
+"disponíveis estão listados abaixo; para os utilizar, digite\n"
+"%s comando. Para obter mais informações sobre um\n"
+"comando específico, digite %s HELP comando.\n"
#, c-format
msgid "%s already exists in %s bad words list."
-msgstr "%s já existe na lista de palavrões do %s."
+msgstr "%s já existe na lista de palavrões de %s."
#, c-format
msgid "%s already exists on %s autokick list."
-msgstr "%s já existe na lista de akick do %s."
+msgstr "%s já existe na lista de autokick de %s."
#, c-format
msgid "%s already exists on the EXCEPTION list."
-msgstr "%s já existe na lista de EXCEPTION."
+msgstr "%s já existe na lista de EXCEÇÕES."
#, c-format
msgid "%s cannot be taken as times to ban."
-msgstr "%s não pode ser colocado como tempo para ban."
+msgstr "%s não pode ser usado como vezes para banir."
-#, fuzzy, c-format
+#, c-format
msgid "%s changed your usermodes to %s."
-msgstr "%s alterou seus modos de usuário."
+msgstr "%s mudou seus modos de usuário para %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s channel list:"
-msgstr "Fim da listagem."
+msgstr "%s lista de canais:"
-#, fuzzy, c-format
+#, c-format
msgid "%s deleted from %s %s list."
-msgstr "%s deletado da lista de AOP do %s."
+msgstr "%s excluído da lista %s de %s."
#, c-format
msgid "%s deleted from %s access list."
-msgstr "%s removido da lista de acesso do %s."
+msgstr "%s excluído da lista de acesso de %s."
#, c-format
msgid "%s deleted from %s autokick list."
-msgstr "%s removido da lista de akick do %s."
+msgstr "%s excluído da lista de autokick de %s."
#, c-format
msgid "%s deleted from %s bad words list."
-msgstr "%s removido da lista de palavrões do %s."
+msgstr "%s excluído da lista de palavrões de %s."
-#, fuzzy, c-format
-msgid "%s deleted from %s's access list."
-msgstr "%s removido da lista de acesso do %s."
-
-#, fuzzy, c-format
+#, c-format
msgid "%s deleted from %s's certificate list."
-msgstr "%s removido da sua lista de acesso."
+msgstr "%s excluído da lista de certificados de %s."
#, c-format
msgid "%s deleted from session-limit exception list."
-msgstr "%s removido da lista de limite de sessões."
+msgstr "%s excluído da lista de exceções de limite de sessão."
-#, fuzzy, c-format
+#, c-format
msgid "%s deleted from the %s list."
-msgstr "%s deletado da lista de AOP do %s."
+msgstr "%s excluído da lista de %s."
#, c-format
msgid "%s deleted from the AKILL list."
-msgstr "%s removido da lista de AKILL."
+msgstr "%s excluído da lista de AKILL."
#, c-format
msgid "%s disabled on channel %s."
msgstr "%s desabilitado no canal %s."
#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr "%s não deseja ser adicionado às listas de acesso de canais."
+
+#, c-format
msgid "%s has been invited to %s."
-msgstr "%s has been invited to %s."
+msgstr "%s foi convidado para o %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s has been joined to %s."
-msgstr "%s has been invited to %s."
+msgstr "%s foi associado ao %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s has been parted from %s."
-msgstr "%s has been unbanned from %s."
+msgstr "%s foi separado do %s."
#, c-format
msgid "%s has been unbanned from %s."
-msgstr "%s has been unbanned from %s."
+msgstr "%s foi desbanido do %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s has no access in any channels."
-msgstr "%s desabilitado no canal %s."
+msgstr "%s não tem acesso em nenhum canal."
-#, fuzzy, c-format
+#, c-format
msgid "%s has no access on %s."
-msgstr "%s has been invited to %s."
+msgstr "%s não tem acesso no %s."
#, c-format
msgid "%s has too many channels registered."
-msgstr "%s possui muitos canais registrados."
+msgstr "%s tem muitos canais registados."
-#, fuzzy, c-format
+#, c-format
msgid "%s is a super administrator."
-msgstr "%s is a services operator of type %s."
+msgstr "%s é um super administrador."
-#, fuzzy, c-format
+#, c-format
msgid ""
"%s is a utility allowing IRC users to send short\n"
"messages to other IRC users, whether they are online at\n"
@@ -245,141 +248,132 @@ msgid ""
"registered in order to send a memo.\n"
"%s's commands include:"
msgstr ""
-"%s é um serviço que permite aos usuários de IRC\n"
-"enviar curtas mensagens a outros usuários, mesmo\n"
-"que eles estejam conectados no momento ou não; ou\n"
-"a canais(*). Ambos, destinatários e remetentes,\n"
-"devem possuir seus nicks (ou canais) registrados para\n"
-"que possam enviar uma mensagem (memo).\n"
-"Os comandos do %s são:"
+"%s é um utilitário que permite aos usuários de IRC enviar\n"
+"mensagens curtas para outros usuários de IRC, estejam eles online\n"
+"ou não, ou para canais(*). Tanto o nickname do remetente quanto o\n"
+"nickname ou canal de destino devem ser registados\n"
+"para enviar um memorando.\n"
+"Os comandos do %s incluem:"
-#, fuzzy, c-format
+#, c-format
msgid "%s is already in %s!"
-msgstr "You are already in %s! "
+msgstr "%s já está no %s!"
-#, fuzzy, c-format
+#, c-format
msgid "%s is already in %s."
-msgstr "You are already in %s! "
+msgstr "%s já está no %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s is already on the ignore list."
-msgstr "%s adicionado em sua lista de acesso."
+msgstr "%s já está na lista de ignore."
-#, fuzzy, c-format
+#, c-format
msgid "%s is already suspended."
-msgstr "You are already in %s! "
+msgstr "%s já está suspenso."
-#, fuzzy, c-format
+#, c-format
msgid "%s is not a registered unforbidden nick or channel."
-msgstr "%s não é um bot válido ou um canal registrado."
+msgstr "%s não é um nick ou canal não proibido registado."
#, c-format
msgid "%s is not a valid ban type."
-msgstr "%s não é um ban válido."
+msgstr "%s não é um tipo de ban válido."
#, c-format
msgid "%s is not a valid bot or registered channel."
-msgstr "%s não é um bot válido ou um canal registrado."
+msgstr "%s não é um bot válido ou canal registado."
-#, fuzzy, c-format
-msgid "%s is not a valid e-mail address."
-msgstr "%s não é um ban válido."
+#, c-format
+msgid "%s is not a valid email address."
+msgstr "%s não é um endereço de email válido."
-#, fuzzy, c-format
+#, c-format
msgid "%s is not currently on channel %s."
-msgstr "%s desabilitado no canal %s."
+msgstr "%s não está atualmente no canal %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s is not in %s."
-msgstr "You are already in %s! "
+msgstr "%s não está no %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s is not on the ignore list."
-msgstr "%s não encontrado na lista de Ignore."
+msgstr "%s não está na lista de ignore."
-#, fuzzy, c-format
+#, c-format
msgid "%s is on the auto kick list of %s (%s)."
-msgstr "%s adicionado à lista de akick do %s."
+msgstr "%s está na lista de kicks automáticos de %s (%s)."
-#, fuzzy, c-format
+#, c-format
msgid "%s is the founder of %s."
-msgstr "%s desabilitado no canal %s."
+msgstr "%s é o fundador do %s."
#, c-format
msgid "%s matches access entry %s (from entry %s), which has privilege %s."
-msgstr ""
+msgstr "%s corresponde à entrada de acesso %s (da entrada %s), que tem o privilégio %s."
#, c-format
msgid "%s matches access entry %s, which has privilege %s."
-msgstr ""
+msgstr "%s corresponde à entrada de acesso %s, que tem o privilégio %s."
#, c-format
-msgid ""
-"%s matches an except on %s and cannot be banned until the except has been "
-"removed."
-msgstr ""
+msgid "%s matches an except on %s and cannot be banned until the except has been removed."
+msgstr "%s corresponde a uma exceção em %s e não pode ser banido até que a exceção seja removida."
-#, fuzzy, c-format
+#, c-format
msgid "%s matches auto kick entry %s on %s (%s)."
-msgstr "%s adicionado à lista de akick do %s."
+msgstr "%s corresponde à entrada de kick automático %s no %s (%s)."
-#, fuzzy, c-format
+#, c-format
msgid "%s not found on %s %s list."
-msgstr "Nick %s não encontrado na lista de AOP do %s."
+msgstr "%s não encontrado na lista %s de %s."
#, c-format
msgid "%s not found on %s access list."
-msgstr "%s não foi encontrado na lista de acesso do %s."
+msgstr "%s não encontrado na lista de acesso de %s."
#, c-format
msgid "%s not found on %s autokick list."
-msgstr "%s não encontrado na lista de akick do %s."
+msgstr "%s não encontrado na lista de autokick de %s."
#, c-format
msgid "%s not found on %s bad words list."
-msgstr "%s não foi encontrado na lista de palavrões do %s."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's access list."
-msgstr "%s não foi encontrado na lista de acesso do %s."
+msgstr "%s não foi encontrado na lista de palavrões de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s not found on %s's certificate list."
-msgstr "%s não foi encontrado em sua lista de acesso."
+msgstr "%s não encontrado na lista de certificados de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s not found on ignore list."
-msgstr "%s não encontrado na lista de Ignore."
+msgstr "%s não encontrado na lista de ignore."
#, c-format
-msgid ""
-"%s not found on session list, but has a limit of %d because it matches entry:"
-" %s."
-msgstr ""
+msgid "%s not found on session list, but has a limit of %d because it matches entry: %s."
+msgstr "%s não foi encontrado na lista de sessões, mas tem um limite de %d porque corresponde à entrada: %s."
#, c-format
msgid "%s not found on session-limit exception list."
-msgstr "%s não encontrado na lista de limite de sessões."
+msgstr "%s não encontrado na lista de exceções de limite de sessão."
-#, fuzzy, c-format
+#, c-format
msgid "%s not found on the %s list."
-msgstr "Nick %s não encontrado na lista de AOP do %s."
+msgstr "%s não encontrado na lista de %s."
#, c-format
msgid "%s not found on the AKILL list."
msgstr "%s não encontrado na lista de AKILL."
-#, fuzzy, c-format
+#, c-format
msgid "%s removed from the %s access list."
-msgstr "%s removido da lista de acesso do %s."
+msgstr "%s foi removido da lista de acesso de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s removed from the ignore list."
-msgstr "%s removido da sua lista de acesso."
+msgstr "%s removido da lista de ignore."
-#, fuzzy, c-format
+#, c-format
msgid "%s users list:"
-msgstr "Fim da listagem."
+msgstr "%s lista de usuários:"
#, c-format
msgid "%s will no longer be ignored."
@@ -391,29 +385,21 @@ msgstr "%s agora será ignorado por %s."
#, c-format
msgid "%s will now permanently be ignored."
-msgstr "%s agora será permanentemente ignorado."
+msgstr "%s agora será ignorado permanentemente."
-#, fuzzy, c-format
-msgid "%s%s HELP %s for more information."
-msgstr ""
-"Digite /msg %s HELP SET opção para maiores informações\n"
-"sobre uma opção em particular."
+#, c-format
+msgid "%s HELP %s for more information."
+msgstr "%s HELP %s para mais informações."
msgid "ADD nick user host real"
-msgstr ""
+msgstr "ADD nick user host real"
-#, fuzzy
msgid "CHANGE oldnick newnick [user [host [real]]]"
-msgstr ""
-"BOT ADD nick user host real\n"
-"BOT CHANGE nickantigo nicknovo [user [host [real]]]\n"
-"BOT DEL nick"
+msgstr "CHANGE nick-antigo novo-nick [user [host [real]]]"
-#, fuzzy
msgid "DEL nick"
-msgstr "DEL <nick>."
+msgstr "DEL nick"
-#, fuzzy
msgid ""
"EXCEPTION ADD adds the given host mask to the exception list.\n"
"Note that nick!user@host and user@host masks are invalid!\n"
@@ -437,47 +423,27 @@ msgid ""
"Note that a connecting client will \"use\" the first exception\n"
"their host matches."
msgstr ""
-"Sintaxe: EXCEPTION ADD [+tempo] máscara limite motivo\n"
-" EXCEPTION DEL {máscara | lista}\n"
-" EXCEPTION MOVE núm posição\n"
-" EXCEPTION LIST [máscara | lista]\n"
-" EXCEPTION VIEW [máscara | lista]\n"
-"\n"
-"Permite que os Administradores dos Services manipulem a lista\n"
-"de hosts que tenham limite de conexões especificados - deixando \n"
-"certos hosts, como shell de servidores, conectar mais que o\n"
-"número padrão de conexões simultâneas. Uma vez um host atingindo\n"
-"um limite de conexão, todos os clientes que tentem conectar \n"
-"daquele host serão expulsos (\"killados\").\n"
-"Antes do usuário ser expulso (\"killado\"), ele será notificado\n"
-"via /NOTICE do %s com um tópico de ajuda sobre limitação\n"
-"de conexões.\n"
-"\n"
-"EXCEPTION ADD adiciona a máscara fornecida à lista de exceções.\n"
-"Note que as máscaras nick!user@host e user@host são\n"
-"inválidas. Só nomes reais de hosts, como mail.dominio.com e \n"
-"*.dominio.com, são permitidos porque a limitação de\n"
-"conexão não utiliza o nick ou ident para bloquear o acesso. \n"
-"\n"
-"EXCEPTION DEL remove a máscara especificada da Lista de\n"
-"exceções.\n"
-"EXCEPTION MOVE move uma exceção de número núm para uma\n"
-"posição dada. As exceções que estavam na faixa onde houve\n"
-"alteração serão todas movidas para cima ou para baixo conforme\n"
-"for o deslocamento necessário.\n"
-"EXCEPTION LIST ou EXCEPTION VIEW mostram todas as \n"
-"exceções atuais válidas; se uma máscara é dada como parâmetro\n"
-"opcional, a lista é limitada as exceções que são compatíveis\n"
-"com a máscara dada. A diferenca é que EXCEPTION VIEW \n"
-"é mais detalhado, mostrando o nome da pessoa que adicionou \n"
-"a exceção, o seu limite de conexões, o motivo, a máscara do\n"
-"host, a data e o tempo de validade.\n"
-"\n"
-"Note que um cliente que conecte vai usar a primeira exceção\n"
-"que for compatível com o seu host. Listas de exceções muito\n"
-"grandes e máscaras de hosts muito abrangentes certamente\n"
-"irão degradar a eficácia de funcionamento (\"performance\")\n"
-"dos services."
+"EXCEPTION ADD adiciona a máscara de host fornecida à lista de exceções.\n"
+"Note que as máscaras nick!user@host e user@host são inválidas!\n"
+"Somente máscaras de host reais, como box.host.dom e *.host.dom,\n"
+"são permitidas porque a limitação de sessões não leva em consideração nick ou\n"
+"nomes de usuário. O limite deve ser um número maior\n"
+"ou igual a zero. Isso determina quantas sessões esse host\n"
+"pode realizar por vez. Um valor zero significa que o host tem um\n"
+"limite de sessão ilimitado. Consulte a ajuda do AKILL para obter\n"
+"detalhes sobre o formato do parâmetro opcional de expiração.\n"
+" \n"
+"EXCEPTION DEL remove a máscara fornecida da lista de exceções.\n"
+" \n"
+"EXCEPTION LIST e EXCEPTION VIEW mostram todas as sessões\n"
+"atuais se a máscara opcional for fornecida, a lista é limitada\n"
+"às sessões que correspondem à máscara. A diferença é que\n"
+"EXCEPTION VIEW mais detalhado, exibindo o nome da\n"
+"pessoa que adicionou a exceção, seu limite de sessão, motivo,\n"
+"máscara de host e data e hora de expiração.\n"
+" \n"
+"Observe que um cliente conectado \"usará\" a primeira exceção\n"
+"correspondente ao seu host."
msgid ""
"SET kills all operators from the given\n"
@@ -485,404 +451,325 @@ msgid ""
"up on the given server. REVOKE removes this\n"
"restriction."
msgstr ""
+"SET killa todos os operadores de um determinado\n"
+"servidor e evita que os operadores operem\n"
+"nesse servidor. REVOKE remove esta\n"
+"restrição."
#, c-format
msgid ""
"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
+"%s command; type %s HELP LEVELS for\n"
"information."
msgstr ""
+"Os níveis de acesso do utilizador podem ser vistos através\n"
+"do comando %s ; digite %s HELP LEVELS para\n"
+"obter mais informações."
#, c-format
msgid "[auto-memo] The memo you sent to %s has been viewed."
-msgstr "[Auto-Memo] O memo que você enviou para %s foi lido."
+msgstr "[auto-memo] O memorando que você enviou para %s foi visualizado."
-#, fuzzy
msgid "[target] [password]"
-msgstr "GROUP alvo senha"
+msgstr "[alvo] [senha]"
msgid "address"
-msgstr ""
+msgstr "endereço"
-#, fuzzy
msgid "botname {ON|OFF}"
-msgstr "SASET nickname AUTOOP {ON | OFF}"
+msgstr "nome-do-bot {ON|OFF}"
-#, fuzzy
msgid "channel"
-msgstr "DROP canal"
+msgstr "canal"
-#, fuzzy
msgid "channel bantype"
-msgstr "ACT canal texto"
-
-#, fuzzy
-msgid "channel channel"
-msgstr "TOPIC canal [tópico]"
+msgstr "canal tipo-de-ban"
-#, fuzzy
msgid "channel command method [status]"
-msgstr "KICK canal opções {ON|OFF} [configurações]"
+msgstr "canal comando método [status]"
-#, fuzzy
msgid "channel mask [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "canal máscara [razão]"
-#, fuzzy
msgid "channel modes"
-msgstr "MODE canal modos"
+msgstr "canal modos"
-#, fuzzy
msgid "channel nick"
-msgstr "UNBAN canal [nick]"
+msgstr "canal nick"
-#, fuzzy
msgid "channel nick [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "canal nick [razão]"
-#, fuzzy
msgid "channel target [what]"
-msgstr "CLEAR canal opção"
+msgstr "canal alvo [quê]"
-#, fuzzy
msgid "channel text"
-msgstr "ACT canal texto"
+msgstr "canal texto"
-#, fuzzy
msgid "channel time"
-msgstr "ACT canal texto"
+msgstr "canal tempo"
-#, fuzzy
msgid "channel user reason"
-msgstr "KICK canal usuário motivo"
+msgstr "canal usuário razão"
-#, fuzzy
msgid "channel what"
-msgstr "TOPIC canal [tópico]"
+msgstr "canal quê"
-#, fuzzy
-msgid "channel ADD mask"
-msgstr "MODE canal modos"
+msgid "channel ADD mask level [description]"
+msgstr "canal ADD máscara nível [descrição]"
-msgid "channel ADD mask level"
-msgstr ""
+msgid "channel ADD mask [description]"
+msgstr "canal ADD máscara [descrição]"
-#, fuzzy
msgid "channel ADD message"
-msgstr "MODE canal modos"
+msgstr "canal ADD mensagem"
msgid "channel ADD word [SINGLE | START | END]"
-msgstr ""
+msgstr "canal ADD palavra [SINGLE | START | END]"
-#, fuzzy
msgid "channel ADD {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "canal ADD {nick | máscara} [razão]"
-#, fuzzy
msgid "channel APPEND topic"
-msgstr "TOPIC canal [tópico]"
+msgstr "canal APPEND tópico"
-#, fuzzy
msgid "channel CLEAR"
-msgstr "DROP canal"
+msgstr "canal CLEAR"
-#, fuzzy
msgid "channel CLEAR [what]"
-msgstr "TOPIC canal [tópico]"
+msgstr "canal CLEAR [quê]"
-#, fuzzy
msgid "channel CLEAR [ALL]"
-msgstr "DROP canal"
+msgstr "canal CLEAR [ALL]"
-#, fuzzy
msgid "channel DEL num"
-msgstr "MODE canal modos"
+msgstr "canal DEL num"
-#, fuzzy
msgid "channel DEL {mask | entry-num | list}"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr "canal DEL {máscara | número-entrada | lista}"
-#, fuzzy
msgid "channel DEL {nick | mask | entry-num | list}"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | entrada]"
+msgstr "canal DEL {nick | máscara | número-entrada | lista}"
-#, fuzzy
msgid "channel DEL {word | entry-num | list}"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr "canal DEL {palavra | número-entrada | lista}"
msgid "channel ENFORCE"
-msgstr ""
+msgstr "canal ENFORCE"
-#, fuzzy
msgid "channel LIST"
-msgstr "DROP canal"
+msgstr "canal LIST"
-#, fuzzy
msgid "channel LIST [mask | entry-num | list]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | entrada]"
+msgstr "canal LIST [máscara | número-entrada | lista]"
-#, fuzzy
msgid "channel LIST [mask | list]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | entrada]"
+msgstr "canal LIST [máscara | lista]"
msgid "channel LIST [mask | +flags]"
-msgstr ""
+msgstr "canal LIST [máscara | +flags]"
-#, fuzzy
msgid "channel LOCK {ADD|DEL|SET|LIST} [what]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | entrada]"
+msgstr "canal LOCK {ADD|DEL|SET|LIST} [quê]"
-#, fuzzy
msgid "channel RESET"
-msgstr "SET canal GREET {ON|OFF}"
+msgstr "canal RESET"
-#, fuzzy
msgid "channel SET modes"
-msgstr "MODE canal modos"
+msgstr "canal SET modos"
msgid "channel SET type level"
-msgstr ""
+msgstr "canal SET tipo nível"
-#, fuzzy
msgid "channel VIEW [mask | entry-num | list]"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | entrada]"
+msgstr "canal VIEW [máscara | número-entrada | lista]"
-#, fuzzy
msgid "channel VIEW [mask | list]"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr "canal VIEW [máscara | lista]"
+
+msgid "channel [code]"
+msgstr "canal [código]"
-#, fuzzy
msgid "channel [description]"
-msgstr "REGISTER canal descrição"
+msgstr "canal [descrição]"
-#, fuzzy
msgid "channel [nick]"
-msgstr "UNBAN canal [nick]"
+msgstr "canal [nick]"
-#, fuzzy
msgid "channel [parameters]"
-msgstr "CLEAR canal opção"
+msgstr "canal [parâmetros]"
-#, fuzzy
msgid "channel [user]"
-msgstr "UNBAN canal [nick]"
+msgstr "canal [usuário]"
-#, fuzzy
msgid "channel [+expiry] [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "canal [+expiração] [razão]"
-#, fuzzy
msgid "channel [+expiry] {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "canal [+expiração] {nick | máscara} [razão]"
-#, fuzzy
-msgid "channel [MODIFY] mask changes"
-msgstr "BAN #channel nick [reason]"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr "canal [MODIFY] máscara mudanças [descrição]"
-#, fuzzy
msgid "channel [SET] [topic]"
-msgstr "TOPIC canal [tópico]"
+msgstr "canal [SET] [tópico]"
-#, fuzzy
msgid "channel [UNLOCK|LOCK]"
-msgstr "DROP canal"
+msgstr "canal [UNLOCK|LOCK]"
-#, fuzzy
msgid "channel {ON|OFF}"
-msgstr "SET canal XOP {ON | OFF}"
+msgstr "canal {ON|OFF}"
-#, fuzzy
msgid "channel {ON|OFF} [ttb [ln [secs]]]"
-msgstr "KICK canal opções {ON|OFF} [configurações]"
+msgstr "canal {ON|OFF} [ttb [ln [seg]]]"
-#, fuzzy
msgid "channel {ON|OFF} [ttb [min [percent]]]"
-msgstr "KICK canal opções {ON|OFF} [configurações]"
+msgstr "canal {ON|OFF} [ttb [min [percent]]]"
-#, fuzzy
msgid "channel {ON|OFF} [ttb [num]]"
-msgstr "KICK canal opções {ON|OFF} [configurações]"
+msgstr "canal {ON|OFF} [ttb [num]]"
-#, fuzzy
msgid "channel {ON|OFF} [ttb]"
-msgstr "SET canal XOP {ON | OFF}"
+msgstr "canal {ON|OFF} [ttb]"
msgid "channel {DIS | DISABLE} type"
-msgstr ""
+msgstr "canal {DIS | DISABLE} tipo"
-#, fuzzy
msgid "channel {ON | LEVEL | OFF}"
-msgstr "SET canal SIGNKICK {ON | LEVEL | OFF}"
+msgstr "canal {ON | LEVEL | OFF}"
-#, fuzzy
msgid "channel {ON | OFF}"
-msgstr "SET canal XOP {ON | OFF}"
+msgstr "canal {ON | OFF}"
msgid "email"
-msgstr ""
+msgstr "email"
-#, fuzzy
msgid "language"
-msgstr "SET LANGUAGE número"
+msgstr "idioma"
-#, fuzzy
msgid "memo-text"
-msgstr "STAFF memo-text"
+msgstr "texto-memorando"
-#, fuzzy
msgid "message"
-msgstr "GLOBAL mensagem"
+msgstr "mensagem"
msgid "modname"
-msgstr ""
+msgstr "nome-do-módulo"
msgid "new-display"
-msgstr ""
+msgstr "novo-display"
-#, fuzzy
msgid "new-password"
-msgstr "GROUP alvo senha"
+msgstr "nova-senha"
-#, fuzzy
msgid "nick"
-msgstr "INFO nick"
+msgstr "nick"
-#, fuzzy
msgid "nick channel"
-msgstr "CANCEL {nick | canal}"
+msgstr "nick canal"
-#, fuzzy
msgid "nick channel [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "nick canal [razão]"
-#, fuzzy
-msgid "nick flags"
-msgstr "OLINE nick flags"
-
-#, fuzzy
msgid "nick hostmask"
-msgstr "SET <nick> <hostmask>."
+msgstr "nick hostmask"
-#, fuzzy
msgid "nick newnick"
-msgstr "SVSNICK nick novonick "
+msgstr "nick novo-nick"
-#, fuzzy
msgid "nick [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "nick [razão]"
-#, fuzzy
msgid "nickname"
-msgstr "CHECK nick"
+msgstr "nickname"
-#, fuzzy
msgid "nickname address"
-msgstr "FORBID nick motivo"
+msgstr "nickname endereço"
-#, fuzzy
msgid "nickname email"
-msgstr "FORBID nick motivo"
+msgstr "nickname email"
-#, fuzzy
msgid "nickname language"
-msgstr "FORBID nick motivo"
+msgstr "nickname idioma"
-#, fuzzy
msgid "nickname message"
-msgstr "FORBID nick motivo"
+msgstr "nickname mensagem"
-#, fuzzy
msgid "nickname new-display"
-msgstr "FORBID nick motivo"
+msgstr "nickname novo-display"
-#, fuzzy
msgid "nickname new-password"
-msgstr "GHOST nick [senha]"
+msgstr "nickname nova-senha"
+
+msgid "nickname [code]"
+msgstr "nickname [código]"
-#, fuzzy
msgid "nickname [parameter]"
-msgstr "GHOST nick [senha]"
+msgstr "nickname [parâmetro]"
-#, fuzzy
msgid "nickname [password]"
-msgstr "GHOST nick [senha]"
+msgstr "nickname [senha]"
-#, fuzzy
msgid "nickname [+expiry] [reason]"
-msgstr "FORBID nick motivo"
+msgstr "nickname [+expiração] [razão]"
-#, fuzzy
msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-msgstr "SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
+msgstr "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-#, fuzzy
msgid "nickname {ON | OFF}"
-msgstr "SASET nickname AUTOOP {ON | OFF}"
+msgstr "nickname {ON | OFF}"
-#, fuzzy
msgid "nickname {ON | QUICK | IMMED | OFF}"
-msgstr "SASET nickname KILL {ON | QUICK | IMMED | OFF}"
+msgstr "nickname {ON | QUICK | IMMED | OFF}"
-#, fuzzy
msgid "option (channel | bot) settings"
-msgstr "SET canal opções configurações"
+msgstr "opção (canal | bot) configurações"
-#, fuzzy
msgid "option channel parameters"
-msgstr "SEND {nick | canal} texto"
+msgstr "opção canal parâmetros"
-#, fuzzy
msgid "option channel {ON|OFF} [settings]"
-msgstr "KICK canal opções {ON|OFF} [configurações]"
+msgstr "opção canal {ON|OFF} [configurações]"
msgid "option nickname parameters"
-msgstr ""
+msgstr "opção nickname parâmetros"
-#, fuzzy
msgid "option parameters"
-msgstr "SET opção configuração"
+msgstr "opção parâmetros"
-#, fuzzy
msgid "option setting"
-msgstr "SET opção configuração"
+msgstr "opção configuração"
-#, fuzzy
msgid "passcode"
-msgstr "REGISTER senha email"
+msgstr "senha"
-#, fuzzy
msgid "password"
-msgstr "GROUP alvo senha"
+msgstr "senha"
-#, fuzzy
msgid "password [email]"
-msgstr "REGISTER senha email"
+msgstr "senha [email]"
-#, fuzzy
msgid "password email"
-msgstr "REGISTER senha email"
+msgstr "senha email"
-#, fuzzy
msgid "pattern [SUSPENDED] [NOEXPIRE]"
-msgstr "LIST opções [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
+msgstr "padrão [SUSPENDED] [NOEXPIRE]"
-#, fuzzy
msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-msgstr "LIST opções [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
+msgstr "padrão [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
+
+msgid "server [message]"
+msgstr "servidor [mensagem]"
-#, fuzzy
msgid "server [reason]"
-msgstr "JUPE servidor [motivo]"
+msgstr "servidor [razão]"
-#, fuzzy
msgid "user modes"
-msgstr "MODE canal modos"
+msgstr "usuário modos"
-#, fuzzy
msgid "user [reason]"
-msgstr "JUPE servidor [motivo]"
+msgstr "usuário [razão]"
-#, fuzzy
msgid ""
" \n"
"SNLINE ADD adds the given realname mask to the SNLINE\n"
@@ -900,55 +787,25 @@ msgid ""
"Note: because the realname mask may contain spaces, the\n"
"separator between it and the reason is a colon."
msgstr ""
-"Sintaxe: AKILL ADD [+tempo] máscara motivo\n"
-" AKILL DEL {máscara | entrada | lista-entradas}\n"
-" AKILL LIST [máscara | lista-entradas]\n"
-" AKILL VIEW [máscara | lista-entradas]\n"
-" AKILL CLEAR\n"
-"\n"
-"Permite que Operadores dos Services manipulem a lista de\n"
-"AKILL. Se um usuário que tenta conectar possui uma máscara\n"
-"prevista na lista de AKILL, os Services emitem um KILL para\n"
-"aquele usuário, em servidores que suportam, e instrui todos\n"
-"os servidores da rede a adicionar um ban (K-line) para a\n"
-"máscara do usuário encontrado.\n"
-"\n"
-"AKILL ADD adiciona uma máscara ident@host na lista de AKILL\n"
-"para um dado motivo (deve ser fornecido).\n"
-"Opcionalmente, um tempo para o akill expirar pode ser\n"
-"fornecido. O tempo precede a máscara ident@host, e é\n"
-"especificado como um número inteiro seguido por uma das\n"
-"seguintes unidades: d (dias), h (horas) ou m (minutos).\n"
-"Combinações (como 1h30m) não são permitidas. Se uma unidade\n"
-"específica não é incluída, o padrão é em dias (assim, +30\n"
-"significa 30 dias). Para adicionar um AKILL que não expira,\n"
-"use +0. Se a máscara a ser adicionada começar com um +,\n"
-"o tempo do AKILL deve ser fornecido, mesmo se esse tempo for igual\n"
-"ao padrão. O tempo atual de expiração de AKILLs pode ser encontrado\n"
+" \n"
+"SNLINE ADD adiciona a máscara de nome real fornecida à\n"
+"lista SNLINE pelo motivo especificado (que deve ser fornecido).\n"
+"A expiração é especificada como um número inteiro seguido por um de d\n"
+"(dias), h (horas), ou m (minutos). Combinações (como\n"
+"1h30m) não são permitidas. Se um especificador de unidade não\n"
+"estiver incluído, o padrão será dias (portanto +30 por si só significa 30\n"
+"dias). Para adicionar um SNLINE que não expira, use +0. Se a\n"
+"máscara de nome real a ser adicionada começar com +, um tempo de expiração\n"
+"deverá ser fornecido, mesmo que seja igual ao padrão. O\n"
+"tempo de expiração padrão atual do SNLINE pode ser encontrado\n"
"com o comando STATS AKILL.\n"
-"\n"
-"AKILL DEL remove uma dada máscara da lista de AKILL, se ela\n"
-"estiver presente. Se uma lista de números de entrada for fornecida,\n"
-"essas entradas serão apagadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"AKILL LIST mostra a lista de AKILL atual.\n"
-"Se uma máscara for fornecida, apenas as entradas que combinarem\n"
-"com a máscara serão exibidas. Se uma lista de números de entrada\n"
-"for fornecida, apenas essas entradas serão exibidas; por exemplo:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" Lista as entradas de AKILL numeradas de 2 a 5 e de 7 a 9.\n"
-"\n"
-"AKILL VIEW é uma versão mais detalhada do AKILL LIST,\n"
-"e mostrará quem adicionou o AKILL, a data em que foi adicionado,\n"
-"e quando irá expirar, como também a máscara (ident@host) e o motivo.\n"
-"\n"
-"AKILL CLEAR apaga todas as entradas da lista de AKILL."
+" \n"
+"Nota: como a máscara do nome real pode conter espaços, o\n"
+"separador entre ela e o motivo é dois pontos."
-#, fuzzy
msgid ""
" \n"
-"SQLINE ADD adds the given (nick's) mask to the SQLINE\n"
+"SQLINE ADD adds the given (nick/channel) mask to the SQLINE\n"
"list for the given reason (which must be given).\n"
"expiry is specified as an integer followed by one of d\n"
"(days), h (hours), or m (minutes). Combinations (such as\n"
@@ -960,67 +817,37 @@ msgid ""
"current SQLINE default expiry time can be found with the\n"
"STATS AKILL command."
msgstr ""
-"Sintaxe: AKILL ADD [+tempo] máscara motivo\n"
-" AKILL DEL {máscara | entrada | lista-entradas}\n"
-" AKILL LIST [máscara | lista-entradas]\n"
-" AKILL VIEW [máscara | lista-entradas]\n"
-" AKILL CLEAR\n"
-"\n"
-"Permite que Operadores dos Services manipulem a lista de\n"
-"AKILL. Se um usuário que tenta conectar possui uma máscara\n"
-"prevista na lista de AKILL, os Services emitem um KILL para\n"
-"aquele usuário, em servidores que suportam, e instrui todos\n"
-"os servidores da rede a adicionar um ban (K-line) para a\n"
-"máscara do usuário encontrado.\n"
-"\n"
-"AKILL ADD adiciona uma máscara ident@host na lista de AKILL\n"
-"para um dado motivo (deve ser fornecido).\n"
-"Opcionalmente, um tempo para o akill expirar pode ser\n"
-"fornecido. O tempo precede a máscara ident@host, e é\n"
-"especificado como um número inteiro seguido por uma das\n"
-"seguintes unidades: d (dias), h (horas) ou m (minutos).\n"
-"Combinações (como 1h30m) não são permitidas. Se uma unidade\n"
-"específica não é incluída, o padrão é em dias (assim, +30\n"
-"significa 30 dias). Para adicionar um AKILL que não expira,\n"
-"use +0. Se a máscara a ser adicionada começar com um +,\n"
-"o tempo do AKILL deve ser fornecido, mesmo se esse tempo for igual\n"
-"ao padrão. O tempo atual de expiração de AKILLs pode ser encontrado\n"
-"com o comando STATS AKILL.\n"
-"\n"
-"AKILL DEL remove uma dada máscara da lista de AKILL, se ela\n"
-"estiver presente. Se uma lista de números de entrada for fornecida,\n"
-"essas entradas serão apagadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"AKILL LIST mostra a lista de AKILL atual.\n"
-"Se uma máscara for fornecida, apenas as entradas que combinarem\n"
-"com a máscara serão exibidas. Se uma lista de números de entrada\n"
-"for fornecida, apenas essas entradas serão exibidas; por exemplo:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" Lista as entradas de AKILL numeradas de 2 a 5 e de 7 a 9.\n"
-"\n"
-"AKILL VIEW é uma versão mais detalhada do AKILL LIST,\n"
-"e mostrará quem adicionou o AKILL, a data em que foi adicionado,\n"
-"e quando irá expirar, como também a máscara (ident@host) e o motivo.\n"
-"\n"
-"AKILL CLEAR apaga todas as entradas da lista de AKILL."
+" \n"
+"SQLINE ADD adiciona a máscara (nick/canal) fornecida à lista \n"
+"SQLINE pelo motivo especificado (que deve ser fornecido).\n"
+"A expiração é especificada como um número inteiro seguido por d\n"
+"(dias), h (horas), ou m (minutos). Combinações (como\n"
+"1h30m) não são permitidas. Se um especificador de unidade não\n"
+"estiver incluído, o padrão será dias (portanto +30 por si só significa 30\n"
+"dias). Para adicionar um SQLINE que não expira, use +0.\n"
+"Se a máscara a ser adicionada começar com +, deverá ser fornecido um\n"
+"tempo de expiração, mesmo que seja igual ao padrão. O\n"
+"tempo de expiração padrão atual do SQLINE pode ser encontrado com o\n"
+"comando STATS AKILL."
-#, fuzzy, c-format
+#, c-format
msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
-"Nicks que não estejam mais sendo usados estão sujeitos \n"
-"a expirarem automaticamente, ou seja, eles serão apagados\n"
-"após %d dias sem serem usados."
+" \n"
+"As contas que não são mais utilizadas estão sujeitas\n"
+"à expiração automática, ou seja, serão excluídas\n"
+"após %lu dias se não forem utilizadas."
-#, fuzzy
msgid ""
" \n"
"Available commands are:"
-msgstr "Nenhuma ajuda disponível para %s."
+msgstr ""
+" \n"
+"Os comandos disponíveis são:"
#, c-format
msgid ""
@@ -1028,8 +855,11 @@ msgid ""
"Bot will join a channel whenever there is at least\n"
"%d user(s) on it."
msgstr ""
+" \n"
+"O bot entrará em um canal sempre que houver pelo menos\n"
+"%d usuário(s) nele."
-#, fuzzy, c-format
+#, c-format
msgid ""
" \n"
"Enables or disables fantasy mode on a channel.\n"
@@ -1037,27 +867,20 @@ msgid ""
"fantasy commands on a channel when prefixed\n"
"with one of the following fantasy characters: %s\n"
" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
+"Note that users wanting to use fantasy commands\n"
+"MUST have enough access for both the FANTASY\n"
+"privilege and the command they are executing."
msgstr ""
-"Sintaxe: SET canal FANTASY {ON|OFF}\n"
-"\n"
-"Ativa ou desativa o modo fantasia em um canal.\n"
-"Quando estiver ativado, os usuários poderão usar\n"
-"comandos como !op, !deop, !voice, !devoice,\n"
-"!kick, !kb, !unban, !seen em um canal. Em algumas\n"
-"redes, mais comandos podem estar disponíveis, tais\n"
-"como: !owner, !deowner, !protect, !deprotect,\n"
-"!halfop, !dehalfop.\n"
-"\n"
-"Note que os usuários que quiserem usar esses \n"
-"comandos DEVEM ter um nível suficiente tanto para\n"
-"o nível FANTASIA quanto para outro, dependendo\n"
-"do comando usado (por exemplo, para usar !op, o \n"
-"usuário deve ter acesso aos comandos OP e DEOP)."
+" \n"
+"Ativa ou desativa o modofantasia em um canal.\n"
+"Quando ativado, os utilizadores poderão usar\n"
+"comandos de fantasia em um canal quando prefixado\n"
+"com um dos seguintes caracteres de fantasia: %s\n"
+" \n"
+"Note que os utilizadores que desejam usar comandos\n"
+"fantasia DEVEM ter acesso suficiente tanto para o FANTASIA\n"
+"quanto para o comando que estão executando."
-#, fuzzy
msgid ""
" \n"
"Enables or disables greet mode on a channel.\n"
@@ -1065,83 +888,86 @@ msgid ""
"messages of users joining the channel, provided\n"
"they have enough access to the channel."
msgstr ""
-"Sintaxe: SET canal GREET {ON|OFF}\n"
-"\n"
-"Ativa ou desativa o modo greet em um canal.\n"
-"Quando ativado, o bot irá mostrar mensagens de\n"
-"entrada dos usuários quando eles entrarem no\n"
-"canal, caso tenham nível de acesso suficiente."
+" \n"
+"Ativa ou desativa o modo de saudação em um canal.\n"
+"Quando habilitado, o bot exibirá mensagens de saudação\n"
+"dos usuários que entrem no canal, desde que\n"
+"tenham acesso suficiente ao canal."
-#, fuzzy
msgid ""
" \n"
"Enables or disables ops protection mode on a channel.\n"
"When it is enabled, ops won't be kicked by the bot\n"
"even if they don't match the NOKICK level."
msgstr ""
-"Sintaxe: SET canal DONTKICKOPS {ON|OFF}\n"
-"\n"
-"Ativa ou desativa o modo de proteção de OPs em um canal.\n"
-"Quando estiver ativado, os OPs não serão kickados pelo bot,\n"
-"mesmo se eles não se enquadram no nível de NOKICK."
+" \n"
+"Ativa ou desativa o modo de proteção de ops em um canal.\n"
+"Quando ativado, os ops não serão kickados pelo bot\n"
+"mesmo que não correspondam ao nível NOKICK."
-#, fuzzy
msgid ""
" \n"
"Enables or disables voices protection mode on a channel.\n"
"When it is enabled, voices won't be kicked by the bot\n"
"even if they don't match the NOKICK level."
msgstr ""
-"Sintaxe: SET canal DONTKICKVOICES {ON|OFF}\n"
-"\n"
+" \n"
"Ativa ou desativa o modo de proteção de voices em um canal.\n"
-"Quando estiver ativado, os voices não serão kickados pelo bot,\n"
-"mesmo se eles não se enquadram no nível de NOKICK."
+"Quando ativado, os voices não serão kickados pelo bot\n"
+"mesmo que não correspondam ao nível NOKICK."
#, c-format
msgid ""
" \n"
"Fantasy commands may be prefixed with one of the following characters: %s\n"
msgstr ""
+" \n"
+"Os comandos de fantasia podem ser prefixados com um dos seguintes caracteres: %s\n"
msgid ""
" \n"
"NOTICE: In order to register a channel, you must have\n"
"first registered your nickname."
msgstr ""
+" \n"
+"AVISO: Para registar um canal, você deve primeiro\n"
+"registar o seu nickname."
-#, fuzzy, c-format
+#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
-"Note que qualquer canal não utilizado por %d dias\n"
-"(entenda como se nenhum usuário da lista de acesso\n"
-"desse canal entrar neste período de tempo) terá\n"
-"automaticamente cancelado o seu registro."
+" \n"
+"Observe que qualquer canal que não for usado por %lu dias\n"
+"(ou seja, no qual nenhum usuário na lista de acesso do canal entrar\n"
+"durante esse período de tempo) será automaticamente descartado."
#, c-format
msgid ""
" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
+"See the %s command (%s HELP ACCESS) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"
msgstr ""
+" \n"
+"Consulte o comando %s (%s HELP ACCESS) para\n"
+"obter informações sobre como conceder um subconjunto desses privilégios\n"
+"a outros usuários do canal.\n"
-#, fuzzy
msgid ""
" \n"
"Services Operators can also drop any nickname without needing\n"
"to identify for the nick, and may view the access list for\n"
"any nickname."
msgstr ""
-"Os Administradores dos Services podem ainda usar o DROP em qualquer nick\n"
-"sem ser necessário se identificar como dono dele, e podem ver a lista de\n"
-"acesso de qualquer nick (/msg %s ACCESS LIST nick)."
+" \n"
+"Os Operadores de Serviços também podem descartar qualquer nickname\n"
+"sem precisar se identificar para o nickname e podem visualizar a lista\n"
+"de acesso de qualquer nickname."
-#, fuzzy
msgid ""
" \n"
"Services Operators can also, depending on their access drop\n"
@@ -1149,10 +975,9 @@ msgid ""
"lists and settings for any channel."
msgstr ""
" \n"
-"Os Administradores dos Services podem também usar o comando\n"
-"DROP mesmo sem se identificarem como donos do canal, e podem\n"
-"também ver as listas de acesso, AKICK, e níveis de qualquer\n"
-"canal."
+"Os Operadores de Serviços também podem, dependendo do\n"
+"seu acesso, descartar qualquer canal, visualizar (e modificar)\n"
+"o acesso, os níveis e as listas de akick e configurações de qualquer canal."
msgid ""
" \n"
@@ -1161,8 +986,13 @@ msgid ""
"be removed after the given time. Set to 0 to disable bans from\n"
"automatically expiring."
msgstr ""
+" \n"
+"Define o tempo em que os bans de bot expiram. Se ativado quaisquer\n"
+"banimentos feitos por bots, como kicker de flood, kicker de palavrões, etc,\n"
+"serão automaticamente removidos após o tempo determinado. Defina como 0\n"
+"para impedir que os banimentos expirem automaticamente."
-#, fuzzy, c-format
+#, c-format
msgid ""
" \n"
"The %s ADD command adds the given nickname to the\n"
@@ -1183,41 +1013,24 @@ msgid ""
"The %s CLEAR command clears all entries of the\n"
"%s list."
msgstr ""
-"Sintaxe: HOP canal ADD nick\n"
-" HOP canal DEL {nick | entrada | lista-entradas}\n"
-" HOP canal LIST [máscara | lista-entradas]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Mantém a lista de HOP (HalfOP) para um canal. A lista\n"
-"de HOP dá a um usuário o direito de receber HalfOP\n"
-"automaticamente ao entrar no canal.\n"
-"\n"
-"O comando HOP ADD adiciona o nick fornecido à lista de HOP.\n"
-"\n"
-"O comando HOP DEL remove o nick fornecido da lista de HOP.\n"
-"Se uma lista de números de entrada é fornecida, essas entradas\n"
-"são deletadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"O comando HOP LIST exibe a lista de HOP. Se uma máscara\n"
-"é fornecida, apenas as entradas que combinarem com ela serão\n"
-"mostradas. Se uma lista de números de entrada é fornecida,\n"
-"apenas essas entradas são mostradas; por exemplo:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Lista as entradas de HOP numeradas de 2 a 5 e de\n"
-" 7 a 9.\n"
-"\n"
-"O comando HOP CLEAR remove todas as entradas da lista de HOP.\n"
-"\n"
-"Os comandos HOP ADD, HOP DEL e HOP LIST são limitados\n"
-"aos AOPs ou acima, enquanto o comando HOP CLEAR pode ser usado\n"
-"apenas pelo Fundador do canal.\n"
-"\n"
-"Este comando pode ter sido desabilitado para seu canal\n"
-"e, nesse caso, você precisa usar a lista de acesso. Veja\n"
-"/msg %s HELP ACCESS para informações sobre a lista\n"
-"de acesso, e /msg %s HELP SET XOP para saber como\n"
-"escolher entre a lista de acesso e o sistema de listas xOP."
+" \n"
+"O comando %s ADD adiciona o apelido fornecido à\n"
+"lista %s.\n"
+" \n"
+"O comando %s DEL remove o nick fornecido da\n"
+"lista %s. Se for fornecida uma lista de números de entradas, essas\n"
+"entradas serão excluídas. (Veja o exemplo para LIST abaixo.)\n"
+" \n"
+"O comando %s LIST exibe a lista %s. Se\n"
+"uma máscara wildcard for fornecida, somente as entradas correspondentes à\n"
+"máscara serão exibidas. Se for fornecida uma lista de números de entradas,\n"
+"apenas essas entradas serão mostradas; por exemplo:\n"
+" %s #canal LIST 2-5,7-9\n"
+" Lista as entradas %s numeradas de 2 a 5 e\n"
+" de 7 a 9.\n"
+" \n"
+"O comando %s CLEAR limpa todas as entradas da\n"
+"lista %s."
#, c-format
msgid ""
@@ -1241,8 +1054,26 @@ msgid ""
"The AKICK CLEAR command clears all entries of the\n"
"akick list."
msgstr ""
+" \n"
+"O comando AKICK DEL remove o nick ou máscara\n"
+"da lista AutoKick. No entanto, isso não remove quaisquer\n"
+"bans colocados por um AutoKick; aqueles devem ser removidos\n"
+"manualmente.\n"
+" \n"
+"O comando AKICK LIST exibe a lista do AutoKick ou,\n"
+"opcionalmente, apenas as entradas do AutoKick que correspondem à\n"
+"máscara fornecida.\n"
+" \n"
+"O comando AKICK VIEW é uma versão mais detalhada do\n"
+"comando AKICK LIST.\n"
+" \n"
+"O comando AKICK ENFORCE faz com que %s imponha a\n"
+"lista AKICK atual removendo os usuários que correspondem a uma\n"
+"máscara AKICK.\n"
+" \n"
+"O comando AKICK CLEAR impa todas as entradas da\n"
+"lista de akick."
-#, fuzzy
msgid ""
" \n"
"The AKILL DEL command removes the given mask from the\n"
@@ -1264,43 +1095,26 @@ msgid ""
" \n"
"AKILL CLEAR clears all entries of the AKILL list."
msgstr ""
-"Sintaxe: HOP canal ADD nick\n"
-" HOP canal DEL {nick | entrada | lista-entradas}\n"
-" HOP canal LIST [máscara | lista-entradas]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Mantém a lista de HOP (HalfOP) para um canal. A lista\n"
-"de HOP dá a um usuário o direito de receber HalfOP\n"
-"automaticamente ao entrar no canal.\n"
-"\n"
-"O comando HOP ADD adiciona o nick fornecido à lista de HOP.\n"
-"\n"
-"O comando HOP DEL remove o nick fornecido da lista de HOP.\n"
-"Se uma lista de números de entrada é fornecida, essas entradas\n"
-"são deletadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"O comando HOP LIST exibe a lista de HOP. Se uma máscara\n"
-"é fornecida, apenas as entradas que combinarem com ela serão\n"
-"mostradas. Se uma lista de números de entrada é fornecida,\n"
-"apenas essas entradas são mostradas; por exemplo:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Lista as entradas de HOP numeradas de 2 a 5 e de\n"
-" 7 a 9.\n"
-"\n"
-"O comando HOP CLEAR remove todas as entradas da lista de HOP.\n"
-"\n"
-"Os comandos HOP ADD, HOP DEL e HOP LIST são limitados\n"
-"aos AOPs ou acima, enquanto o comando HOP CLEAR pode ser usado\n"
-"apenas pelo Fundador do canal.\n"
-"\n"
-"Este comando pode ter sido desabilitado para seu canal\n"
-"e, nesse caso, você precisa usar a lista de acesso. Veja\n"
-"/msg %s HELP ACCESS para informações sobre a lista\n"
-"de acesso, e /msg %s HELP SET XOP para saber como\n"
-"escolher entre a lista de acesso e o sistema de listas xOP."
+" \n"
+"O comando AKILL DEL remove a máscara fornecida da lista\n"
+"AKILL e ela estiver presente. Se for fornecida uma lista de números\n"
+"de entradas, essas entradas serão excluídas. (Veja o exemplo para LIST\n"
+"abaixo.)\n"
+" \n"
+"O comando AKILL LIST exibe a lista AKILL.\n"
+"Se uma máscara wildcard for fornecida, somente as entradas correspondentes à\n"
+"máscara serão exibidas. Se for fornecida uma lista de números de entradas,\n"
+"apenas essas entradas serão mostradas; por exemplo:\n"
+" AKILL LIST 2-5,7-9\n"
+" Lista as entradas AKILL numeradas de 2 a 5\n"
+" e de 7 a 9.\n"
+" \n"
+"AKILL VIEW é uma versão mais detalhada de AKILL LIST, e\n"
+"mostrará quem adicionou um AKILL, a data em que foi adicionado e quando\n"
+"expira, bem como a máscara user@host/ip e o motivo.\n"
+" \n"
+"AKILL CLEAR limpa todas as entradas da lista AKILL."
-#, fuzzy
msgid ""
" \n"
"The SNLINE DEL command removes the given mask from the\n"
@@ -1322,43 +1136,26 @@ msgid ""
" \n"
"SNLINE CLEAR clears all entries of the SNLINE list."
msgstr ""
-"Sintaxe: HOP canal ADD nick\n"
-" HOP canal DEL {nick | entrada | lista-entradas}\n"
-" HOP canal LIST [máscara | lista-entradas]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Mantém a lista de HOP (HalfOP) para um canal. A lista\n"
-"de HOP dá a um usuário o direito de receber HalfOP\n"
-"automaticamente ao entrar no canal.\n"
-"\n"
-"O comando HOP ADD adiciona o nick fornecido à lista de HOP.\n"
-"\n"
-"O comando HOP DEL remove o nick fornecido da lista de HOP.\n"
-"Se uma lista de números de entrada é fornecida, essas entradas\n"
-"são deletadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"O comando HOP LIST exibe a lista de HOP. Se uma máscara\n"
-"é fornecida, apenas as entradas que combinarem com ela serão\n"
-"mostradas. Se uma lista de números de entrada é fornecida,\n"
-"apenas essas entradas são mostradas; por exemplo:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Lista as entradas de HOP numeradas de 2 a 5 e de\n"
-" 7 a 9.\n"
-"\n"
-"O comando HOP CLEAR remove todas as entradas da lista de HOP.\n"
-"\n"
-"Os comandos HOP ADD, HOP DEL e HOP LIST são limitados\n"
-"aos AOPs ou acima, enquanto o comando HOP CLEAR pode ser usado\n"
-"apenas pelo Fundador do canal.\n"
-"\n"
-"Este comando pode ter sido desabilitado para seu canal\n"
-"e, nesse caso, você precisa usar a lista de acesso. Veja\n"
-"/msg %s HELP ACCESS para informações sobre a lista\n"
-"de acesso, e /msg %s HELP SET XOP para saber como\n"
-"escolher entre a lista de acesso e o sistema de listas xOP."
+" \n"
+"O comando SNLINE DEL remove a máscara fornecida da lista\n"
+"SNLINE se ela estiver presente. Se for fornecida uma lista de números\n"
+"de entradas, essas entradas serão excluídas. (Veja o exemplo para LIST\n"
+"abaixo.)\n"
+" \n"
+"O comando SNLINE LIST exibe a lista SNLINE.\n"
+"Se uma máscara wildcard for fornecida, somente as entradas correspondentes\n"
+"à máscara serão exibidas. Se for fornecida uma lista de números de entradas,\n"
+"apenas essas entradas serão mostradas; por exemplo:\n"
+" SNLINE LIST 2-5,7-9\n"
+" Lista as entradas SNLINE numeradas de 2 a 5 e de 7\n"
+" a 9.\n"
+" \n"
+"SNLINE VIEW é uma versão mais detalhada de SNLINE LIST, e\n"
+"e mostrará quem adicionou um SNLINE, a data em que foi adicionado e quando\n"
+"expira, bem como a máscara do nome real e o motivo.\n"
+" \n"
+"SNLINE CLEAR limpa todas as entradas da lista SNLINE."
-#, fuzzy
msgid ""
" \n"
"The SQLINE DEL command removes the given mask from the\n"
@@ -1380,761 +1177,727 @@ msgid ""
" \n"
"SQLINE CLEAR clears all entries of the SQLINE list."
msgstr ""
-"Sintaxe: HOP canal ADD nick\n"
-" HOP canal DEL {nick | entrada | lista-entradas}\n"
-" HOP canal LIST [máscara | lista-entradas]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Mantém a lista de HOP (HalfOP) para um canal. A lista\n"
-"de HOP dá a um usuário o direito de receber HalfOP\n"
-"automaticamente ao entrar no canal.\n"
-"\n"
-"O comando HOP ADD adiciona o nick fornecido à lista de HOP.\n"
-"\n"
-"O comando HOP DEL remove o nick fornecido da lista de HOP.\n"
-"Se uma lista de números de entrada é fornecida, essas entradas\n"
-"são deletadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"O comando HOP LIST exibe a lista de HOP. Se uma máscara\n"
-"é fornecida, apenas as entradas que combinarem com ela serão\n"
-"mostradas. Se uma lista de números de entrada é fornecida,\n"
-"apenas essas entradas são mostradas; por exemplo:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Lista as entradas de HOP numeradas de 2 a 5 e de\n"
-" 7 a 9.\n"
-"\n"
-"O comando HOP CLEAR remove todas as entradas da lista de HOP.\n"
-"\n"
-"Os comandos HOP ADD, HOP DEL e HOP LIST são limitados\n"
-"aos AOPs ou acima, enquanto o comando HOP CLEAR pode ser usado\n"
-"apenas pelo Fundador do canal.\n"
-"\n"
-"Este comando pode ter sido desabilitado para seu canal\n"
-"e, nesse caso, você precisa usar a lista de acesso. Veja\n"
-"/msg %s HELP ACCESS para informações sobre a lista\n"
-"de acesso, e /msg %s HELP SET XOP para saber como\n"
-"escolher entre a lista de acesso e o sistema de listas xOP."
+" \n"
+"O comando SQLINE DEL remove a máscara fornecida da lista\n"
+"SQLINE, se estiver presente. Se for fornecida uma lista de números\n"
+"de entradas, essas entradas serão excluídas. (Veja o exemplo para LIST\n"
+"abaixo.)\n"
+" \n"
+"O comando SQLINE LIST exibe a lista SQLINE.\n"
+"Se uma máscara wildcard for fornecida, somente as entradas correspondentes à\n"
+"máscara serão exibidas. Se for fornecida uma lista de números de entradas,\n"
+"apenas essas entradas serão mostradas; por exemplo:\n"
+" SQLINE LIST 2-5,7-9\n"
+" Lista as entradas SQLINE numeradas de 2 a 5 e de 7\n"
+" a 9.\n"
+" \n"
+"SQLINE VIEW é uma versão mais detalhada de SQLINE LIST, e\n"
+"mostrará quem adicionou um SQLINE, a data em que foi adicionado e quando\n"
+"expira, bem como a máscara e o motivo.\n"
+" \n"
+"SQLINE CLEAR limpa todas as entradas da lista SQLINE."
-#, fuzzy
msgid ""
" \n"
"This option makes a channel unassignable. If a bot\n"
"is already assigned to the channel, it is unassigned\n"
"automatically when you enable it."
msgstr ""
-"Sintaxe: SET canal NOBOT {ON|OFF}\n"
-"\n"
-"Este comando faz com que um determinado bot não possa ser\n"
-"associado a um canal. Se já houver um bot associado a este\n"
-"canal, este será automaticamente desassociado quando você\n"
-"ativar essa opção."
+" \n"
+"Esta opção torna um canal inatribuível. Se um bot\n"
+"á estiver atribuído ao canal, sua atribuição será cancelada\n"
+"automaticamente quando você o ativar."
-#, fuzzy
msgid ""
" \n"
"This option prevents a bot from being assigned to a\n"
"channel by users that aren't IRC Operators."
msgstr ""
-"Sintaxe: SET nick PRIVATE {ON|OFF}\n"
-"\n"
-"Esta opção previne um bot de ser associado a um canal\n"
-"por usuários que não sejam Operadores de IRC."
+" \n"
+"Esta opção evita que um bot seja atribuído a um\n"
+"canal por usuários que não sejam Operadores de IRC."
#, c-format
msgid ""
" \n"
-"Type %s%s HELP command for help on any of the\n"
+"Type %s HELP command for help on any of the\n"
"above commands."
msgstr ""
+" \n"
+"Digite %s HELP comando para obter ajuda sobre\n"
+"qualquer um dos comandos acima."
#, c-format
msgid " %s is online using this oper block."
-msgstr ""
+msgstr " %s está online usando este bloco de oper."
#, c-format
msgid " Command %s on %s is linked to %s"
-msgstr ""
+msgstr " O comando %s em %s está vinculado a %s"
-#, fuzzy, c-format
+#, c-format
msgid " Providing service: %s"
-msgstr "Comando fornecido: //msg %s %s"
+msgstr " Fornecendo serviço: %s"
msgid " This oper is configured in the configuration file."
-msgstr ""
+msgstr " Este oper está configurado no arquivo de configuração."
#, c-format
msgid " Loaded at: %p"
-msgstr ""
+msgstr " Carregado em: %p"
#, c-format
msgid " but %s mysteriously dematerialized."
-msgstr ""
-
-#, c-format
-msgid ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
+msgstr " mas %s misteriosamente se desmaterializou."
-#, fuzzy
msgid "\"Jupiter\" a server"
-msgstr " JUPE Jupa um servidor"
+msgstr "\"Júpiter\" um servidor"
-#, fuzzy, c-format
+#, c-format
msgid "%-8s %s"
-msgstr "%-20s %s@%s"
+msgstr "%-8s %s"
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr "%2d %-16s letras: %s, palavras: %s, linhas: %s, smileys: %s, ações: %s"
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr ""
+msgid "%b %d %Y %H:%M:%S %Z"
+msgstr "%b %d %Y %H:%M:%S %Z"
#, c-format
msgid "%c is an unknown status mode."
-msgstr ""
+msgstr "%c é um modo de status desconhecido."
-#, fuzzy, c-format
+#, c-format
msgid "%c%c is not locked on %s."
-msgstr "%s não é notificado de novos memos."
+msgstr "%c%c não está bloqueado em %s."
-#, fuzzy, c-format
+#, c-format
msgid "%c%c%s has been unlocked from %s."
-msgstr "Nick %s has been ungrouped from %s."
+msgstr "%c%c%s foi desbloqueado de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%d access entries from %s have been cloned to %s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s"
+msgstr "%d entradas de acesso de %s foram clonadas para %s."
#, c-format
msgid "%d bots available."
msgstr "%d bots disponíveis."
-#, fuzzy, c-format
+#, c-format
msgid "%d modules loaded."
msgstr "%d módulos carregados."
-#, fuzzy, c-format
-msgid "%d nickname(s) in the group."
-msgstr "%d nicks no grupo."
-
#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
-msgstr ""
+msgstr "%lu nicks são armazenados no banco de dados, usando %.2Lf kB de memória."
-#, fuzzy, c-format
+#, c-format
msgid "%s %s list is empty."
-msgstr "Lista de AOP do canal %s está vazia."
+msgstr "A lista %s de %s está vazia."
-#, fuzzy, c-format
+#, c-format
msgid "%s (%d kick(s) to ban)"
-msgstr " Kick por negrito: %s (%d kick(s) para banir)"
+msgstr "%s (%d kick(s) para banir)"
-#, fuzzy, c-format
+#, c-format
msgid "%s (%d kick(s) to ban; %d lines in %ds)"
-msgstr " Kick por flood: %s (%d kick(s) para banir; %d linhas em %ds)"
+msgstr "%s (%d kick(s) para banir; %d linhas em %ds)"
-#, fuzzy, c-format
+#, c-format
msgid "%s (%d kick(s) to ban; %d times)"
-msgstr " Kick por repetição: %s (%d kick(s) para banir; %d vezes)"
+msgstr "%s (%d kick(s) para banir; %d vezes)"
-#, fuzzy, c-format
+#, c-format
msgid "%s (%d kick(s) to ban; minimum %d/%d%%)"
-msgstr " Kick por Caps: %s (%d kick(s) para banir; mínimo %d/%d%%)"
+msgstr "%s (%d kick(s) para banir; mínimo %d/%d%%)"
-#, fuzzy, c-format
+#, c-format
msgid "%s (%d lines in %ds)"
-msgstr " %s (expira em %s)"
+msgstr "%s (%d linhas em %ds)"
#, c-format
msgid "%s (%d times)"
-msgstr ""
+msgstr "%s (%d vezes)"
#, c-format
msgid "%s (%s) was kicked from %s (\"%s\") %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi kickado de %s (\"%s\") há %s atrás%s"
#, c-format
msgid "%s (%s) was kicked from a secret channel %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi kickado de um canal secreto há %s atrás%s"
#, c-format
msgid "%s (%s) was last seen changing nick from %s to %s %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi visto pela última vez mudando de nick de %s para %s %s atrás%s"
#, c-format
msgid "%s (%s) was last seen changing nick to %s %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi visto pela última vez mudando de nick para %s %s atrás%s"
#, c-format
msgid "%s (%s) was last seen connecting %s ago (%s)%s"
-msgstr ""
+msgstr "%s (%s) foi visto pela última vez conectando-se há %s atrás (%s)%s"
#, c-format
msgid "%s (%s) was last seen joining %s %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi visto pela última vez entrando em %s há %s atrás%s"
#, c-format
msgid "%s (%s) was last seen joining a secret channel %s ago%s"
-msgstr ""
+msgstr "%s (%s) oi visto pela última vez entrando em um canal secreto há %s atrás%s"
#, c-format
msgid "%s (%s) was last seen parting %s %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi visto pela última vez saindo de %s há %s atrás%s"
#, c-format
msgid "%s (%s) was last seen parting a secret channel %s ago%s"
-msgstr ""
+msgstr "%s (%s) foi visto pela última vez saindo de um canal secreto há %s atrás%s"
#, c-format
msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
-msgstr ""
+msgstr "%s (%s) foi visto saindo pela última vez (%s) há %s atrás (%s)."
-#, fuzzy, c-format
+#, c-format
msgid "%s (minimum %d/%d%%)"
-msgstr " Kick por Caps: %s (mínimo %d/%d%%)"
+msgstr "%s (mínimo %d/%d%%)"
#, c-format
msgid "%s access list is empty."
-msgstr "Lista de acesso do canal %s está vazia."
+msgstr "A lista de acesso %s está vazia."
-#, fuzzy, c-format
+#, c-format
msgid "%s added to %s's auto join list."
-msgstr "%s adicionado à lista de akick do %s."
+msgstr "%s adicionado à lista de auto join de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s already exists."
-msgstr "Bot %s já existe."
+msgstr "%s já existe."
#, c-format
msgid "%s autokick list is empty."
-msgstr "Lista de akick do %s vazia."
+msgstr "A lista de autokick do %s está vazia."
#, c-format
msgid "%s bad words list is empty."
-msgstr "Lista de palvrões do %s está vazia."
+msgstr "A lista de palavrões de %s está vazia."
-#, fuzzy, c-format
+#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr "%s não pode mais ser adicionado às listas de acesso de canais."
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr "%s agora pode ser adicionado às listas de acesso de canais."
+
+#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
-msgstr "%s não pode ser o successor do canal %s porque ele é o founder."
+msgstr "%s não pode ser o sucessor do canal %s pois é o fundador."
#, c-format
msgid "%s commands:"
-msgstr "Comandos do %s:"
+msgstr "Comandos %s:"
#, c-format
msgid "%s coverage is too wide; Please use a more specific mask."
-msgstr ""
+msgstr "A cobertura de %s é muito ampla; Por favor, use uma máscara mais específica."
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s possui atualmente %d memos, dos quais %d não foram lidos."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr "%s atualmente possui %zu memorandos, dos quais %zu não foram lidos."
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s possui atualmente %d memos, dos quais 1 não foi lido."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr "%s atualmente possui %zu memorandos, dos quais 1 não foi lido."
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s possui atualmente %d memos."
+msgid "%s currently has %zu memos."
+msgstr "%s atualmente tem %zu memorandos."
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s possui atualmente %d memos; dos quais nenhum foi lido."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr "%s atualmente tem %zu memorandos; todos eles não foram lidos."
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
-msgstr "%s possui atualmente 1 memo, e ainda não foi lido."
+msgstr "%s tem atualmente 1 memorando, e ainda não foi lido."
#, c-format
msgid "%s currently has 1 memo."
-msgstr "%s possui atualmente 1 memo."
+msgstr "%s atualmente tem 1 memorando."
#, c-format
msgid "%s currently has no memos."
-msgstr "%s não possui nenhum memo atualmente."
+msgstr "%s atualmente não tem memorandos."
-#, fuzzy, c-format
+#, c-format
msgid "%s deleted from the %s forbid list."
-msgstr "%s removido da lista de palavrões do %s."
+msgstr "%s excluído da lista de proibições de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s for %s set to %s."
-msgstr "vhost de %s ajustado para %s."
+msgstr "%s para %s definido como %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s for %s unset."
-msgstr "Successor do canal %s removido."
+msgstr "%s para %s não definido."
#, c-format
msgid "%s had an invalid key specified, and was thus ignored."
-msgstr ""
+msgstr "%s tinha uma chave inválida especificada e foi ignorada."
#, c-format
msgid "%s has no memo limit."
-msgstr "%s não possui limite de memos."
+msgstr "%s não tem limite de memorandos."
-#, fuzzy, c-format
+#, c-format
msgid "%s has no memos."
-msgstr "%s não possui limite de memos."
+msgstr "%s não tem memorandos."
-#, fuzzy, c-format
+#, c-format
msgid "%s has no new memos."
-msgstr "%s não possui limite de memos."
+msgstr "%s não tem novos memorandos."
#, c-format
msgid "%s is %s"
msgstr "%s é %s"
-#, fuzzy, c-format
+#, c-format
msgid "%s is a Services Operator of type %s."
-msgstr "%s is a services operator of type %s."
+msgstr "%s é um Operador de Serviços do tipo %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s is a client on services."
-msgstr "%s está online neste momento."
+msgstr "%s é um cliente de serviços."
-#, fuzzy, c-format
+#, c-format
msgid "%s is a network service."
-msgstr "%s está online neste momento."
+msgstr "%s é um serviço de rede."
-#, fuzzy, c-format
+#, c-format
msgid "%s is already covered by %s."
-msgstr "%s já está coberto pelo AKILL %s."
+msgstr "%s já está coberto por %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s is already on %s's auto join list."
-msgstr "%s adicionado em sua lista de acesso."
+msgstr "%s já está na lista de auto join de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s is an unconfirmed nickname."
-msgstr "Este nick não irá expirar."
+msgstr "%s é um nickname não confirmado."
#, c-format
msgid ""
"%s is another way to modify the channel access list, similar to\n"
"the XOP and ACCESS methods."
msgstr ""
+"%s é outra forma de modificar a lista de acesso do canal, semelhante\n"
+"aos métodos XOP e ACCESS."
#, c-format
msgid "%s is currently online."
-msgstr "%s está online neste momento."
+msgstr "%s está on-line no momento."
#, c-format
msgid "%s is disabled"
-msgstr "%s está desativada"
+msgstr "%s está desabilitado"
#, c-format
msgid "%s is enabled"
-msgstr "%s está ativada"
+msgstr "%s está ativado"
-#, fuzzy, c-format
+#, c-format
msgid "%s is not a valid IP address."
-msgstr "%s não é um ban válido."
+msgstr "%s não é um endereço IP válido."
-#, fuzzy, c-format
+#, c-format
msgid "%s is not a valid command."
-msgstr "%s não é um ban válido."
+msgstr "%s não é um comando válido."
-#, fuzzy, c-format
+#, c-format
msgid "%s is not a valid logging method."
-msgstr "%s não é um ban válido."
+msgstr "%s não é um método de log válido."
#, c-format
msgid "%s is not notified of new memos."
-msgstr "%s não é notificado de novos memos."
+msgstr "%s não é notificado sobre novos memorandos."
#, c-format
msgid "%s is notified of new memos at logon and when they arrive."
-msgstr ""
-"%s é notificado de novos memos quando conecta e quando eles são enviados."
+msgstr "%s é notificado sobre novos memorandos no logon e quando eles chegam."
#, c-format
msgid "%s is notified of new memos at logon."
-msgstr "%s é notificado de novos memos quando conecta."
+msgstr "%s é notificado sobre novos memorandos no logon."
#, c-format
msgid "%s is notified when new memos arrive."
-msgstr "%s é notificado de novos memos quando eles são enviados."
+msgstr "%s é notificado quando novos memorandos chegam."
#, c-format
msgid "%s is on the channel right now (as %s)!"
-msgstr ""
+msgstr "%s está no canal agora (como %s)!"
-#, fuzzy, c-format
+#, c-format
msgid "%s is on the channel right now!"
-msgstr "%s desabilitado no canal %s."
+msgstr "%s está no canal agora!"
-#, fuzzy, c-format
+#, c-format
msgid "%s list for %s"
-msgstr "Lista de acesso para %s:"
+msgstr "Lista %s para %s"
-#, fuzzy, c-format
+#, c-format
msgid "%s list is empty."
-msgstr "Lista de AOP do canal %s está vazia."
+msgstr "A lista %s está vazia."
-#, fuzzy, c-format
+#, c-format
msgid "%s locked on %s."
-msgstr "%s não é notificado de novos memos."
+msgstr "%s bloqueado em %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s not found."
-msgstr "Nick %s não encontrado na lista de AOP do %s."
+msgstr "%s não encontrado."
#, c-format
msgid "%s settings:"
-msgstr ""
+msgstr "Configurações %s:"
#, c-format
msgid "%s was last seen here %s ago."
-msgstr ""
+msgstr "%s foi visto aqui pela última vez há %s atrás."
-#, fuzzy, c-format
+#, c-format
msgid "%s was not found on %s's auto join list."
-msgstr "%s não encontrado na lista de akick do %s."
+msgstr "%s não foi encontrado na lista de auto join de %s."
-#, fuzzy, c-format
+#, c-format
msgid "%s was removed from %s's auto join list."
-msgstr "%s removido da lista de akick do %s."
+msgstr "%s foi removido da lista de auto join de %s."
#, c-format
msgid "%s will not send you any notification of memos."
-msgstr "%s não irá mais notificá-lo de novos memos."
+msgstr "%s não enviará nenhuma notificação de memorandos."
#, c-format
msgid "%s will now notify you of memos when they are sent to you."
-msgstr ""
-"%s irá agora notificá-lo de novos memos quando eles lhe forem enviados."
+msgstr "%s agora irá notificá-lo sobre memorandos quando eles forem enviados para você."
#, c-format
-msgid ""
-"%s will now notify you of memos when you log on and when they are sent to "
-"you."
-msgstr ""
-"%s irá agora notificá-lo de novos memos quando você conectar, quando eles "
-"lhe forem enviados ou quando desativar o /AWAY."
+msgid "%s will now notify you of memos when you log on and when they are sent to you."
+msgstr "%s agora irá notificá-lo sobre memorandos quando você fizer logon e quando eles forem enviados para você."
#, c-format
msgid "%s will now notify you of memos when you log on or unset /AWAY."
-msgstr ""
-"%s irá agora notificá-lo de novos memos quando você conectar ou quando "
-"desativar o /AWAY."
+msgstr "%s agora irá notificá-lo sobre memorandos quando você fizer logon ou desmarcar /AWAY."
#, c-format
msgid "%s!%s@%s (%s) added to the bot list."
msgstr "%s!%s@%s (%s) adicionado à lista de bots."
-#, fuzzy, c-format
-msgid "%s's access list is empty."
-msgstr "Lista de acesso do canal %s está vazia."
-
-#, fuzzy, c-format
+#, c-format
msgid "%s's auto join list is empty."
-msgstr "Lista de akick do %s vazia."
+msgstr "A lista de auto join de %s está vazia."
-#, fuzzy, c-format
+#, c-format
msgid "%s's auto join list:"
-msgstr " AKICK Faz a manutenção da Lista de Autokick"
+msgstr "Lista de auto join de %s:"
-#, fuzzy, c-format
+#, c-format
msgid "%s's certificate list is empty."
-msgstr "Sua lista de acesso está vazia."
+msgstr "A lista de certificados de %s está vazia."
#, c-format
msgid "%s's memo limit is %d, and may not be changed."
-msgstr "Limite de memos para %s é de %d, e não pode ser alterado."
+msgstr "O limite de memorandos de %s é %d, e não pode ser alterado."
#, c-format
msgid "%s's memo limit is %d."
-msgstr "Limite de memos para %s é de %d."
+msgstr "O limite de memorandos de %s é %d."
+
+#, c-format
+msgid "%zu nickname(s) in the group."
+msgstr "%zu nickname(s) no grupo."
#, c-format
msgid "(%s ago)"
-msgstr ""
+msgstr "(%s atrás)"
#, c-format
msgid "(%s from now)"
-msgstr ""
+msgstr "(%s a partir de agora)"
msgid "(Split)"
-msgstr ""
+msgstr "(Split)"
#, c-format
msgid "(by %s on %s) %s"
-msgstr ""
+msgstr "(por %s em %s) %s"
-#, fuzzy
msgid "(disabled)"
-msgstr "%s está ativada"
+msgstr "(desabilitado)"
msgid "(founder only)"
-msgstr ""
+msgstr "(somente fundador)"
msgid "(now)"
-msgstr ""
+msgstr "(agora)"
msgid "* AKILL any new clients connecting"
-msgstr "* AKILLA quaisquer novos clientes conectando"
+msgstr "* AKILL quaisquer novos clientes que se conectem"
-#, fuzzy, c-format
+#, c-format
msgid "* Force channel modes (%s) to be set on all channels"
-msgstr "* Força os Modos de Canal (%s) a serem setados em todos os canais"
+msgstr "* Força que os modos de canal (%s) sejam definidos em todos os canais"
-#, fuzzy
msgid "* Ignore non-opers with a message"
-msgstr "* Ignora quaisquer não-opers com mensagem"
+msgstr "* Ignora não-opers com uma mensagem"
-#, fuzzy
msgid "* Kill any new clients connecting"
-msgstr "* Killa quaisquer NOVOS clientes conectando"
+msgstr "* Kill todos os novos clientes que se conectarem"
-#, fuzzy
msgid "* No mode lock changes"
-msgstr "* Impedida a mudança de MLOCK"
+msgstr "* Nenhuma alteração de bloqueio de modo"
msgid "* No new channel registrations"
-msgstr "* Impedido o registro de novos canais"
+msgstr "* Sem novos registos de canais"
msgid "* No new memos sent"
-msgstr "* Impede o envio de novos memos"
+msgstr "* Nenhum novo memorando enviado"
msgid "* No new nick registrations"
-msgstr "* Impedido o registro de novos nicks"
+msgstr "* Nenhum novo registo de nick"
msgid "* Silently ignore non-opers"
-msgstr "* Silenciosamente ignora não-opers"
+msgstr "* Ignore silenciosamente os não-opers"
#, c-format
msgid "* Use the reduced session limit of %d"
-msgstr "* Usa o limite de sessões reduzido de %d"
+msgstr "* Use o limite de sessão reduzido de %d"
#, c-format
msgid ", but %s mysteriously dematerialized."
-msgstr ""
+msgstr ", mas %s se desmaterializou misteriosamente."
-#, fuzzy, c-format
+#, c-format
msgid ". %s is still online."
-msgstr "%s está online neste momento."
+msgstr ". %s ainda está on-line."
msgid "<unknown>"
-msgstr ""
+msgstr "<unknown>"
-#, fuzzy, c-format
-msgid ""
-"A confirmation e-mail has been sent to %s. Follow the instructions in it to "
-"change your e-mail address."
-msgstr ""
-"O passcode foi enviado para %s, por favor digite /msg %s confirm <passcode> "
-"para completar o registro."
+#, c-format
+msgid "A confirmation email has been sent to %s. Follow the instructions in it to change your email address."
+msgstr "Um email de confirmação foi enviado para %s. Siga as instruções nele para alterar seu endereço de email."
msgid "A massmemo has been sent to all registered users."
-msgstr "Uma mensagem global foi enviada a todos os usuários registrados."
+msgstr "Um memo em massa foi enviado a todos os usuários registados."
-msgid ""
-"A memo informing the user will also be sent, which includes the reason for "
-"the rejection if supplied."
-msgstr ""
+msgid "A memo informing the user will also be sent, which includes the reason for the rejection if supplied."
+msgstr "Será também enviado um memorando informando o usuário, que incluirá o motivo da rejeição, caso fornecido."
msgid "A memo informing the user will also be sent."
-msgstr ""
+msgstr "Um memorando informando o usuário também será enviado."
#, c-format
msgid ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
+"A notification memo has been sent to %s informing them you have\n"
+"read their memo."
msgstr ""
-"Um memo de notificação foi enviado para %s informando que você leu seu memo."
+"Um memo de notificação foi enviado para %s informando que\n"
+"você leu o memorando."
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr ""
+msgid "A vhost must be in the format of a valid hostname."
+msgstr "Um vhost deve estar no formato de um nome de host válido."
-msgid "A vHost must be in the format of a valid hostname."
-msgstr ""
+msgid "A vident must be in the format of a valid ident."
+msgstr "Um vident deve estar no formato de uma ident válida."
-#, fuzzy
msgid "ADD expiry {nick|mask} [reason]"
-msgstr "BAN #channel nick [reason]"
+msgstr "ADD expiração {nick|máscara} [razão]"
+
+msgid "ADD message"
+msgstr "ADD mensagem"
msgid "ADD oper type"
-msgstr ""
+msgstr "ADD oper tipo"
-#, fuzzy
msgid "ADD target info"
-msgstr "GROUP alvo senha"
+msgstr "ADD alvo info"
msgid "ADD text"
-msgstr ""
+msgstr "ADD texto"
-#, fuzzy
msgid "ADD [+expiry] mask limit reason"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
+msgstr "ADD [+expiração] máscara limite razão"
-#, fuzzy
msgid "ADD [nickname] channel [key]"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
-
-#, fuzzy
-msgid "ADD [nickname] mask"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
+msgstr "ADD [nickname] canal [chave]"
-#, fuzzy
msgid "ADD [nickname] [fingerprint]"
-msgstr "FORBID nick motivo"
+msgstr "ADD [nickname] [impressão-digital]"
-#, fuzzy
msgid "ADD [+expiry] mask reason"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
+msgstr "ADD [+expiração] máscara razão"
-#, fuzzy
msgid "ADD [+expiry] mask:reason"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
+msgstr "ADD [+expiração] máscara:razão"
-#, fuzzy
msgid "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiry] entry reason"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
+msgstr "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiração] entrada razão"
msgid "ADDIP server.name ip"
-msgstr ""
+msgstr "ADDIP nome.do.servidor ip"
msgid "ADDSERVER server.name [zone.name]"
-msgstr ""
+msgstr "ADDSERVER nome.do.servidor [nome.da.zona]"
msgid "ADDZONE zone.name"
-msgstr ""
+msgstr "ADDZONE nome.da.zona"
#, c-format
msgid "AKICK ENFORCE for %s complete; %d users were affected."
-msgstr "AKICK ENFORCE para %s terminado; %d usuários afetados."
+msgstr "AKICK ENFORCE para %s completado; %d usuários foram afetados."
-#, fuzzy
msgid "AKILL all users on a specific channel"
-msgstr " CHANKILL AKILL todos os usuários de um canal específico"
+msgstr "AKILL todos os usuários em um canal específico"
msgid "AKILL list is empty."
-msgstr "A lista de AKILL está vazia."
+msgstr "A lista AKILL está vazia."
-#, fuzzy
msgid "AMSG kicker"
-msgstr " Kick por Caps: %s"
+msgstr "Kicker AMSG"
-#, fuzzy
msgid "Access"
-msgstr "Lista de acesso:"
+msgstr "Acesso"
-#, fuzzy
msgid "Access denied."
-msgstr "Lista de acesso:"
+msgstr "Acesso negado."
-#, fuzzy, c-format
+#, c-format
msgid "Access for %s on %s:"
-msgstr "Nível de acesso para %s no %s alterado para %d."
+msgstr "Acesso para %s em %s:"
-#, fuzzy, c-format
+#, c-format
msgid "Access level must be between %d and %d inclusive."
-msgstr "O nível deve ser entre %d e %d inclusive."
+msgstr "O nível de acesso deve estar entre %d e %d inclusive."
msgid "Access level must be non-zero."
msgstr "O nível de acesso deve ser diferente de zero."
#, c-format
msgid "Access level settings for channel %s:"
-msgstr "Opções de nível de acesso para o canal %s:"
+msgstr "Configurações de nível de acesso para o canal %s:"
#, c-format
msgid "Access levels for %s reset to defaults."
-msgstr "Níveis de acesso para o %s redefinidos para o padrão."
+msgstr "Os níveis de acesso para %s foram redefinidos para os padrões."
-#, fuzzy, c-format
+#, c-format
msgid "Access list for %s:"
-msgstr "Lista de acesso para %s:"
+msgstr "Lista de acesso para %s:"
#, c-format
-msgid ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-msgstr ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
+msgid "Access to this command requires the permission %s to be present in your opertype."
+msgstr "O acesso a este comando requer que a permissão %s esteja presente no seu opertype."
+
+msgid "Account"
+msgstr "Conta"
#, c-format
-msgid ""
-"Account %s has already reached the maximum number of simultaneous logins "
-"(%u)."
-msgstr ""
+msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
+msgstr "A conta %s já atingiu o número máximo de logins simultâneos (%u)."
-#, fuzzy
-msgid "Activate security features"
-msgstr " SECURE Ativa os recursos de segurança do %s"
+msgid "Account id"
+msgstr "ID da conta"
-msgid "Activate the requested vHost for the given nick."
-msgstr ""
+msgid "Account registered"
+msgstr "Conta registada"
+
+msgid "Accounts can not be registered right now. Please try again later."
+msgstr "As contas não podem ser registadas no momento. Por favor, tente novamente mais tarde."
+
+msgid "Activate the requested vhost for the given nick."
+msgstr "Ative o vhost solicitado para o nick fornecido."
-#, fuzzy
msgid ""
"Activates the vhost currently assigned to the nick in use.\n"
"When you use this command any user who performs a /whois\n"
"on you will see the vhost instead of your real host/IP address."
msgstr ""
-"Sintaxe: ON\n"
-"Ativa o vhost atualmente associado ao nick em uso.\n"
-"Quando você usa este comando, qualquer usuário que faça um /whois\n"
-"em você irá ver o vhost em vez do seu endereço IP real/encriptado."
+"Ativa o vhost atualmente atribuído ao nick em uso.\n"
+"Quando você usa este comando, qualquer usuário que executa um /whois\n"
+"em você verá o vhost em vez do seu host/endereço IP real."
-#, fuzzy
msgid "Activates your assigned vhost"
-msgstr " ON Ativa seu vHost associado"
+msgstr "Ativa seu vhost atribuído"
msgid ""
"Add or delete oper information for a given nick or channel.\n"
"This will show to opers in the respective info command for\n"
"the nick or channel."
msgstr ""
+"Adicione ou exclua informações de oper para um determinado nick ou canal.\n"
+"Isto será mostrado aos operadores no respectivo comando info\n"
+"do nick ou canal."
#, c-format
msgid "Added IP %s to %s."
-msgstr ""
+msgstr "Adicionado IP %s a %s."
#, c-format
msgid "Added a forbid on %s of type %s to expire on %s."
-msgstr ""
+msgstr "Adicionada uma proibição de %s do tipo %s para expirar em %s."
-#, fuzzy, c-format
+#, c-format
msgid "Added info to %s."
-msgstr "Memo enviado para %s."
+msgstr "Adicionadas informações a %s."
-#, fuzzy
msgid "Added new logon news item."
-msgstr "Adicionado novo logon news (#%d)."
+msgstr "Adicionada nova notícia de logon."
-#, fuzzy
msgid "Added new oper news item."
-msgstr "Adicionado novo OperNews (#%d)."
+msgstr "Adicionada nova notícia de oper."
-#, fuzzy
msgid "Added new random news item."
-msgstr "Adicionada novo item RandomNews (#%d)."
+msgstr "Adicionada nova notícia aleatória."
-#, fuzzy, c-format
+#, c-format
msgid "Added server %s."
-msgstr "Uplink server: %s"
+msgstr "Servidor %s adicionado."
#, c-format
msgid "Added zone %s."
-msgstr ""
+msgstr "Zona %s adicionada."
msgid ""
"Adding, deleting, or clearing entry messages requires the\n"
"SET permission."
msgstr ""
+"Adicionar, excluir ou limpar mensagens de entrada requer a\n"
+"permissão SET."
msgid ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
+"Additionally, Services Operators with the chanserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
msgstr ""
+"Além disso, os Operadores de Serviços com permissão chanserv/drop/override podem\n"
+"substituir código por OVERRIDE para remover o registo sem um código de confirmação."
+
+msgid ""
"Additionally, Services Operators with the nickserv/confirm permission can\n"
"replace passcode with a users nick to force validate them."
+msgstr ""
+"Além disso, Operadores de Serviços com permissão nickserv/confirm podem\n"
+"substituir a senha por um nick de usuário para forçar a validação."
+
+msgid ""
+"Additionally, Services Operators with the nickserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
+msgstr ""
+"Além disso, os Operadores de Serviços com permissão nickserv/drop/override podem\n"
+"substituir código por OVERRIDE para remover o registo sem um código de confirmação."
#, c-format
msgid ""
@@ -2142,199 +1905,174 @@ msgid ""
"can be executed by prefixing the command name with\n"
"one of the following characters: %s"
msgstr ""
+"Além disso, se a fantasia estiver habilitada, os comandos\n"
+"da fantasia podem ser executados prefixando o nome do\n"
+"comando com um dos seguintes caracteres: %s"
#, c-format
msgid "All O:lines of %s have been reset."
-msgstr "Todas as O:lines do servidor %s foram resetadas."
+msgstr "Todas as O:lines de %s foram redefinidas."
-#, fuzzy, c-format
+#, c-format
msgid "All akick entries from %s have been cloned to %s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s"
+msgstr "Todas as entradas de akick de %s foram clonadas para %s."
-#, fuzzy, c-format
+#, c-format
msgid "All available commands for %s:"
-msgstr "Nenhuma ajuda disponível para %s."
+msgstr "Todos os comandos disponíveis para %s:"
-#, fuzzy, c-format
+#, c-format
msgid "All badword entries from %s have been cloned to %s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s"
+msgstr "Todas as entradas de palavrões de %s foram clonadas para %s."
-#, fuzzy, c-format
+#, c-format
msgid "All level entries from %s have been cloned into %s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s"
+msgstr "Todas as entradas de nível de %s foram clonadas para %s."
msgid "All logon news items deleted."
-msgstr "Todos os logon news foram removidos."
+msgstr "Todas as notícias de logon foram excluídas."
#, c-format
msgid "All memos for channel %s have been deleted."
-msgstr "Todos os memos para o canal %s foram apagados."
+msgstr "Todos os memos do canal %s foram excluídos."
#, c-format
msgid "All modes cleared on %s."
-msgstr ""
+msgstr "Todos os modos foram apagados em %s."
-msgid ""
-"All new accounts must be validated by an administrator. Please wait for your "
-"registration to be confirmed."
-msgstr ""
+msgid "All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."
+msgstr "Todas as novas contas devem ser validadas por um administrador. Aguarde a confirmação do seu registo."
msgid "All of your memos have been deleted."
-msgstr "Todos os seus memos foram apagados."
+msgstr "Todos os seus memos foram excluídos."
msgid "All oper news items deleted."
-msgstr "Todos os OperNews foram removidos."
+msgstr "Todas as notícias de oper foram excluídas."
-#, fuzzy, c-format
+#, c-format
msgid "All operators from %s have been removed."
-msgstr "Todas as O:lines do servidor %s foram removidas."
+msgstr "Todos os operadores de %s foram removidos."
msgid "All random news items deleted."
-msgstr "Todos os itens RandomNews deletados."
+msgstr "Todas as notícias aleatórias foram excluídas."
-#, fuzzy, c-format
+#, c-format
msgid "All settings from %s have been cloned to %s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s"
+msgstr "Todas as configurações de %s foram clonadas para %s."
-#, fuzzy, c-format
+#, c-format
msgid "All user modes on %s have been synced."
-msgstr "Todas as O:lines do servidor %s foram resetadas."
+msgstr "Todos os modos de usuário em %s foram sincronizados."
-#, fuzzy, c-format
+#, c-format
msgid "All vhosts in the group %s have been set to %s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s"
+msgstr "Todos os vhosts do grupo %s foram definidos como %s."
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "Todos os vhost's no grupo %s foram ajustados para %s@%s"
-
-msgid "Allowed to (de)halfop him/herself"
-msgstr ""
+msgid "Allowed to (de)halfop themself"
+msgstr "Permissão para (de)halfop a si mesmo"
msgid "Allowed to (de)halfop users"
-msgstr ""
+msgstr "Permissão para (de)halfop usuários"
-msgid "Allowed to (de)op him/herself"
-msgstr ""
+msgid "Allowed to (de)op themself"
+msgstr "Permissão para (de)op a si mesmo"
msgid "Allowed to (de)op users"
-msgstr ""
+msgstr "Permissão para (de)op usuários"
-msgid "Allowed to (de)owner him/herself"
-msgstr ""
+msgid "Allowed to (de)owner themself"
+msgstr "Permissão para (de)owner a si mesmo"
msgid "Allowed to (de)owner users"
-msgstr ""
+msgstr "Permissão para (de)owner usuários"
-msgid "Allowed to (de)protect him/herself"
-msgstr ""
+msgid "Allowed to (de)protect themself"
+msgstr "Permissão para (de)protect a si mesmo"
msgid "Allowed to (de)protect users"
-msgstr ""
+msgstr "Permissão para (de)protect usuários"
-msgid "Allowed to (de)voice him/herself"
-msgstr ""
+msgid "Allowed to (de)voice themself"
+msgstr "Permissão para (de)voice a si mesmo"
msgid "Allowed to (de)voice users"
-msgstr ""
+msgstr "Permissão para (de)voice usuários"
msgid "Allowed to assign/unassign a bot"
-msgstr ""
+msgstr "Permissão para atribuir/cancelar atribuição de um bot"
msgid "Allowed to ban users"
-msgstr ""
+msgstr "Permissão para banir utilizadores"
-#, fuzzy
msgid "Allowed to change channel topics"
-msgstr "%s alterou seus modos de usuário."
+msgstr "Permissão para alterar os tópicos do canal"
msgid "Allowed to get full INFO output"
-msgstr ""
+msgstr "Permissão obter saída INFO completa"
msgid "Allowed to issue commands restricted to channel founders"
-msgstr ""
+msgstr "Permissão para emitir comandos restritos aos fundadores do canal"
msgid "Allowed to modify channel badwords list"
-msgstr ""
+msgstr "Permissão para modificar a lista de palavrões do canal"
+
+msgid "Allowed to modify channel settings"
+msgstr "Permissão para alterar as definições de canal"
-#, fuzzy
msgid "Allowed to modify the access list"
-msgstr "%s removido da lista de acesso do %s."
+msgstr "Permissão para modificar a lista de acesso"
msgid "Allowed to read channel memos"
-msgstr ""
+msgstr "Permissão para ler memos do canal"
-#, fuzzy
-msgid "Allowed to set channel settings"
-msgstr "* Impedido o registro de novos canais"
+msgid "Allowed to unban themself"
+msgstr "Permissão para se desbanir"
msgid "Allowed to unban users"
-msgstr ""
+msgstr "Permissão para desbanir outros utilizadores"
msgid "Allowed to use GETKEY command"
-msgstr ""
+msgstr "Permissão para utilizar o comando GETKEY"
msgid "Allowed to use SAY and ACT commands"
-msgstr ""
+msgstr "Permissão para utilizar os comandos SAY e ACT"
-#, fuzzy
msgid "Allowed to use fantasy commands"
-msgstr " PEACE Regula o uso de comandos críticos"
+msgstr "Permissão para usar comandos de fantasia"
-#, fuzzy
msgid "Allowed to use the AKICK command"
-msgstr "You cannot use this command."
+msgstr "Permissão para usar o comando AKICK"
msgid "Allowed to use the INVITE command"
-msgstr ""
+msgstr "Permissão para utilizar o comando INVITE"
-#, fuzzy
msgid "Allowed to use the KICK command"
-msgstr "You cannot use this command."
+msgstr "Permissão para usar o comando KICK"
-#, fuzzy
msgid "Allowed to use the MODE command"
-msgstr "You cannot use this command."
+msgstr "Permissão para usar o comando MODE"
-#, fuzzy
msgid "Allowed to view the access list"
-msgstr "%s removido da lista de acesso do %s."
-
-#, fuzzy, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
-msgstr ""
-"Sintaxe: GLOBAL mensagens\n"
-"\n"
-"Permite que os IRCops enviem mensagens para todos os usuários\n"
-"da Rede. A mensagem será enviada pelo nick %s."
+msgstr "Permissão para visualizar a lista de acesso"
-#, fuzzy
msgid ""
"Allows Services Operators to change modes for any channel.\n"
"Parameters are the same as for the standard /MODE command.\n"
"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
"If CLEAR ALL is given then all modes, including user status, is removed."
msgstr ""
-"Sintaxe: MODE canal modos\n"
-"\n"
-"Permite que os Operadores dos Services ajustem os modos de\n"
-"qualquer canal. Os parâmetros são os mesmos do comando\n"
-"/MODE padrão."
+"Permite aos Operadores de Serviços alterar os modos de qualquer canal.\n"
+"Os parâmetros são os mesmos do comando /MODE padrão.\n"
+"Em alternativa, pode ser utilizado CLEAR para limpar todos os modos do canal.\n"
+"Se for fornecido CLEAR ALL, todos os modos, incluindo o estatuto do utilizador, serão removidos."
-#, fuzzy
msgid ""
"Allows Services Operators to change modes for any user.\n"
"Parameters are the same as for the standard /MODE command."
msgstr ""
-"Sintaxe: MODE canal modos\n"
-"\n"
-"Permite que os Operadores dos Services ajustem os modos de\n"
-"qualquer canal. Os parâmetros são os mesmos do comando\n"
-"/MODE padrão."
+"Permite aos Operadores de Serviços alterar os modos para qualquer utilizador.\n"
+"Os parâmetros são os mesmos do comando /MODE padrão."
-#, fuzzy
msgid ""
"Allows Services Operators to create, modify, and delete\n"
"bots that users will be able to use on their own\n"
@@ -2354,71 +2092,52 @@ msgid ""
"currently registered. If an unregistered user is currently\n"
"using the nick, they will be killed."
msgstr ""
-"Sintaxe: BOT ADD nick user host real\n"
-" BOT CHANGE NickAntigo NickNovo [user [host [real]]]\n"
-" BOT DEL nick\n"
-"\n"
-"Permite que os Administradores dos Services criem,\n"
-"modifiquem, e apaguem bots que os usuários poderão usar\n"
-"em seus próprios canais.\n"
-"\n"
-"BOT ADD adiciona um bot com um determinado nick, username,\n"
-"hostname e realname. \n"
-"BOT CHANGE permite alterar o nick, username, hostname\n"
-"ou realname de um bot sem que seja necessário apagá-lo (e\n"
-"todas as informações nele contidas).\n"
-"BOT DEL remove um bot da lista de bots. \n"
-"\n"
-"Nota: você não pode criar um bot que use um nick que já\n"
-"seja registrado. Se um usuário não registrado está atualmente\n"
-"usando o nick, ele será killado."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Sintaxe: OLINE usuário flags\n"
-"\n"
-"Permite aos Services Operators dar flags de Oper\n"
-"a qualquer usuário. Flags devem ser prefixadas com \"+\" ou\n"
-"\"-\". Para remover todas as flags apenas digite um \"-\" em\n"
-"vez de usar alguma flag."
+"Permite aos Operadores de Serviços criar, modificar e eliminar\n"
+"bots que os utilizadores poderão utilizar nos seus próprios\n"
+"canais..\n"
+" \n"
+"BOT ADD adiciona um bot com o nickname, nome de utilizador,\n"
+"nome de host e nome real fornecidos. Como não é feita nenhuma verificação\n"
+"de integridade para estas definições, tenha muito cuidado.\n"
+" \n"
+"BOT CHANGE permite alterar o nickname, o nome de utilizador, o nome do host\n"
+"ou o nome real de um bot sem o eliminar (e todos\n"
+"os dados a ele associados).\n"
+" \n"
+"BOT DEL remove o bot fornecido da lista de bots.\n"
+" \n"
+"Nota: Não pode criar um bot com um nick que esteja\n"
+"registado atualmente. Se um utilizador não registado estiver\n"
+"a utilizar o nick, será killado."
-#, fuzzy
msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
"Ignores will not be enforced on IRC Operators."
msgstr ""
-"Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask]\n"
-"\n"
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes, \n"
-"h for hours and d for days. \n"
-"Combinations of these units are not permitted. To make\n"
-"Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format user@host\n"
-"or nick!user@host, everything else will be considered a nick.\n"
-"Wildcards are permitted.\n"
-"\n"
-"Ignores will not be enforced on IRC Operators."
+"Permite aos Operadores de Serviços fazer com que os serviços ignorem um nick ou máscara\n"
+"durante um determinado tempo ou até ao próximo reinício. O formato de hora predefinido\n"
+"é segundos. Pode especificá-lo usando unidades.\n"
+"As unidades válidas são: s para segundos, m para minutos,\n"
+"h para horas e d para dias.\n"
+"Não são permitidas combinações destas unidades.\n"
+"Para fazer com que os serviços ignorem permanentemente o utilizador, introduza 0 como tempo.\n"
+"Ao adicionar uma máscara, esta terá de estar no formato nick!user@host,\n"
+"tudo o resto será considerado um nick. Wildcards são permitidos.\n"
+" \n"
+"Ignores não serão aplicado aos Operadores de IRC."
-#, fuzzy
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2438,68 +2157,56 @@ msgid ""
"current AKILL default expiry time can be found with the\n"
"STATS AKILL command."
msgstr ""
-"Sintaxe: AKILL ADD [+tempo] máscara motivo\n"
-" AKILL DEL {máscara | entrada | lista-entradas}\n"
-" AKILL LIST [máscara | lista-entradas]\n"
-" AKILL VIEW [máscara | lista-entradas]\n"
-" AKILL CLEAR\n"
-"\n"
-"Permite que Operadores dos Services manipulem a lista de\n"
-"AKILL. Se um usuário que tenta conectar possui uma máscara\n"
-"prevista na lista de AKILL, os Services emitem um KILL para\n"
-"aquele usuário, em servidores que suportam, e instrui todos\n"
-"os servidores da rede a adicionar um ban (K-line) para a\n"
-"máscara do usuário encontrado.\n"
-"\n"
-"AKILL ADD adiciona uma máscara ident@host na lista de AKILL\n"
-"para um dado motivo (deve ser fornecido).\n"
-"Opcionalmente, um tempo para o akill expirar pode ser\n"
-"fornecido. O tempo precede a máscara ident@host, e é\n"
-"especificado como um número inteiro seguido por uma das\n"
-"seguintes unidades: d (dias), h (horas) ou m (minutos).\n"
-"Combinações (como 1h30m) não são permitidas. Se uma unidade\n"
-"específica não é incluída, o padrão é em dias (assim, +30\n"
-"significa 30 dias). Para adicionar um AKILL que não expira,\n"
-"use +0. Se a máscara a ser adicionada começar com um +,\n"
-"o tempo do AKILL deve ser fornecido, mesmo se esse tempo for igual\n"
-"ao padrão. O tempo atual de expiração de AKILLs pode ser encontrado\n"
-"com o comando STATS AKILL.\n"
-"\n"
-"AKILL DEL remove uma dada máscara da lista de AKILL, se ela\n"
-"estiver presente. Se uma lista de números de entrada for fornecida,\n"
-"essas entradas serão apagadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"AKILL LIST mostra a lista de AKILL atual.\n"
-"Se uma máscara for fornecida, apenas as entradas que combinarem\n"
-"com a máscara serão exibidas. Se uma lista de números de entrada\n"
-"for fornecida, apenas essas entradas serão exibidas; por exemplo:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" Lista as entradas de AKILL numeradas de 2 a 5 e de 7 a 9.\n"
-"\n"
-"AKILL VIEW é uma versão mais detalhada do AKILL LIST,\n"
-"e mostrará quem adicionou o AKILL, a data em que foi adicionado,\n"
-"e quando irá expirar, como também a máscara (ident@host) e o motivo.\n"
-"\n"
-"AKILL CLEAR apaga todas as entradas da lista de AKILL."
+"Permite aos Operadores de Serviços manipular a lista AKILL. Se\n"
+"um utilizador que corresponda a uma máscara AKILL tentar ligar-se, os serviços\n"
+"emitirão um KILL para esse utilizador e, nos tipos de servidores suportados,\n"
+"darão instruções a todos os servidores para adicionar um ban para a máscara\n"
+"que o utilizador correspondeu.\n"
+" \n"
+"AKILL ADD adiciona a máscara fornecida à lista AKILL\n"
+"pelo motivo especificado, que deve deve ser fornecido.\n"
+"A máscara deve estar no formato nick!user@host#nome real,\n"
+"embora tudo o que seja necessário seja user@host. Se for especificado\n"
+"um nome real, o motivo deverá ser precedido de :.\n"
+"Expiração é especificada como um número inteiro seguido de d\n"
+"(dias), h (horas), ou m (minutos). Combinações (como por exemplo\n"
+"1h30m) não são permitidas. Se um especificador de unidade não\n"
+"estiver incluído, o padrão será dias (portanto +30 por si só significa 30\n"
+"dias). Para adicionar um AKILL que não expira, utilize +0. Se a\n"
+"máscara de utilizador a adicionar começar por +, terá de ser fornecido\n"
+"um prazo de expiração, mesmo que seja igual ao padrão. O\n"
+"tempo de expiração padrão atual do AKILL pode ser encontrado com\n"
+"o comando STATS AKILL."
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
+"Allows Services Operators to manipulate the SNLINE list. If\n"
+"a user with a realname matching an SNLINE mask attempts to\n"
+"connect, services will not allow them to pursue their IRC\n"
+"session."
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
"regular expression, the expression will be matched against\n"
"channels too."
msgstr ""
+"Permite aos Operadores de Serviços manipular a lista SQLINE. Se\n"
+"um utilizador com um nick correspondente a uma máscara SQLINE tentar\n"
+"ligar-se, os serviços não lhe permitirão continuar a sua sessão\n"
+"de IRC.\n"
+"Se o primeiro caractere da máscara for #, os serviços impedirão\n"
+"a utilização dos canais correspondentes. Se a máscara for uma\n"
+"expressão regular, a expressão também será comparada\n"
+"com canais."
msgid ""
"Allows Services Operators to manipulate the list of hosts that\n"
@@ -2511,8 +2218,15 @@ msgid ""
"source of help regarding session limiting. The content of\n"
"this notice is a config setting."
msgstr ""
+"Permite aos Operadores de Serviços manipular a lista de hosts que\n"
+"têm limites de sessão específicos - permitindo que determinadas máquinas,\n"
+"como os servidores shell, transportem mais do que o número padrão\n"
+"de clientes de cada vez. Quando um host atingir o seu limite de sessão,\n"
+"todos os clientes que tentarem ligar-se a partir desse host serão\n"
+"killados. Antes de o utilizador ser killado, é notificado sobre uma\n"
+"fonte de ajuda sobre a limitação de sessões. O conteúdo desta\n"
+"notificação é uma definição na configuração."
-#, fuzzy
msgid ""
"Allows Services Operators to view the session list.\n"
" \n"
@@ -2529,24 +2243,20 @@ msgid ""
"limiting and how to set session limits specific to certain\n"
"hosts and groups thereof."
msgstr ""
-"Sintaxe: SESSION LIST número\n"
-" SESSION VIEW host\n"
-"\n"
-"Permite que os Administradores dos Services vejam a lista de\n"
-"conexões.\n"
-"\n"
-"SESSION LIST lista máscaras de hosts com pelo menos \n"
-"número conexões permitidas.\n"
-"O limite deve ser um número maior que 1. Isto deve prevenir \n"
-"a listagem de muitos hosts com um limite de conexões \n"
-"limitado a 1.\n"
-"SESSION VIEW mostra informações detalhadas sobre um host\n"
-"específico, incluindo o número de conexões atual e o limite\n"
-"A máscara dada em host não deve incluir wildcards.\n"
-"\n"
-"Veja a ajuda sobre EXCEPTION para mais informações sobre\n"
-"o limite de conexões e como especificar limites de conexões\n"
-"para certos hosts e grupos de hosts."
+"Permite que Operadores de Serviços visualizem a lista de sessões.\n"
+" \n"
+"SESSION LIST lista hosts com pelo menos o limite de sessões.\n"
+"O limite deve ser um número superior a 1. Isto serve\n"
+"para evitar a listagem acidental de um grande número de hosts\n"
+"com sessão única.\n"
+" \n"
+"SESSION VIEW exibe informações detalhadas sobre um host\n"
+"específico - incluindo o número atual de sessões e o limite de sessões.\n"
+"O valor de host não pode incluir wildcards.\n"
+" \n"
+"Consulte a ajuda para EXCEPTION para mais informações sobre a limitação\n"
+"de sessões e como definir limites de sessões específicos para certos\n"
+"hosts e grupos de hosts."
msgid ""
"Allows manipulating the topic of the specified channel.\n"
@@ -2555,12 +2265,64 @@ msgid ""
"the given topic to the existing topic.\n"
" \n"
"LOCK and UNLOCK may be used to enable and disable topic lock. When\n"
-"topic lock is set, the channel topic will be unchangeable by users who do "
-"not have\n"
+"topic lock is set, the channel topic will be unchangeable by users who do not have\n"
"the TOPIC privilege."
msgstr ""
+"Permite manipular o tópico do canal especificado.\n"
+"O comando SET altera o tópico do canal para o tópico indicado\n"
+"ou remove o tópico se nenhum tópico for fornecido. O comando APPEND\n"
+"adiciona o tópico indicado ao tópico existente.\n"
+" \n"
+"LOCK e UNLOCK podem ser usados para ativar e desativar o bloqueio de tópico.\n"
+"Quando o bloqueio de tópico está ativado, o tópico do canal não poderá ser alterado por\n"
+"utilizadores que não possuam o privilégio TOPIC."
-#, fuzzy, c-format
+msgid ""
+"Allows queueing messages to send to users on the network.\n"
+"\n"
+"The QUEUE ADD command adds the given message to the message queue.\n"
+"The QUEUE CLEAR command clears the message queue.\n"
+"The QUEUE DEL command removes the specified message from the message queue. The\n"
+"message number can be obtained from the output of the QUEUE LIST command.\n"
+"The QUEUE LIST command lists all messages that are currently in the message queue."
+msgstr ""
+"Permite enfileirar mensagens para enviar a utilizadores na rede.\n"
+"\n"
+"O comando QUEUE ADD adiciona a mensagem indicada à fila de mensagens.\n"
+"O comando QUEUE CLEAR limpa a fila de mensagens.\n"
+"O comando QUEUE DEL remove a mensagem especificada da fila de mensagens. O\n"
+"número da mensagem pode ser obtido a partir do resultado do comando QUEUE LIST .\n"
+"O comando QUEUE LIST lista todas as mensagens que estão atualmente na fila de mensagens."
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on a server. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+"Permite enviar mensagens a todos os utilizadores num servidor. A mensagem\n"
+"será enviada de %s.\n"
+"\n"
+"Pode enviar uma mensagem especificando-a como um parâmetro ou não fornecer\n"
+"parâmetros para enviar uma mensagem previamente enfileirada.\n"
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on the network. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+"Permite enviar mensagens a todos os utilizadores num servidor. A mensagem\n"
+"será enviada de %s.\n"
+"\n"
+"Pode enviar uma mensagem especificando-a como um parâmetro ou não fornecer\n"
+"parâmetros para enviar uma mensagem previamente enfileirada.\n"
+
+#, c-format
msgid ""
"Allows staff to kick a user from any channel.\n"
"Parameters are the same as for the standard /KICK\n"
@@ -2569,26 +2331,21 @@ msgid ""
" \n"
"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
msgstr ""
-"Sintaxe: KICK canal usuário motivo\n"
-"\n"
-"Permite IRCops kickar um usuário de um canal.\n"
-"Os parâmetros são os mesmos do comando /KICK padrão.\n"
-"A mensagem do kick tem o nick do IRCop que enviou o\n"
-"comando KICK, por exemplo:\n"
-"\n"
-"*** Spam foi kickado do canal #canal pelo %s (Operador (Flood))"
+"Permite ao staff kickar um utilizador de qualquer canal.\n"
+"Os parâmetros são os mesmos que para o comando padrão /KICK.\n"
+"A mensagem de expulsão terá o apelido do IRCop que enviou o comando\n"
+"KICK como prefixo; por exemplo:\n"
+" \n"
+"*** SpamMan foi expulso do canal #my_channel por %s (Alcan (Flood))"
-#, fuzzy
msgid ""
"Allows the channel founder to set various channel options\n"
"and other information.\n"
" \n"
"Available options:"
msgstr ""
-"Sintaxe: SET canal opção parâmetros\n"
-"\n"
-"Permite ao fundador do canal ajustar as várias opções do\n"
-"canal e outras informações.\n"
+"Permite ao fundador do canal definir várias opções\n"
+"e outras informações do canal.\n"
"\n"
"Opções disponíveis:"
@@ -2597,6 +2354,9 @@ msgid ""
"Note that operators removed by this command but are still set in\n"
"the configuration file are not permanently affected by this."
msgstr ""
+"Permite alterar e visualizar os Operadores de Serviços.\n"
+"Note que os operadores removidos por este comando, mas que ainda estão\n"
+"definidos no arquivo de configuração, não são permanentemente afetados por isto."
msgid ""
"Allows you to change and view configuration settings.\n"
@@ -2607,30 +2367,32 @@ msgid ""
"Example:\n"
" MODIFY nickserv forcemail no"
msgstr ""
+"Permite alterar e visualizar definições de configuração.\n"
+"As definições alteradas por este comando são temporárias e não serão refletidas\n"
+"no arquivo de configuração, sendo perdidas caso o Anope seja desligado,\n"
+"reiniciado ou a configuração seja recarregada.\n"
+" \n"
+"Exemplo:\n"
+" MODIFY nickserv forcemail no"
-#, fuzzy
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
-"Syntax: SASET nickname MSG {ON | OFF}\n"
-"\n"
-"Allows you to choose the way Services are communicating with \n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
+"Permite escolher a forma como os serviços se comunicam com\n"
+"o utilizador indicado. Com MSG definido, os serviços utilizarão mensagens,\n"
+"caso contrário, usarão notices."
-#, fuzzy, c-format
+#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
-"Sintaxe: SET MSG {ON | OFF}\n"
-"\n"
-"Permite que você escolha a forma que os Services devem se \n"
-"comunicar com você. Com MSG acionado, os Services irão usar\n"
-"mensagems, caso contrário, usarão notices. "
+"Permite escolher a forma como os serviços se comunicam\n"
+"consigo. Com %s definido, os serviços utilizarão mensagens,\n"
+"caso contrário, utilizarão notices."
msgid ""
"Allows you to ignore users by nick or host from memoing\n"
@@ -2638,60 +2400,61 @@ msgid ""
"to memo you or a channel, they will not be told that you have\n"
"them ignored."
msgstr ""
+"Permite ignorar utilizadores por apelido ou host, impedindo-os de enviar-lhe\n"
+"memos ou enviar memos para um canal. Se alguém na lista de ignorados tentar\n"
+"enviar-lhe um memo ou enviar um memo para um canal,\n"
+"não será informado de que foi ignorado."
msgid ""
"Allows you to kill a user from the network.\n"
"Parameters are the same as for the standard /KILL\n"
"command."
msgstr ""
+"Permite killar um utilizador da rede.\n"
+"Os parâmetros são os mesmos que para o comando\n"
+"padrão /KILL."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
+"nick. You can hide the email address (EMAIL), last seen\n"
"user@host mask (USERMASK), the services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
"be displayed (OFF) or hidden (ON)."
msgstr ""
-"Syntax: SASET nickname HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
+"Permite impedir que certas informações sejam exibidas\n"
+"quando alguém executa %s INFO no\n"
+"nick. Pode ocultar o endereço de e-mail (EMAIL),a máscara de\n"
+"utilizador@host vista da última vez (USERMASK), o status de acesso aos serviços\n"
+"(STATUS) e a última mensagem de saída (QUIT).\n"
+"O segundo parâmetro especifica se a informação deve\n"
+"ser exibida (OFF) ou ocultada (ON)."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
+"nick. You can hide your email address (EMAIL), last seen\n"
"user@host mask (USERMASK), your services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
"be displayed (OFF) or hidden (ON)."
msgstr ""
-"Sintaxe: SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Permite que você previna que certas informações sejam\n"
-"mostradas quando alguém usa %s INFO no seu nick. Você pode\n"
-"esconder seu endereço de e-mail (EMAIL), última máscara vista\n"
-"user@host (USERMASK), seu status de acesso aos Services\n"
-"(STATUS) e sua última mensagem de saída (QUIT).\n"
-"O segundo parâmetro especifica quando a informação deve ser\n"
-"mostrada (OFF) ou escondida (ON)."
-
-#, fuzzy, c-format
+"Permite impedir que certas informações sejam exibidas\n"
+"quando alguém executa %s INFO no seu\n"
+"nick. Pode ocultar o seu endereço de e-mail (EMAIL), a máscara de\n"
+"utilizador@host vista pela última vez (USERMASK), o seu status de acesso aos serviços\n"
+"(STATUS) e a última mensagem de saída (QUIT).\n"
+"O segundo parâmetro especifica se a informação deve\n"
+"ser exibida (OFF) ou ocultada (ON)."
+
+#, c-format
msgid "Allows you to see %s information about a channel or a bot"
-msgstr ""
-" INFO Permite que você veja informações do BotServ sobre um "
-"canal ou bot"
+msgstr "Permite ver informações %s sobre um canal ou um bot"
-#, fuzzy, c-format
+#, c-format
msgid ""
"Allows you to see %s information about a channel or a bot.\n"
"If the parameter is a channel, then you'll get information\n"
@@ -2699,157 +2462,133 @@ msgid ""
"you'll get information about a bot, such as creation\n"
"time or number of channels it is on."
msgstr ""
-"Sintaxe: INFO {canal | nick}\n"
-"\n"
-"Permite que você veja informações do %s sobre um\n"
-"canal ou bot. Se a opção for um canal, então você terá\n"
-"informações tais como kickers ativos. Se tiver sido um nick,\n"
-"você terá informações sobre o bot, como o horário de criação\n"
-"ou número de canais onde ele está."
+"Permite ver informações %s sobre um canal ou um bot.\n"
+"Se o parâmetro for um canal, você obterá informações\n"
+"omo kickers ativados. Se o parâmetro for um nick,\n"
+"você obterá informações sobre um bot, como o tempo de criação\n"
+"ou o número de canais em que ele está."
msgid ""
"Alternative methods of modifying channel access lists are\n"
"available."
msgstr ""
+"Métodos alternativos para modificar as listas de acesso do\n"
+"canal estão disponíveis."
-#, fuzzy
-msgid "Approve the requested vHost of a user"
-msgstr " DEL Deleta o vHost de outro usuário"
+msgid "Approve the requested vhost of a user"
+msgstr "Aprovar o vhost solicitado por um utilizador"
-#, fuzzy
msgid "As a Services Operator, you may drop any nick."
-msgstr "%s is a services operator of type %s."
+msgstr "Como Operador de Serviços, pode remover qualquer nick."
-#, fuzzy
msgid "Assigns a bot to a channel"
-msgstr " ASSIGN Associa um bot ao canal"
+msgstr "Atribui um bot a um canal"
-#, fuzzy
msgid ""
"Assigns the specified bot to a channel. You\n"
"can then configure the bot for the channel so it fits\n"
"your needs."
msgstr ""
-"Sintaxe: ASSIGN canal nick\n"
-"\n"
-"Associa um bot escolhido pelo nick a um canal.\n"
-"Você poderá então configurar o bot para o canal de acordo\n"
-"com as suas necessidades."
+"Atribui o bot especificado a um canal. Pode,\n"
+"então, configurar o bot para o canal de forma a que\n"
+"se ajuste às suas necessidades."
-#, fuzzy
msgid "Associate a URL with the channel"
-msgstr " ASSIGN Associa um bot ao canal"
+msgstr "Associa um URL ao canal"
msgid "Associate a URL with this account"
-msgstr ""
+msgstr "Associa um URL a esta conta"
-#, fuzzy
msgid "Associate a URL with your account"
-msgstr " GREET Associa uma mensgem de entrada ao seu nick"
+msgstr "Associa um URL à tua conta"
-#, fuzzy
msgid "Associate a greet message with your nickname"
-msgstr " GREET Associa uma mensgem de entrada ao seu nick"
+msgstr "Associa uma mensagem de saudação ao teu nickname"
-#, fuzzy
-msgid "Associate an E-mail address with the channel"
-msgstr " EMAIL Associa um endereço de e-mail ao seu nick"
+msgid "Associate an email address with the channel"
+msgstr "Associa um endereço de e-mail ao canal"
-#, fuzzy
-msgid "Associate an E-mail address with your nickname"
-msgstr " EMAIL Associa um endereço de e-mail ao seu nick"
+msgid "Associate an email address with your nickname"
+msgstr "Associa um endereço de e-mail ao teu nickname"
-#, fuzzy
msgid "Associate oper info with a nick or channel"
-msgstr " ASSIGN Associa um bot ao canal"
+msgstr "Associa informações de operador a um nickname ou canal"
-#, fuzzy
-msgid "Associates the given E-mail address with the nickname."
-msgstr " EMAIL Associa um endereço de e-mail ao seu nick"
+msgid "Associates the given email address with the nickname."
+msgstr "Associa o endereço de e-mail fornecido ao nickname."
-#, fuzzy
msgid ""
-"Associates the given E-mail address with your nickname.\n"
+"Associates the given email address with your nickname.\n"
"This address will be displayed whenever someone requests\n"
"information on the nickname with the INFO command."
msgstr ""
-"Sintaxe: SET EMAIL endereço\n"
-"\n"
-"Associa um endereço de email designado ao seu nick. Este\n"
-"endereço será sempre mostrado quando alguém solicitar\n"
-"informação sobre seu nick atraves do comando INFO.\n"
-"O email especificado também é usado para enviar sua senha\n"
-"caso seja perdida. Caso não tenha nenhum endereço para seu\n"
-"nick ou o mesmo seje inválido, não será possível recuperar\n"
-"a senha perdida."
+"Associa o endereço de e-mail fornecido ao teu nickname.\n"
+"Este endereço será exibido sempre que alguém solicitar\n"
+"informações sobre o nickname com o comando INFO."
msgid "Auto-op"
msgstr "Auto-op"
#, c-format
msgid "Autokick list for %s:"
-msgstr "Lista de akick para %s:"
+msgstr "Lista de autokick para %s:"
msgid "Automatic channel operator status upon join"
-msgstr ""
+msgstr "Status automático de operador de canal ao entrar"
msgid "Automatic halfop upon join"
-msgstr ""
+msgstr "Halfop automático ao entrar"
msgid "Automatic owner upon join"
-msgstr ""
+msgstr "Owner automático ao entrar"
msgid "Automatic protect upon join"
-msgstr ""
+msgstr "Proteção automática ao entrar"
msgid "Automatic voice on join"
-msgstr ""
+msgstr "Voice automático ao entrar"
-#, fuzzy, c-format
+#, c-format
msgid "Available commands for %s:"
-msgstr "Nenhuma ajuda disponível para %s."
+msgstr "Comandos disponíveis para %s:"
-#, fuzzy
msgid "Available opertypes:"
-msgstr "Nenhuma ajuda disponível para %s."
+msgstr "Tipos de operador disponíveis:"
#, c-format
msgid "Available privileges for %s:"
-msgstr ""
+msgstr "Privilégios disponíveis para %s:"
msgid "BANS enforced by "
-msgstr ""
+msgstr "BANS aplicados por "
-#, fuzzy
msgid "Bad words kicker"
-msgstr " Kick por palavrão: %s"
+msgstr "Kicker de palavrões"
-#, fuzzy, c-format
+#, c-format
msgid "Bad words list for %s:"
-msgstr "Lista de acesso para %s:"
+msgstr "Lista de palavrões para %s:"
msgid "Bad words list is now empty."
-msgstr "Lista de palavrões está agora vazia."
+msgstr "A lista de palavrões está agora vazia."
msgid "Ban expiry may not be longer than 1 day."
-msgstr ""
+msgstr "A expiração do banimento não pode ser superior a 1 dia."
-#, fuzzy, c-format
+#, c-format
msgid "Ban on %s expires in %s."
-msgstr "Bot %s já existe."
+msgstr "O banimento em %s expira em %s."
msgid "Ban type"
-msgstr ""
+msgstr "Tipo de banimento"
#, c-format
msgid "Ban type for channel %s is now #%d."
-msgstr "Tipo de ban para o canal %s é agora #%d."
+msgstr "O tipo de banimento para o canal %s é agora #%d."
-#, fuzzy
msgid "Bans a given nick or mask on a channel"
-msgstr " BAN Bane o nick selecionado em um canal"
+msgstr "Bane um nick ou máscara num canal"
-#, fuzzy
msgid ""
"Bans a given nick or mask on a channel. An optional expiry may\n"
"be given to cause services to remove the ban after a set amount\n"
@@ -2858,405 +2597,342 @@ msgid ""
"By default, limited to AOPs or those with level 5 access\n"
"and above on the channel. Channel founders may ban masks."
msgstr ""
-"Sintaxe: BAN #canal nick [motivo]\n"
-"\n"
-"Bane o nick selecionado em um canal.\n"
-"\n"
-"Por padrão, limitado a AOPs ou àqueles com nível de acesso 5 ou\n"
-"superior no canal."
+"Bane um nick ou máscara num canal. Pode ser dada uma expiração\n"
+"opcional para que os serviços removam o banimento após um determinado\n"
+"período de tempo.\n"
+" \n"
+"Por defeito, é limitado a AOPs ou utilizadores com acesso de nível 5\n"
+"ou superior no canal. Os fundadores do canal podem banir máscaras."
-#, fuzzy, c-format
+#, c-format
msgid "Bans enforced on %s."
-msgstr "%s não é notificado de novos memos."
+msgstr "Bans aplicados em %s."
-#, fuzzy
msgid "Bolds kicker"
-msgstr " Kick por negrito: %s"
+msgstr "Kicker de negrito"
#, c-format
msgid "Bot %s already exists."
-msgstr "Bot %s já existe."
+msgstr "O bot %s já existe."
-#, fuzzy, c-format
+#, c-format
msgid "Bot %s does not exist."
-msgstr "Bot %s já existe."
+msgstr "O bot %s não existe."
#, c-format
msgid "Bot %s has been assigned to %s."
-msgstr "Bot %s foi associado ao canal %s."
+msgstr "O bot %s foi atribuído a %s."
-#, fuzzy, c-format
+#, c-format
msgid "Bot %s has been changed to %s!%s@%s (%s)."
-msgstr "Bot %s foi alterado para %s!%s@%s (%s)"
+msgstr "O bot %s foi alterado para %s!%s@%s (%s)."
#, c-format
msgid "Bot %s has been deleted."
-msgstr "Bot %s foi removido."
+msgstr "O bot %s foi eliminado."
#, c-format
msgid "Bot %s is already assigned to channel %s."
-msgstr "Bot %s já está associado ao canal %s."
+msgstr "O bot %s já está atribuído ao canal %s."
#, c-format
msgid "Bot will kick ops on channel %s."
-msgstr "Bot irá kickar OPs no canal %s."
+msgstr "O bot vai kickar ops no canal %s."
#, c-format
msgid "Bot will kick voices on channel %s."
-msgstr "Bot irá kickar voices no canal %s."
+msgstr "O bot vai kickar voices no canal %s."
#, c-format
msgid "Bot won't kick ops on channel %s."
-msgstr "Bot não irá kickar OPs no canal %s."
+msgstr "O bot nãi vai kickar ops no canal %s."
#, c-format
msgid "Bot won't kick voices on channel %s."
-msgstr "Bot não irá kickar voices no canal %s."
+msgstr "O bot não vai kickar voices no canal %s."
-#, fuzzy, c-format
+#, c-format
msgid "Bot %s is not changeable."
-msgstr "Modo NOBOT está agora ATIVADO no canal %s."
+msgstr "O bot %s não é alterável."
-#, fuzzy, c-format
+#, c-format
msgid "Bot %s is not deletable."
-msgstr "Bot %s foi removido."
+msgstr "O bot %s não pode ser eliminado."
#, c-format
msgid "Bot bans will automatically expire after %s."
-msgstr ""
+msgstr "Os bans do bot irão expirar automaticamente após %s."
-#, fuzzy
msgid "Bot bans will no longer automatically expire."
-msgstr "Services will no longer autoop %s in channels."
+msgstr "Os bans do bot já não expirarão automaticamente."
-#, fuzzy, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Bot Hosts may only contain %d characters."
+#, c-format
+msgid "Bot hosts may only be %zu characters long."
+msgstr "Os hosts dos bots só podem ter %zu caracteres de comprimento."
-#, fuzzy
msgid "Bot hosts may only contain valid host characters."
-msgstr "O Host do bot deve conter apenas caracteres válidos a Hosts."
+msgstr "Os hosts dos bots só podem conter caracteres válidos de host."
-#, fuzzy, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Bot Idents may only contain %d characters."
+#, c-format
+msgid "Bot idents may only be %zu characters long."
+msgstr "Os idents dos bots podem ter no máximo %zu caracteres."
-#, fuzzy
msgid "Bot idents may only contain valid ident characters."
-msgstr "A Identd do bot deve conter apenas caracteres válidos."
+msgstr "Os idents dos bots só podem conter caracteres válidos de ident."
-#, fuzzy, c-format
+#, c-format
msgid "Bot is not on channel %s."
-msgstr "Bot irá kickar OPs no canal %s."
+msgstr "O bot não está no canal %s."
msgid "Bot list:"
msgstr "Lista de bots:"
msgid "Bot nick"
-msgstr ""
+msgstr "Nick do bot"
-#, fuzzy, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Bot Idents may only contain %d characters."
+#, c-format
+msgid "Bot nicks may only be %zu characters long."
+msgstr "Os nicks dos bots podem ter no máximo %zu caracteres."
-#, fuzzy
msgid "Bot nicks may only contain valid nick characters."
-msgstr "O Nick do bot deve conter apenas caracteres válidos a Nicks."
+msgstr "Os nicks dos bots só podem conter caracteres válidos para nicks."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for %s, and will place a ban\n"
"after %d kicks for the same user."
msgstr ""
-"Bot will now kick italics, and will place a ban after %d\n"
-"kicks for the same user."
+"O bot irá agora kickar por %s e colocará um banimento\n"
+"após %d kicks do mesmo utilizador."
-#, fuzzy, c-format
+#, c-format
msgid "Bot will now kick for %s."
-msgstr "O bot irá agora kickar por negritos."
+msgstr "O bot irá agora kickar por %s."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for caps (they must constitute at least\n"
"%d characters and %d%% of the entire message), and will\n"
"place a ban after %d kicks for the same user."
msgstr ""
-"O bot irá agora kickar por caps (deve ter no mínimo\n"
-"%d caracteres e %d%% na mensagem inteira), e irá setar\n"
-"um ban após %d kicks no mesmo usuário."
+"O bot irá agora kickar por caps (devem constituir pelo menos\n"
+"%d caracteres e %d%% de toda a mensagem), e colocará\n"
+"um banimento após %d kicks para o mesmo utilizador."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for caps (they must constitute at least\n"
"%d characters and %d%% of the entire message)."
msgstr ""
-"O bot irá agora kickar por caps (deve ter no mínimo\n"
-"%d caracteres e %d%% na mensagem inteira)."
+"O bot irá agora kickar por caps (devem constituir pelo menos\n"
+"%d caracteres e %d%% de toda a mensagem)."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for flood (%d lines in %d seconds\n"
"and will place a ban after %d kicks for the same user."
msgstr ""
-"O bot irá agora kickar por flood (%d linhas em %d segundos), e \n"
-"setar um ban após %d kicks no mesmo usuário."
+"O bot irá agora kickar por flood (%d linhas em %d segundos)\n"
+"e irá aplicar um banimento após %d kicks para o mesmo utilizador."
-#, fuzzy, c-format
+#, c-format
msgid "Bot will now kick for flood (%d lines in %d seconds)."
msgstr "O bot irá agora kickar por flood (%d linhas em %d segundos)."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for repeats (users that repeat the\n"
"same message %d time), and will place a ban after %d\n"
"kicks for the same user."
msgstr ""
-"O bot irá agora kickar por repetição (usuários que escreverem\n"
-"%d vezes a mesma coisa), e irá setar um ban após %d \n"
-"kicks no mesmo usuário."
+"O bot irá agora kickar por repetições (usuários que repetem a\n"
+"mesma mensagem %d vezes) e aplicará um banimento após %d\n"
+"kicks para o mesmo usuário."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for repeats (users that repeat the\n"
"same message %d time)."
msgstr ""
-"O bot irá agora kickar por repetição (usuários que escreverem\n"
-"%d vezes a mesma coisa)."
+"O bot irá agora kickar por repetições (usuários que repetem a\n"
+"mesma mensagem %d vezes)."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for repeats (users that repeat the\n"
"same message %d times), and will place a ban after %d\n"
"kicks for the same user."
msgstr ""
-"O bot irá agora kickar por repetição (usuários que escreverem\n"
-"%d vezes a mesma coisa), e irá setar um ban após %d \n"
-"kicks no mesmo usuário."
+"O bot irá agora kickar por repetições (usuários que repetem a\n"
+"mesma mensagem %d vezes) e aplicará um banimento após %d\n"
+"kicks para o mesmo usuário."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Bot will now kick for repeats (users that repeat the\n"
"same message %d times)."
msgstr ""
-"O bot irá agora kickar por repetição (usuários que escreverem\n"
-"%d vezes a mesma coisa)."
+"O bot irá agora kickar por repetições (usuários que repetem a\n"
+"mesma mensagem %d vezes)."
-#, fuzzy, c-format
+#, c-format
msgid "Bot won't kick for %s anymore."
-msgstr "O bot não irá mais kickar por caps."
+msgstr "O bot não irá mais kickar por %s."
-#, fuzzy
msgid "Bot won't kick for caps anymore."
msgstr "O bot não irá mais kickar por caps."
-#, fuzzy
msgid "Bot won't kick for flood anymore."
msgstr "O bot não irá mais kickar por flood."
-#, fuzzy
msgid "Bot won't kick for repeats anymore."
-msgstr "O bot não irá mais kickar por repetição."
+msgstr "O bot não irá mais kickar por repetições ."
msgid "By"
-msgstr ""
+msgstr "Por"
msgid "CLEAR target"
-msgstr ""
+msgstr "CLEAR alvo"
msgid "CLEAR time"
-msgstr ""
+msgstr "CLEAR tempo"
-#, fuzzy
msgid "Cancel the last memo you sent"
-msgstr " CANCEL Cancela o último memo enviado por você"
+msgstr "Cancelar o último memo que você enviou"
-#, fuzzy
msgid "Cancel the registration of a channel"
-msgstr " DROP Cancela o registro de um canal"
+msgstr "Cancelar o registo de um canal"
-#, fuzzy
msgid "Cancel the registration of a nickname"
-msgstr " DROP Cancela o registro de um nick"
+msgstr "Cancelar o registo de um nickname"
-#, fuzzy
msgid ""
"Cancels the last memo you sent to the given nick or channel,\n"
"provided it has not been read at the time you use the command."
msgstr ""
-"Sintaxe: CANCEL {nick | canal}\n"
-"\n"
-"Cancela a última mensagem enviada para um determinado nick ou\n"
-"canal, caso ela ainda não tenha sido lida no momento em que este\n"
-"comando for usado."
+"Cancela o último memo que você enviou para o nick ou canal fornecido,\n"
+"desde que não tenha sido lido no momento em que o comando for utilizado."
-#, fuzzy, c-format
+#, c-format
msgid "Cannot clone channel %s to itself!"
-msgstr "Bot irá kickar OPs no canal %s."
+msgstr "Não é possível clonar o canal %s para ele mesmo!"
msgid "Cannot send mail now; please retry a little later."
-msgstr "Não foi possível enviar e-mail agora; tente novamente mais tarde."
+msgstr "Não é possível enviar o e-mail agora; por favor, tente novamente mais tarde."
-#, fuzzy
msgid "Caps kicker"
-msgstr " Kick por Caps: %s"
+msgstr "Kicker de maiúsculas"
-#, fuzzy
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
msgstr ""
-"Sintaxe: QUIT\n"
-"\n"
-"Faz com que desligue os Services imediatamente; o banco de\n"
-"dados não é salvo. Este comando não deve ser usado a menos\n"
-"que haja um dano da cópia do banco de dados na memória e por\n"
-"isso eles não devam ser salvos. Para desligar normalmente,\n"
-"use o comando SHUTDOWN."
+"Faz com que os serviços realizem um desligamento imediato; os bancos de dados\n"
+"não são salvos. Este comando não deve ser utilizado a menos que haja\n"
+"receio de danos nas cópias em memória dos bancos de dados\n"
+"e que não devam ser salvas."
-#, fuzzy
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
-"Sintaxe: RELOAD\n"
-"\n"
-"Faz com que os Services recarreguem seu arquivo de configuração. \n"
-"Repare que, para algumas mudanças terem efeito, será necessário\n"
-"que os Services sejam reiniciados."
+"Faz com que os serviços recarreguem o ficheiro de configuração. Note\n"
+"que algumas diretivas ainda necessitam do reinício dos serviços para\n"
+"ter efeito (como os apelidos dos serviços, ativação da\n"
+"limitação de sessões, etc.)."
-#, fuzzy
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr ""
-"Sintaxe: RESTART\n"
-"\n"
-"Salva o banco de dados dos Services e os reinicia.\n"
-"(sai e roda imediatamente o executável)."
+"Faz com que os serviços salvem todos os bancos de dados e depois reiniciem\n"
+"(ou seja, saem e executam novamente o executável)."
-#, fuzzy
-msgid "Causes Services to save all databases and then shut down."
-msgstr ""
-"Sintaxe: SHUTDOWN\n"
-"\n"
-"Salva o banco de dados dos Services e os desliga."
+msgid "Causes services to save all databases and then shut down."
+msgstr "Faz com que os serviços salvem todos os bancos de dados e depois desliguem."
-#, fuzzy
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr ""
-"Sintaxe: UPDATE\n"
-"\n"
-"Faz com que os Services atualizem o banco de dados logo que\n"
-"você envia este comando."
+"Faz com que os serviços atualizem todos os arquivos de banco de dados\n"
+"assim que enviar o comando."
-#, fuzzy, c-format
+#, c-format
msgid "Certificate list for %s:"
-msgstr "Lista de acesso para %s:"
+msgstr "Lista de certificados para %s:"
msgid "ChanServ is required to enable persist on this network."
-msgstr ""
+msgstr "O ChanServ é necessário para ativar a persistência nesta rede."
-#, fuzzy
msgid "Change channel modes"
-msgstr "%s alterou seus modos de usuário."
+msgstr "Alterar os modos do canal"
-#, fuzzy
-msgid "Change the communication method of Services"
-msgstr " MSG Altera o método de comunicação dos Services"
+msgid "Change the communication method of services"
+msgstr "Alterar o método de comunicação dos serviços"
-#, fuzzy
msgid "Change user modes"
-msgstr "%s alterou seus modos de usuário."
+msgstr "Alterar os modos do utilizador"
-#, fuzzy, c-format
+#, c-format
msgid "Changed usermodes of %s to %s."
-msgstr "Modos do usuário %s alterados."
+msgstr "Modos de utilizador de %s alterados para %s."
-#, fuzzy
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
-"Sintaxe: SET DISPLAY novo-display\n"
-"\n"
-"Altera o display usado como referência ao nome do seu grupo \n"
-"nos Services. O novo display DEVE ser um nick do seu grupo."
+"Altera o display usado para se referir ao grupo de nicknames\n"
+"nos serviços. O novo display DEVE ser um nickname do grupo."
-#, fuzzy
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
-"Sintaxe: SET DISPLAY novo-display\n"
-"\n"
-"Altera o display usado como referência ao nome do seu grupo \n"
-"nos Services. O novo display DEVE ser um nick do seu grupo."
+"Altera o display usado para se referir ao seu grupo de nicknames\n"
+"nos serviços. O novo display DEVE ser um nickname do seu grupo."
-#, fuzzy
msgid ""
"Changes the founder of a channel. The new nickname must\n"
"be a registered one."
-msgstr ""
-"Sintaxe: %s canal FOUNDER nick\n"
-"\n"
-"Muda o fundador do canal. O novo nick deve estar\n"
-"registrado."
+msgstr "Altera o fundador de um canal. O novo nickname deve ser um registado."
-#, fuzzy
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Sintaxe: SET LANGUAGE número\n"
-"\n"
-"Muda a linguagem que os Services usam ao enviar mensagens\n"
-"para você (por exemplo, quando responde um comando que você\n"
-"emite). A linguagem Português, assim como outras, pode\n"
-"apresentar algumas diferenças da linguagem Inglês (English),\n"
-"já que Inglês é a linguagem oficial destes Services.\n"
-"O número deve ser escolhido da seguinte lista de línguas:"
+"Altera o idioma que os serviços usam ao enviar mensagens para o\n"
+"usuário dado (por exemplo, ao responder a um comando que ele envia). \n"
+"O idioma deve ser escolhido a partir da seguinte lista de\n"
+"idiomas suportados:"
-#, fuzzy
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
msgstr ""
-"Sintaxe: SET LANGUAGE número\n"
-"\n"
-"Muda a linguagem que os Services usam ao enviar mensagens\n"
-"para você (por exemplo, quando responde um comando que você\n"
-"emite). A linguagem Português, assim como outras, pode\n"
-"apresentar algumas diferenças da linguagem Inglês (English),\n"
-"já que Inglês é a linguagem oficial destes Services.\n"
-"O número deve ser escolhido da seguinte lista de línguas:"
-
-#, fuzzy
+"Altera o idioma que os serviços usam ao enviar mensagens para\n"
+"si (por exemplo, ao responder a um comando que envia).\n"
+"O idioma deve ser escolhido a partir da seguinte lista de\n"
+"idiomas suportados:"
+
msgid "Changes the password used to identify as the nick's owner."
-msgstr ""
-"Sintaxe: SET PASSWORD nova-senha\n"
-"\n"
-"Muda a senha de seu nick."
+msgstr "Altera a password usada para se identificar como o proprietário do nickname."
-#, fuzzy
msgid ""
"Changes the password used to identify you as the nick's\n"
"owner."
msgstr ""
-"Sintaxe: SET PASSWORD nova-senha\n"
-"\n"
-"Muda a senha de seu nick."
+"Altera a password usada para se identificar como o proprietário\n"
+"do seu nickname."
-#, fuzzy
msgid ""
"Changes the successor of a channel. If the founder's\n"
"nickname expires or is dropped while the channel is still\n"
@@ -3267,70 +2943,77 @@ msgid ""
"become the new founder, but if the access list is empty, the\n"
"channel will be dropped."
msgstr ""
-"Sintaxe: %s canal SUCCESSOR nick\n"
-"\n"
-"Altera o sucessor de um canal. Se o nick do founder expirar\n"
-"ou for dropado enquanto o canal ainda estiver registrado,\n"
-"o sucessor se tornará o novo founder do canal.\n"
-"No entanto, se o sucessor possuir muitos canais registrados\n"
-"(%d), o canal será dropado, como se nenhum sucessor tivesse\n"
-"sido ajustado. O novo nick deverá estar registrado."
-
-#, fuzzy
+"Altera o sucessor de um canal. Se o nickname do fundador\n"
+"expirar ou for removido enquanto o canal ainda estiver\n"
+"registado, o sucessor tornará-se o novo fundador do\n"
+"canal. O nickname do sucessor deve ser um registado.\n"
+"Se não houver sucessor definido, o primeiro nickname na\n"
+"lista de acesso (com o maior acesso, se aplicável) tornará-se\n"
+"o novo fundador, mas se a lista de acesso estiver vazia, o\n"
+"canal será removido."
+
+#, c-format
+msgid "Changing your usermodes to %s"
+msgstr "Alterando os seus modos de utilizador para %s"
+
+#, c-format
+msgid "Changing your vhost to %s"
+msgstr "A alterar o seu vhost para %s"
+
msgid "Channel"
-msgstr "DROP canal"
+msgstr "Canal"
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s doesn't exist."
-msgstr "Channel %s is now persistant."
+msgstr "O canal %s não existe."
#, c-format
msgid "Channel %s has been dropped."
-msgstr "O canal %s foi desregistrado."
+msgstr "O canal %s foi removido."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s has no key."
-msgstr "O canal %s não tem key."
+msgstr "O canal %s não tem chave."
#, c-format
msgid "Channel %s is already registered!"
-msgstr "O canal %s já está registrado!"
+msgstr "O canal %s já está registado!"
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s is forbidden by %s: %s"
-msgstr "Este canal foi registrado com o %s."
+msgstr "O canal %s é proibido por %s: %s"
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s is forbidden."
-msgstr "Channel %s is now persistant."
+msgstr "O canal %s é proibido."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s is no longer persistent."
-msgstr "Channel %s is no longer persistant."
+msgstr "O canal %s deixou de ser persistente."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s is now persistent."
-msgstr "Channel %s is now persistant."
+msgstr "O canal %s agora é persistente."
#, c-format
msgid "Channel %s is now released."
-msgstr "Canal %s está agora liberado."
+msgstr "O canal %s agora está libertado."
#, c-format
msgid "Channel %s is now suspended."
-msgstr "Canal %s está agora suspenso."
+msgstr "O canal %s agora está suspenso."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s isn't registered."
-msgstr "O canal %s não pode ser registrado."
+msgstr "O canal %s não está registado."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s isn't suspended."
-msgstr "Canal %s está agora suspenso."
+msgstr "O canal %s não está suspenso."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s registered under your account: %s"
-msgstr "O nick %s foi registrado em sua conta: %s"
+msgstr "Canal %s registado sob a sua conta: %s"
#, c-format
msgid "Channel %s will expire."
@@ -3340,193 +3023,162 @@ msgstr "O canal %s irá expirar."
msgid "Channel %s will not expire."
msgstr "O canal %s não irá expirar."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s %s list has been cleared."
-msgstr "Lista de AOP do canal %s foi limpa."
+msgstr "A lista %s do canal %s foi limpa."
#, c-format
msgid "Channel %s access list has been cleared."
-msgstr "Lista de acesso do canal %s apagada."
+msgstr "A lista de acesso do canal %s foi limpa."
#, c-format
msgid "Channel %s akick list has been cleared."
-msgstr "Lista de akick do canal %s foi limpa."
+msgstr "A lista de akicks do canal %s foi limpa."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s has no mode locks."
-msgstr "Canal %s está agora liberado."
+msgstr "O canal %s não tem bloqueios de modo."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s is currently suspended."
-msgstr "Canal %s está agora suspenso."
+msgstr "O canal %s está atualmente suspenso."
-#, fuzzy, c-format
+#, c-format
msgid "Channel %s is not a valid channel."
-msgstr "%s não é um ban válido."
+msgstr "O canal %s não é um canal válido."
-#, fuzzy
msgid "Channel list:"
-msgstr "Lista de bots:"
+msgstr "Lista de canais:"
-#, fuzzy, c-format
+#, c-format
msgid "Channel stats for %s on %s:"
-msgstr ""
-"Canais nos quais %s tem acesso:\n"
-" Núm Canal Nível Descrição "
+msgstr "Estatísticas do canal %s para %s:"
-#, fuzzy
msgid "Channels may not be on access lists."
-msgstr "%s não foi encontrado na lista de acesso do %s."
+msgstr "Canais não podem estar nas listas de acesso."
-#, fuzzy, c-format
+#, c-format
msgid "Channels that %s has access on:"
-msgstr ""
-"Canais nos quais %s tem acesso:\n"
-" Núm Canal Nível Descrição "
+msgstr "Canais nos quais %s tem acesso:"
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Canais: %zu entradas, %zu buckets, a cadeia mais longa tem %zu"
msgid "Chanstats"
-msgstr ""
+msgstr "Estatísticas do canal"
-#, fuzzy, c-format
+#, c-format
msgid "Chanstats statistics are now disabled for %s"
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr "As estatísticas do Chanstats estão agora desativadas para %s"
msgid "Chanstats statistics are now disabled for this channel."
-msgstr ""
+msgstr "As estatísticas do Chanstats estão agora desativadas para este canal."
-#, fuzzy
msgid "Chanstats statistics are now disabled for your nick."
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr "As estatísticas do Chanstats estão agora desativadas para o seu nickname."
-#, fuzzy, c-format
+#, c-format
msgid "Chanstats statistics are now enabled for %s"
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr "As estatísticas do Chanstats estão agora ativadas para %s"
msgid "Chanstats statistics are now enabled for this channel."
-msgstr ""
+msgstr "As estatísticas do Chanstats estão agora ativadas para este canal."
-#, fuzzy
msgid "Chanstats statistics are now enabled for your nick."
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr "As estatísticas do Chanstats estão agora ativadas para o seu nickname."
msgid ""
"Checks for the last time nick was seen joining, leaving,\n"
"or changing nick on the network and tells you when and, depending\n"
"on channel or user settings, where it was."
msgstr ""
+"Verifica a última vez em que nick foi visto a entrar, sair\n"
+"ou a mudar de nickname na rede e informa-lhe quando e, dependendo\n"
+"das configurações do canal ou do utilizador, onde aconteceu."
-#, fuzzy
msgid "Checks if last memo to a nick was read"
-msgstr " CHECK Verifica se o último memo enviado para um nick foi lido"
+msgstr "Verifica se o último memo enviado para um nickname foi lido"
-#, fuzzy
msgid ""
"Checks whether the _last_ memo you sent to nick has been read\n"
"or not. Note that this only works with nicks, not with channels."
msgstr ""
-"Sintaxe: CHECK nick\n"
-"\n"
-"Verifica se o último memo que você enviou para nick\n"
-"foi lido ou não. Observe que isso só funciona com nicks,\n"
-"nunca com canais."
+"Verifica se o _último_ memo que enviou para nick foi lido\n"
+"ou não. Note que isto funciona apenas com nicknames, não com canais."
#, c-format
msgid "Cleared info from %s."
-msgstr ""
+msgstr "Informações de %s foram limpas."
-#, fuzzy
msgid "Colors kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Kicker de cores"
-#, fuzzy
msgid "Command"
-msgstr "Comandos do %s:"
+msgstr "Comando"
-#, fuzzy
msgid "Configures AMSG kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de AMSG"
-#, fuzzy
msgid "Configures badwords kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de palavrões"
-#, fuzzy
msgid "Configures bolds kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de negritos"
-#, fuzzy
msgid "Configures bot kickers. option can be one of:"
-msgstr ""
-"Sintaxe: SET opção parâmetros\n"
-"\n"
-"Ajusta várias opções de nick. A opção pode ser:"
+msgstr "Configura os kickers de bots. opção pode ser uma das seguintes:"
-#, fuzzy
msgid "Configures bot options"
-msgstr " SET Configura as opções do bot"
+msgstr "Configura as opções do bot"
-#, fuzzy
msgid ""
"Configures bot options.\n"
" \n"
"Available options:"
-msgstr " SET Configura as opções do bot"
+msgstr ""
+"Configura as opções do bot.\n"
+"\n"
+"Opções disponíveis:"
-#, fuzzy
msgid "Configures caps kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de maiúsculas"
-#, fuzzy
msgid "Configures channel logging settings"
-msgstr "* Impedido o registro de novos canais"
+msgstr "Configura as definições de registo de canais"
-#, fuzzy
msgid "Configures color kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de cores"
-#, fuzzy
msgid "Configures flood kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de flood"
-#, fuzzy
msgid "Configures italics kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de itálico"
-#, fuzzy
msgid "Configures kickers"
-msgstr " KICK Configura os kickers"
+msgstr "Configura os kickers"
-#, fuzzy
msgid "Configures repeat kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de repetições"
-#, fuzzy
msgid "Configures reverses kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de reverso"
-#, fuzzy
msgid "Configures the time bot bans expire in"
-msgstr " SET Configura as opções do bot"
+msgstr "Configura o tempo em que os banimentos de bots expiram"
-#, fuzzy
msgid "Configures underlines kicker"
-msgstr " KICK Configura os kickers"
+msgstr "Configura o kicker de sublinhados"
-#, fuzzy
msgid "Confirm a passcode"
-msgstr " CONFIRM Confirma um código de autorização do NickServ"
+msgstr "Confirme uma palavra-passe"
-#, fuzzy
msgid "Control modes and mode locks on a channel"
-msgstr " CLEARMODES Limpa os modos de um canal"
+msgstr "Modos de controlo e bloqueios de modo num canal"
-msgid ""
-"Controls what messages will be sent to users when they join the channel."
-msgstr ""
+msgid "Controls what messages will be sent to users when they join the channel."
+msgstr "Controla quais as mensagens que serão enviadas aos utilizadores quando entram no canal."
msgid ""
"Copies all settings, access, akicks, etc from channel to the\n"
@@ -3534,86 +3186,75 @@ msgid ""
"or LEVELS then only the respective settings are cloned.\n"
"You must be the founder of channel and target."
msgstr ""
+"Copia todas as configurações, acessos, kicks, etc, do canal para o\n"
+"canal alvo . Se quê for ACCESS, AKICK, BADWORDS,\n"
+"ou LEVELS então apenas as respectivas configurações serão clonadas.\n"
+"Deve ser o fundador do canal e do alvo."
-#, fuzzy
msgid "Copy all settings from one channel to another"
msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-#, fuzzy
msgid "Created"
-msgstr " Criado: %s"
+msgstr ""
-#, fuzzy
msgid "Creator"
-msgstr " Criado: %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Current %s list:"
-msgstr "Lista de AKILL atual:"
+msgstr ""
-#, fuzzy
msgid "Current AKILL list:"
-msgstr "Lista de AKILL atual:"
+msgstr ""
msgid "Current Session Limit Exception list:"
-msgstr "Atual lista de Limite de sessões:"
+msgstr ""
-#, fuzzy
msgid "Current module list:"
-msgstr "Lista de Módulos atual:"
+msgstr ""
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Número atual de AKILLs: %d"
+msgid "Current number of AKILLs: %zu"
+msgstr ""
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Número atual de SNLINEs: %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr ""
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Número atual de SQLINEs: %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr ""
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Usuários atuais: %d (%d ops)"
+msgid "Current users: %zu (%d ops)"
+msgstr ""
+
+msgid "DEL entry-num"
+msgstr ""
-#, fuzzy
msgid "DEL oper"
-msgstr "DEL <nick>."
+msgstr ""
-#, fuzzy
msgid "DEL target info"
-msgstr "GROUP alvo senha"
+msgstr ""
-#, fuzzy
msgid "DEL [nickname] channel"
-msgstr "MODE canal modos"
+msgstr ""
-#, fuzzy
msgid "DEL [nickname] fingerprint"
-msgstr "FORBID nick motivo"
-
-#, fuzzy
-msgid "DEL [nickname] mask"
-msgstr "MODE canal modos"
+msgstr ""
-#, fuzzy
msgid "DEL {mask | entry-num | list | id}"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr ""
-#, fuzzy
msgid "DEL {mask | entry-num | list}"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr ""
-#, fuzzy
msgid "DEL {nick|mask}"
-msgstr "DEL <nick>."
+msgstr ""
-#, fuzzy
msgid "DEL {num | ALL}"
-msgstr "OPERNEWS DEL {núm | ALL}"
+msgstr ""
msgid "DEL {NICK|CHAN|EMAIL|REGISTER} entry"
msgstr ""
@@ -3627,9 +3268,8 @@ msgstr ""
msgid "DELZONE zone.name"
msgstr ""
-#, fuzzy
msgid "DEPOOL server.name"
-msgstr "NOOP {SET|REVOKE} servidor"
+msgstr ""
#, c-format
msgid "Database cleared, removed %lu nicks that were added after %s."
@@ -3638,172 +3278,167 @@ msgstr ""
msgid "Date/Time"
msgstr ""
-#, fuzzy
msgid ""
"Deactivates the vhost currently assigned to the nick in use.\n"
"When you use this command any user who performs a /whois\n"
"on you will see your real host/IP address."
msgstr ""
-"Sintaxe: OFF\n"
-"Desativa o vhost atualmente associado ao nick em uso.\n"
-"Quando você usa este comando, qualquer usuário que faça um /whois\n"
-"em você irá ver seu endereço IP real/encriptado."
-#, fuzzy
msgid "Deactivates your assigned vhost"
-msgstr " OFF Desativa seu vHost associado"
+msgstr ""
#, c-format
msgid "Default AKILL expiry time: %d days"
-msgstr "Tempo atual de expiração de akill: %d dias"
+msgstr ""
#, c-format
msgid "Default AKILL expiry time: %d hours"
-msgstr "Tempo atual de expiração de akill: %d horas"
+msgstr ""
#, c-format
msgid "Default AKILL expiry time: %d minutes"
-msgstr "Tempo atual de expiração de akill: %d minutos"
+msgstr ""
msgid "Default AKILL expiry time: 1 day"
-msgstr "Tempo atual de expiração de akill: 1 dia"
+msgstr ""
msgid "Default AKILL expiry time: 1 hour"
-msgstr "Tempo atual de expiração de akill: 1 hora"
+msgstr ""
msgid "Default AKILL expiry time: 1 minute"
-msgstr "Tempo atual de expiração de akill: 1 minuto"
+msgstr ""
msgid "Default AKILL expiry time: No expiration"
-msgstr "Tempo atual de expiração de akill: Não expira"
+msgstr ""
#, c-format
msgid "Default SNLINE expiry time: %d days"
-msgstr "Tempo atual de expiração de SNLINE: %d dias"
+msgstr ""
#, c-format
msgid "Default SNLINE expiry time: %d hours"
-msgstr "Tempo atual de expiração de SNLINE: %d horas"
+msgstr ""
#, c-format
msgid "Default SNLINE expiry time: %d minutes"
-msgstr "Tempo atual de expiração de SNLINE: %d minutos"
+msgstr ""
msgid "Default SNLINE expiry time: 1 day"
-msgstr "Tempo atual de expiração de SNLINE: 1 dia"
+msgstr ""
msgid "Default SNLINE expiry time: 1 hour"
-msgstr "Tempo atual de expiração de SNLINE: 1 hora"
+msgstr ""
msgid "Default SNLINE expiry time: 1 minute"
-msgstr "Tempo atual de expiração de SNLINE: 1 minuto"
+msgstr ""
msgid "Default SNLINE expiry time: No expiration"
-msgstr "Tempo atual de expiração de SNLINE: Não expira"
+msgstr ""
#, c-format
msgid "Default SQLINE expiry time: %d days"
-msgstr "Tempo atual de expiração de SQLINE: %d dias"
+msgstr ""
#, c-format
msgid "Default SQLINE expiry time: %d hours"
-msgstr "Tempo atual de expiração de SQLINE: %d horas"
+msgstr ""
#, c-format
msgid "Default SQLINE expiry time: %d minutes"
-msgstr "Tempo atual de expiração de SQLINE: %d minutos"
+msgstr ""
msgid "Default SQLINE expiry time: 1 day"
-msgstr "Tempo atual de expiração de SQLINE: 1 dia"
+msgstr ""
msgid "Default SQLINE expiry time: 1 hour"
-msgstr "Tempo atual de expiração de SQLINE: 1 hora"
+msgstr ""
msgid "Default SQLINE expiry time: 1 minute"
-msgstr "Tempo atual de expiração de SQLINE: 1 minuto"
+msgstr ""
msgid "Default SQLINE expiry time: No expiration"
-msgstr "Tempo atual de expiração de SQLINE: Não expira"
+msgstr ""
-#, fuzzy
msgid "Define messages to be randomly shown to users at logon"
-msgstr " LOGONNEWS Define mensagens a serem mostradas na conexão"
+msgstr ""
-#, fuzzy
msgid "Define messages to be shown to users at logon"
-msgstr " LOGONNEWS Define mensagens a serem mostradas na conexão"
+msgstr ""
-#, fuzzy
msgid "Define messages to be shown to users who oper"
-msgstr " OPERNEWS Define mensagens a serem mostradas a quem pega Oper"
+msgstr ""
-#, fuzzy
msgid "Delete a memo or memos"
-msgstr " DEL Apaga a(s) mensagem(ns)"
+msgstr ""
-#, fuzzy
msgid "Delete the vhost of another user"
-msgstr " DEL Deleta o vHost de outro usuário"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Deleted %d entries from %s %s list."
-msgstr "Deletadas %d entradas da lista de AOP do %s."
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s access list."
-msgstr "Removidas %d entradas da lista de acesso do %s."
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s autokick list."
-msgstr "Removidas %d entradas da lista de akick do %s."
+msgstr ""
#, c-format
msgid "Deleted %d entries from %s bad words list."
-msgstr "Removidas %d entradas da lista de palavrões do %s."
+msgstr ""
#, c-format
msgid "Deleted %d entries from session-limit exception list."
-msgstr "Removidas %d entradas da lista de limite de sessões."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Deleted %d entries from the %s list."
-msgstr "Deletadas %d entradas da lista de AOP do %s."
+msgstr ""
#, c-format
msgid "Deleted %d entries from the AKILL list."
-msgstr "Removidas %d entradas da lista de AKILL."
+msgstr ""
+
+#, c-format
+msgid "Deleted %u entries from your message queue."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from %s access list."
-msgstr "Removida 1 entrada da lista de acesso do %s."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from %s autokick list."
-msgstr "Removida 1 entrada da lista de akick do %s."
+msgstr ""
#, c-format
msgid "Deleted 1 entry from %s bad words list."
-msgstr "Removida 1 entrada da lista de palavrões do %s."
+msgstr ""
msgid "Deleted 1 entry from session-limit exception list."
-msgstr "Removida 1 entrada da lista de limite de sessões."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Deleted 1 entry from the %s list."
-msgstr "Removida 1 entrada da lista de AKILL."
+msgstr ""
msgid "Deleted 1 entry from the AKILL list."
-msgstr "Removida 1 entrada da lista de AKILL."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Deleted info from %s."
-msgstr "Removida 1 entrada da lista de AKILL."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Deleted one entry from %s %s list."
-msgstr "Deletada 1 entrada da lista de AOP do %s."
+msgstr ""
+
+msgid "Deleted one entry from your message queue."
+msgstr ""
-#, fuzzy
msgid ""
"Deletes the specified memo or memos. You can supply\n"
"multiple memo numbers or ranges of numbers instead of a\n"
@@ -3820,64 +3455,38 @@ msgid ""
" DEL 2-5,7-9\n"
" Deletes memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Sintaxe: DEL [canal] {num | list | LAST | ALL}\n"
-"\n"
-"Apaga a(s) mensagem(ns) especificada(s). Você pode fornecer\n"
-"vários números de mensagens ou seqüências de números ao invés\n"
-"de um único número, como no segundo exemplo abaixo.\n"
-"Se LAST é fornecido, a última mensagem será apagada.\n"
-"Se ALL é fornecido, todas as suas mensagens serão apagadas.\n"
-"\n"
-"Exemplos:\n"
-"\n"
-" DEL 1\n"
-" Apaga sua primeira mensagem.\n"
-"\n"
-" DEL 2-5,7-9\n"
-" Apaga mensagens numeradas de 2 a 5 e de 7 a 9."
-#, fuzzy
msgid ""
"Deletes the vhost assigned to the given nick from the\n"
"database."
msgstr ""
-"Sintaxe: DEL <nick>\n"
-"Deleta o vhost associado ao nick dado."
-#, fuzzy
msgid "Deletes the vhost for all nicks in a group"
-msgstr " DELALL Deleta o vHost de todos os nicks de um grupo"
+msgstr ""
-#, fuzzy
msgid ""
"Deletes the vhost for all nicks in the same group as\n"
"that of the given nick."
msgstr ""
-"Sintaxe: DELALL <nick>.\n"
-"Deleta o vhost para todos os nicks no mesmo grupo do\n"
-"nick fornecido."
#, c-format
msgid "Depooled %s."
msgstr ""
-#, fuzzy
msgid "Description"
-msgstr "Descrição do canal %s alterada para %s."
+msgstr ""
#, c-format
msgid "Description of %s changed to %s."
-msgstr "Descrição do canal %s alterada para %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Description of %s unset."
-msgstr "Descrição do canal %s alterada para %s."
+msgstr ""
-#, fuzzy
msgid "Disabled"
-msgstr "%s está ativada"
+msgstr ""
-#, fuzzy
msgid ""
"Disallows anyone from using the given channel.\n"
"May be cancelled by using the UNSUSPEND\n"
@@ -3888,35 +3497,26 @@ msgid ""
" \n"
"Reason may be required on certain networks."
msgstr ""
-"Sintaxe: SUSPEND canal [motivo]\n"
-"\n"
-"Proibe qualquer um de registrar ou usar o canal dado.\n"
-"Pode ser cancelado usando o comando UNSUSPEND para\n"
-"preservar todos os dados/configurações anteriores do canal.\n"
-"\n"
-"Um motivo pode ser necessário em algumas redes."
-#, fuzzy, c-format
+#, c-format
msgid "Displayed %d records (%d total)."
-msgstr "Exibidos todos os registros (Contador: %d)"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Displayed all records (count: %d)."
-msgstr "Exibidos todos os registros (Contador: %d)"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Displayed records from %d to %d."
-msgstr "Exibidos registros de %d até %d"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Displayed records matching key %s (count: %d)."
-msgstr "Exibidos registros coincidindo com a chave %s (Contador: %d)"
+msgstr ""
-#, fuzzy
msgid "Displays information about a given nickname"
-msgstr " INFO Mostra informações sobre algum nick registrado"
+msgstr ""
-#, fuzzy
msgid ""
"Displays information about the given nickname, such as\n"
"the nick's owner, last seen address and time, and nick\n"
@@ -3924,39 +3524,27 @@ msgid ""
"your account name is used, else your current nickname is\n"
"used."
msgstr ""
-"Sintaxe: INFO nick\n"
-"\n"
-"Mostra a informação sobre o nick dado, como o dono do nick,\n"
-"último endereço utilizado e horário, e opções. Se você está\n"
-"identificado para o nick que você está obtendo informações\n"
-"e a opção ALL é especificada, será mostrado a você toda\n"
-"informação possível; independente de haver opções para esconder."
-#, fuzzy
msgid "Displays information about your memos"
-msgstr " INFO Exibe informações sobre suas mensagens"
+msgstr ""
-#, fuzzy
msgid "Displays one or more vhost entries"
-msgstr " LIST Exibe uma ou mais entradas de vHost"
+msgstr ""
-#, fuzzy
msgid "Displays the top 10 users of a channel"
-msgstr " FOUNDER Ajusta o fundador do canal"
+msgstr ""
msgid "Displays the top 10 users of the network"
msgstr ""
-#, fuzzy
msgid "Displays the top 3 users of a channel"
-msgstr " FOUNDER Ajusta o fundador do canal"
+msgstr ""
msgid "Displays the top 3 users of the network"
msgstr ""
-#, fuzzy
msgid "Displays this list and give information about commands"
-msgstr " INFO Exibe informações sobre suas mensagens"
+msgstr ""
msgid "Displays your Channel Stats"
msgstr ""
@@ -3968,23 +3556,23 @@ msgid "Don't use AMSGs!"
msgstr ""
msgid "Don't use bolds on this channel!"
-msgstr "Não use negritos neste canal!"
+msgstr ""
msgid "Don't use colors on this channel!"
-msgstr "Não use cores neste canal!"
+msgstr ""
msgid "Don't use italics on this channel!"
-msgstr "Don't use italics on this channel!"
+msgstr ""
msgid "Don't use reverses on this channel!"
-msgstr "Por favor não use reversos no canal!"
+msgstr ""
#, c-format
msgid "Don't use the word \"%s\" on this channel!"
-msgstr "Não use a palavra %s neste canal!"
+msgstr ""
msgid "Don't use underlines on this channel!"
-msgstr "Não use sublinhados neste canal!"
+msgstr ""
msgid ""
"Drops the given nick from the database. Once your nickname\n"
@@ -3994,18 +3582,6 @@ msgid ""
msgstr ""
#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "E-mail address for %s changed to %s."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "E-mail address for %s unset."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "E-mail para %s é inválido."
-
-#, fuzzy, c-format
msgid ""
"Edits or displays the list of logon news messages. When a\n"
"user connects to the network, these messages will be sent\n"
@@ -4013,20 +3589,8 @@ msgid ""
"sent in order to avoid flooding the user. If there are\n"
"more news messages, only the most recent will be sent."
msgstr ""
-"Syntax: LOGONNEWS ADD text\n"
-" LOGONNEWS DEL {num | ALL}\n"
-" LOGONNEWS LIST\n"
-"\n"
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. (However, no more than %s messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent.)\n"
-"NewsCount can be configured in services.conf.\n"
-"\n"
-"LOGONNEWS may only be used by Services Operators."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Edits or displays the list of oper news messages. When a\n"
"user opers up (with the /OPER command), these messages will\n"
@@ -4034,81 +3598,56 @@ msgid ""
"be sent in order to avoid flooding the user. If there are\n"
"more news messages, only the most recent will be sent."
msgstr ""
-"Syntax: OPERNEWS ADD text\n"
-" OPERNEWS DEL {num | ALL}\n"
-" OPERNEWS LIST\n"
-"\n"
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. (However, no more than %s messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent.)\n"
-"NewsCount can be configured in services.conf.\n"
-"\n"
-"OPERNEWS may only be used by Services Operators."
-#, fuzzy
msgid ""
"Edits or displays the list of random news messages. When a\n"
"user connects to the network, one (and only one) of the\n"
"random news will be randomly chosen and sent to them."
msgstr ""
-"Sintaxe: RANDOMNEWS ADD texto\n"
-" RANDOMNEWS DEL {núm | ALL}\n"
-" RANDOMNEWS LIST\n"
-"\n"
-"Edita ou mostra a lista de random news. Quando um usuário\n"
-"se conecta à rede, uma (apenas uma) das random news será\n"
-"aleatóriamente escolhida e enviada a ele.\n"
-"\n"
-"RANDOMNEWS may only be used by Services Operators."
-#, fuzzy
msgid "Email address"
-msgstr " E-mail: %s"
+msgstr ""
-#, fuzzy, c-format
-msgid "Email matched: %s (%s) to %s."
-msgstr "O nick %s usa o E-mail %s."
+#, c-format
+msgid "Email address for %s changed to %s."
+msgstr ""
+
+#, c-format
+msgid "Email address for %s unset."
+msgstr ""
+
+#, c-format
+msgid "Email for %s is invalid."
+msgstr ""
-msgid "Enable fantaisist commands"
+#, c-format
+msgid "Email matched: %s (%s) to %s."
msgstr ""
+msgid "Enable fantasy commands"
+msgstr "Ativa comandos de fantasia"
+
msgid "Enable greet messages"
msgstr ""
msgid "Enable or disable keep modes"
msgstr ""
-#, fuzzy
msgid "Enabled"
-msgstr "%s está ativada"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Enables or disables %s's autoop feature for a\n"
"channel. When disabled, users who join the channel will\n"
"not automatically gain any status from %s."
msgstr ""
-"Sintaxe: %s canal SECUREOPS {ON|OFF}\n"
-"\n"
-"Ativa ou desativa a opção de segurança de ops para um canal.\n"
-"Quando secure ops estiver ativada, os usuários que não\n"
-"estiverem na lista de acesso não poderão ter o status de OP."
-#, fuzzy
msgid ""
"Enables or disables keepmodes for the given channel. If keep\n"
"modes is enabled, services will remember modes set on the channel\n"
"and attempt to re-set them the next time the channel is created."
msgstr ""
-"Sintaxe: %s canal KEEPTOPIC {ON|OFF}\n"
-"\n"
-"Ativa ou desativa a opção de retenção de tópico para\n"
-"um canal. Quando a retenção de tópico está acionada,\n"
-"o tópico para o canal será lembrado pelo %s\n"
-"mesmo depois que os usuários deixarem o canal, e será\n"
-"restaurado na próxima vez que o canal for reutilizado."
msgid ""
"Enables or disables keepmodes for the given nick. If keep\n"
@@ -4122,22 +3661,6 @@ msgid ""
"and attempt to re-set them the next time you authenticate."
msgstr ""
-#, fuzzy
-msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Sintaxe: %s canal SECURE {ON|OFF}\n"
-"\n"
-"Ativa ou desativa os recursos de segurança do %s\n"
-"para um canal. Quando o SECURE estiver ativo, somente\n"
-"usuários que possuirem seus nicks registrados no %s\n"
-"e identificados com sua senha poderão entrar no canal\n"
-"controlado pela lista de acesso."
-
-#, fuzzy
msgid ""
"Enables or disables signed kicks for a\n"
"channel. When SIGNKICK is set, kicks issued with\n"
@@ -4148,47 +3671,24 @@ msgid ""
"or equal to the SIGNKICK level on the channel won't have their\n"
"kicks signed."
msgstr ""
-"Sintaxe: %s canal SIGNKICK {ON | LEVEL | OFF}\n"
-"\n"
-"Habilita ou desabilita a assinatura nos kicks para um\n"
-"canal. Quando o SIGNKICK está habilitado, kicks através\n"
-"do comando %s KICK terão o nick de quem usou o comando\n"
-"no motivo do kick.\n"
-"\n"
-"Se você usar LEVEL, aqueles que tiverem um nível igual ou \n"
-"superior ao nível do SIGNKICK não terão o nick aparecendo no \n"
-"motivo. Veja /msg %s HELP LEVELS para maiores informações. "
-#, fuzzy, c-format
+#, c-format
msgid ""
"Enables or disables the peace option for a channel.\n"
"When peace is set, a user won't be able to kick,\n"
"ban or remove a channel status of a user that has\n"
-"a level superior or equal to his via %s commands."
+"a level superior or equal to theirs via %s commands."
msgstr ""
-"Sintaxe: %s canal PEACE {ON | OFF}\n"
-"\n"
-"Ativa ou destiva a opção peace para um canal.\n"
-"Quando peace está ativada, um usuário não poderá kickar,\n"
-"banir ou remover os modos no canal de um usuário que tenha\n"
-"nível superior ou igual ao seu via comandos do %s."
msgid "Enables or disables the private option for a channel."
msgstr ""
-#, fuzzy
msgid ""
"Enables or disables the restricted access option for a\n"
"channel. When restricted access is set, users not on the access list will\n"
"instead be kicked and banned from the channel."
msgstr ""
-"Sintaxe: %s canal RESTRICTED {ON|OFF}\n"
-"\n"
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-#, fuzzy
msgid ""
"Enables or disables the secure founder option for a channel.\n"
"When secure founder is set, only the real founder will be\n"
@@ -4196,26 +3696,14 @@ msgid ""
"and not those who have founder level access through\n"
"the access/qop command."
msgstr ""
-"Sintaxe: %s canal SECUREFOUNDER {ON | OFF}\n"
-"\n"
-"Ativa ou desativa a opção secure founder para um canal.\n"
-"Quando o secure founder está ligado, apenas o verdadeiro founder\n"
-"poderá dar DROP no canal, mudar sua senha, seu founder e seu\n"
-"successor, e não aqueles que estiverem identificados no %s."
-#, fuzzy
msgid ""
"Enables or disables the secure ops option for a channel.\n"
"When secure ops is set, users who are not on the access list\n"
"will not be allowed channel operator status."
msgstr ""
-"Sintaxe: %s canal SECUREOPS {ON|OFF}\n"
-"\n"
-"Ativa ou desativa a opção de segurança de ops para um canal.\n"
-"Quando secure ops estiver ativada, os usuários que não\n"
-"estiverem na lista de acesso não poderão ter o status de OP."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Enables or disables the topic retention option for a\n"
"channel. When %s is set, the topic for the\n"
@@ -4223,15 +3711,8 @@ msgid ""
"last user leaves the channel, and will be restored the\n"
"next time the channel is created."
msgstr ""
-"Sintaxe: %s canal KEEPTOPIC {ON|OFF}\n"
-"\n"
-"Ativa ou desativa a opção de retenção de tópico para\n"
-"um canal. Quando a retenção de tópico está acionada,\n"
-"o tópico para o canal será lembrado pelo %s\n"
-"mesmo depois que os usuários deixarem o canal, e será\n"
-"restaurado na próxima vez que o canal for reutilizado."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Enables or disables the persistent channel setting.\n"
"When persistent is set, the service bot will remain\n"
@@ -4253,84 +3734,57 @@ msgid ""
"Additionally, services will set or unset this mode when you\n"
"set persist on or off."
msgstr ""
-"Syntax: %s channel PERSIST {ON | OFF}\n"
-"Enables or disables the persistant channel setting.\n"
-"When persistant is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-"\n"
-"If your IRCd does not a permanent (persistant) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-"\n"
-"If this network does not have BotServ enabled and does\n"
-"not have a permanent channel mode, ChanServ will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-"\n"
-"If your IRCd has a permanent (persistant) channel mode\n"
-"and is is set or unset (for any reason, including MLOCK),\n"
-"persist is automatically set and unset for the channel aswell.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-#, fuzzy
msgid "End of AKILL list."
-msgstr "Fim da listagem."
+msgstr ""
-#, fuzzy
msgid "End of access list"
-msgstr "Fim da lista de acesso."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "End of access list - %d/%d entries shown."
-msgstr "Fim da listagem - %d/%d resultados mostrados."
+msgstr ""
msgid "End of access list."
-msgstr "Fim da lista de acesso."
+msgstr ""
-#, fuzzy
msgid "End of autokick list"
-msgstr "Fim da lista de acesso."
+msgstr ""
-#, fuzzy
msgid "End of bad words list."
-msgstr "Fim da listagem."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "End of channel list. %u channels shown."
-msgstr "Fim da listagem - %d/%d resultados mostrados."
+msgstr ""
msgid "End of configuration."
msgstr ""
-#, fuzzy
msgid "End of entry message list."
-msgstr "Fim da listagem."
+msgstr ""
-#, fuzzy, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Fim da listagem - %d/%d resultados mostrados."
+#, c-format
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr ""
-#, fuzzy
msgid "End of forbid list."
-msgstr "Fim da listagem."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "End of list - %d channels shown."
-msgstr "Fim da listagem - %d/%d resultados mostrados."
+msgstr ""
#, c-format
msgid "End of list - %d/%d matches shown."
-msgstr "Fim da listagem - %d/%d resultados mostrados."
+msgstr ""
-#, fuzzy
msgid "End of news list."
-msgstr "Fim da listagem."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "End of users list. %u users shown."
-msgstr "Fim da listagem - %d/%d resultados mostrados."
+msgstr ""
msgid "Enforce various channel modes and set options"
msgstr ""
@@ -4352,46 +3806,42 @@ msgid ""
msgstr ""
msgid "English"
-msgstr "Português"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Entry message %i for %s deleted."
-msgstr "Greet message for %s unset."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Entry message %s not found on channel %s."
-msgstr "Modo Fantasia está agora ATIVADO no canal %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Entry message added to %s"
-msgstr "Greet message for %s changed to %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Entry message list for %s is empty."
-msgstr "Lista de acesso para %s está vazia."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Entry message list for %s:"
-msgstr "Lista de acesso para %s:"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Entry messages for %s have been cleared."
-msgstr "Todos os memos para o canal %s foram apagados."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Error reloading configuration file: %s"
-msgstr " RELOAD Recarrega o arquivo de configuração dos Services"
+msgstr ""
#, c-format
-msgid ""
-"Error! The vHost ident is too long, please use an ident shorter than %d "
-"characters."
+msgid "Error! The vhost is too long, please use a hostname shorter than %zu characters."
msgstr ""
#, c-format
-msgid ""
-"Error! The vHost is too long, please use a hostname shorter than %d "
-"characters."
+msgid "Error! The vident is too long, please use an ident shorter than %zu characters."
msgstr ""
msgid ""
@@ -4411,70 +3861,65 @@ msgstr ""
#, c-format
msgid "Exception for %s has been updated to %d."
-msgstr "Exceção para %s foi atualizada para %d."
+msgstr ""
-#, fuzzy
msgid "Expires"
-msgstr " Expira em: %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Expiry and reason updated for %s."
-msgstr "Exceção para %s foi atualizada para %d."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Expiry for %s updated."
-msgstr "Tempo de expiração para %s alterado."
+msgstr ""
msgid "Fantasy"
-msgstr "Fantasia"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Fantasy mode is now off on channel %s."
-msgstr "Modo Fantasia está agora ATIVADO no canal %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Fantasy mode is now on on channel %s."
-msgstr "Modo Fantasia está agora ATIVADO no canal %s."
+msgstr ""
-#, fuzzy
msgid "Find a user's status on a channel"
-msgstr " DEOWNER Retira seu status de Owner no canal"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Fingerprint %s already present on %s's certificate list."
-msgstr "A máscara %s já se encontra em sua lista de acesso."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Fingerprint %s is already in use."
-msgstr "You are already in %s! "
+msgstr ""
msgid "Flags"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Flags for %s on %s set to +%s"
-msgstr "Nível de acesso para %s no %s alterado para %d."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Flags list for %s"
-msgstr "Lista de acesso para %s:"
+msgstr ""
-#, fuzzy
msgid "Flood kicker"
-msgstr " Kick por flood: %s"
+msgstr ""
msgid ""
"Forbid allows you to forbid usage of certain nicknames, channels,\n"
"and email addresses. Wildcards are accepted for all entries."
msgstr ""
-#, fuzzy
msgid "Forbid list is empty."
-msgstr "Lista de Ignore dos Services vazia."
+msgstr ""
-#, fuzzy
msgid "Forbid list:"
-msgstr "Lista de bots:"
+msgstr ""
#, c-format
msgid "Forbid on %s was not found."
@@ -4483,54 +3928,36 @@ msgstr ""
msgid "Forbid usage of nicknames, channels, and emails"
msgstr ""
-#, fuzzy
-msgid "Force the Services databases to be updated immediately"
-msgstr " UPDATE Salva os dados atuais dos Services"
+msgid "Force the services databases to be updated immediately"
+msgstr ""
-#, fuzzy
msgid "Forcefully change a user's nickname"
-msgstr " SVSNICK Força a mudança do nick de um usuário"
+msgstr ""
-#, fuzzy
msgid "Forcefully changes a user's nickname from nick to newnick."
msgstr ""
-"Sintaxe: SVSNICK nick novo-nick\n"
-"\n"
-"Força a mudança do nick de um usuário, de nick a novo-nick."
-#, fuzzy
msgid "Forcefully join a user to a channel"
-msgstr " SVSNICK Força a mudança do nick de um usuário"
+msgstr ""
-#, fuzzy
msgid "Forcefully join a user to a channel."
-msgstr " SVSNICK Força a mudança do nick de um usuário"
+msgstr ""
-#, fuzzy
msgid "Forcefully part a user from a channel"
-msgstr " KICK Kicka um usuário de um canal"
+msgstr ""
-#, fuzzy
msgid "Forcefully part a user from a channel."
-msgstr " KICK Kicka um usuário de um canal"
+msgstr ""
-#, fuzzy
msgid "Founder"
-msgstr "Founder Seguro"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Founder of %s changed to %s."
-msgstr "Founder do canal %s alterado para %s."
-
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "Comando GETPASS não disponível: modo de encriptação ativado."
+msgstr ""
msgid "Ghost with your nick has been killed."
-msgstr "Seu nick foi derrubado e pode ser usado."
-
-#, fuzzy
-msgid "Give Operflags to a certain user"
-msgstr " OLINE Dá flags de Operador a um determinado usuário"
+msgstr ""
#, c-format
msgid ""
@@ -4538,59 +3965,55 @@ msgid ""
"not given, it will %s you."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Gives you or the specified nick %s status on a channel"
-msgstr " OWNER Concede-lhe status de Owner no canal"
+msgstr ""
msgid "Greet"
-msgstr "Mensagem de entrada"
+msgstr ""
-#, fuzzy
msgid "Greet message displayed on join"
-msgstr "Greet message for %s changed to %s."
+msgstr ""
#, c-format
msgid "Greet message for %s changed to %s."
-msgstr "Greet message for %s changed to %s."
+msgstr ""
#, c-format
msgid "Greet message for %s unset."
-msgstr "Greet message for %s unset."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Greet mode is now off on channel %s."
-msgstr "Modo mensagem de entrada está agora ATIVADO no canal %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Greet mode is now on on channel %s."
-msgstr "Modo mensagem de entrada está agora ATIVADO no canal %s."
+msgstr ""
-#, fuzzy
msgid "Helps you reset lost passwords"
-msgstr " RESETPASS Helps you reset lost passwords"
+msgstr ""
-#, fuzzy
msgid "Hide certain pieces of nickname information"
-msgstr " HIDE Esconde certas informações sobre seu nick"
+msgstr ""
-#, fuzzy
msgid "Hide channel from the LIST command"
-msgstr " PRIVATE Esconde o canal do comando LIST"
+msgstr ""
msgid "Host"
msgstr ""
#, c-format
msgid "Hosts with at least %d sessions:"
-msgstr "Hosts com pelo menos %d sessões:"
+msgstr ""
#, c-format
msgid "I don't know who %s is."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "I've never seen %s on this channel."
-msgstr "Por favor não use reversos no canal!"
+msgstr ""
msgid "ID"
msgstr ""
@@ -4601,54 +4024,49 @@ msgstr ""
msgid "IP"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "IP %s already exists for %s."
-msgstr "Bot %s já existe."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "IP %s does not exist for %s."
-msgstr "Bot %s já existe."
+msgstr ""
-#, fuzzy
msgid "Identify yourself with your password"
-msgstr " IDENTIFY Identifica seu nick com sua senha"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "If you do not change within %s, I will change your nick."
-msgstr "Se você não mudar seu nick em 20 segundos, eu irei mudá-lo."
+msgstr ""
msgid "Ignore list has been cleared."
-msgstr "Lista de Ignore foi apagada."
+msgstr ""
msgid "Ignore list is empty."
-msgstr "Lista de Ignore dos Services vazia."
+msgstr ""
-#, fuzzy
msgid "Ignore list:"
-msgstr "Lista de bots:"
+msgstr ""
-#, fuzzy
msgid "Immediate protection"
-msgstr "Proteção de Voices"
+msgstr ""
-#, fuzzy
msgid "Incorrect email address."
-msgstr " E-mail: %s"
+msgstr ""
msgid "Incorrect range specified. The correct syntax is #from-to."
msgstr ""
-#, fuzzy
msgid "Info about a loaded module"
-msgstr " MODINFO Informação sobre um módulo carregado"
+msgstr ""
#, c-format
-msgid "Information for bot %s:"
-msgstr "Informações do bot %s:"
+msgid "Information about bot %s:"
+msgstr ""
-#, fuzzy, c-format
-msgid "Information for channel %s:"
-msgstr "Informações do bot %s:"
+#, c-format
+msgid "Information about channel %s:"
+msgstr ""
#, c-format
msgid "Invalid duration %s, using %d days."
@@ -4657,94 +4075,72 @@ msgstr ""
msgid "Invalid expiry time."
msgstr ""
-#, fuzzy
-msgid ""
-"Invalid hostmask. Only real hostmasks are valid, as exceptions are not "
-"matched against nicks or usernames."
+msgid "Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames."
msgstr ""
-"Máscara inválida. Apenas máscaras (hosts) são válidas como exceções aos "
-"limites de sessões. Nick ou username não são válidos."
#, c-format
msgid "Invalid limit %s, using %d."
msgstr ""
-msgid ""
-"Invalid passcode has been entered, please check the e-mail again, and retry."
+msgid "Invalid passcode has been entered, please check the email again, and retry."
msgstr ""
msgid "Invalid passcode."
msgstr ""
#, c-format
-msgid ""
-"Invalid session limit. It must be a valid integer greater than or equal to "
-"zero and less than %d."
+msgid "Invalid session limit. It must be a valid integer greater than or equal to zero and less than %d."
msgstr ""
-"Limite de sessão inválida. O limite deve ser um número inteiro maior ou "
-"igual a zero e menor que %d."
msgid "Invalid threshold value. It must be a valid integer greater than 1."
-msgstr "Número inválido. Deve ser um número inteiro maior que 1."
+msgstr ""
msgid "Invalid value for LIMIT. Must be numerical."
msgstr ""
-#, fuzzy
msgid "Invites you or an optionally specified nick into a channel"
-msgstr " OP Atribui status de OP a um nick no canal"
+msgstr ""
-#, fuzzy
msgid "Italics kicker"
-msgstr " Italics kicker : %s"
+msgstr ""
-#, fuzzy
msgid "Join a group"
-msgstr " GROUP Se junta a um grupo"
+msgstr ""
-#, fuzzy
msgid "Keep modes"
-msgstr "Modo mensagem"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Keep modes for %s is now off."
-msgstr "Opção Peace para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Keep modes for %s is now on."
-msgstr "Opção Peace para %s está agora ATIVADA."
+msgstr ""
msgid "Key"
msgstr ""
#, c-format
msgid "Key for channel %s is %s."
-msgstr "Key for channel %s is %s."
+msgstr ""
-#, fuzzy
msgid "Kick a user from a channel"
-msgstr " KICK Kicka um usuário de um canal"
+msgstr ""
#, c-format
msgid "Kicked %d/%d users matching %s from %s."
msgstr ""
-#, fuzzy
msgid "Kicks a specified nick from a channel"
-msgstr " KICK Kicka (expulsa) um nick de um canal"
+msgstr ""
-#, fuzzy
msgid ""
"Kicks a specified nick from a channel.\n"
" \n"
"By default, limited to AOPs or those with level 5 access\n"
"and above on the channel. Channel founders can also specify masks."
msgstr ""
-"Sintaxe: KICK #canal nick [motivo]\n"
-"\n"
-"Kicka (expulsa) um nick dado em um determinado canal.\n"
-"Por padrão, é limitado aos AOPs ou àqueles que possuem\n"
-"nível de acesso 5 ou superior no canal."
msgid "Kill a user"
msgstr ""
@@ -4753,126 +4149,106 @@ msgid "LIMIT enforced by "
msgstr ""
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
+msgid "LIMIT enforced on %s, %zu users removed."
msgstr ""
msgid "LIST threshold"
msgstr ""
-#, fuzzy
msgid "LIST [mask | list | id]"
-msgstr "LIST [canal] [list | NEW]"
+msgstr ""
-#, fuzzy
msgid "LIST [mask | list]"
-msgstr "LIST [canal] [list | NEW]"
+msgstr ""
-#, fuzzy
msgid "LIST [nickname]"
-msgstr "CHECK nick"
+msgstr ""
msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "LOGONNEWS {ADD|DEL|LIST} [texto|núm]"
+msgstr ""
msgid "Language changed to English."
-msgstr "Linguagem alterada para Português."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Language for %s changed to %s."
-msgstr "Successor do canal %s alterado para %s."
+msgstr ""
#, c-format
msgid "Last memo to %s has been cancelled."
-msgstr "Último memo enviado para %s foi cancelado."
+msgstr ""
-#, fuzzy
msgid "Last quit message"
-msgstr "Última mensagem de saída: %s"
+msgstr ""
-#, fuzzy
msgid "Last seen"
-msgstr " Último horário visto: %s"
+msgstr ""
-#, fuzzy
msgid "Last seen address"
-msgstr " Último endereço visto: %s"
+msgstr ""
msgid "Last topic"
msgstr ""
-#, fuzzy
msgid "Last used"
-msgstr " Último horário visto: %s"
+msgstr ""
-#, fuzzy
msgid "Last usermask"
-msgstr " Último horário visto: %s"
+msgstr ""
msgid "Level"
msgstr ""
#, c-format
msgid "Level for %s on channel %s changed to %d."
-msgstr "Nível para %s no canal %s alterado para %d."
+msgstr ""
#, c-format
msgid "Level for %s on channel %s changed to founder only."
-msgstr "Level for %s on channel %s changed to founder only."
+msgstr ""
#, c-format
msgid "Level must be between %d and %d inclusive."
-msgstr "O nível deve ser entre %d e %d inclusive."
+msgstr ""
msgid "Limit"
msgstr ""
-#, fuzzy
msgid "List all registered nicknames that match a given pattern"
msgstr ""
-" LIST Lista todos os nicks registrados que combinam com o padrão "
-"fornecido"
-#, fuzzy
msgid "List channels you have access on"
-msgstr " ALIST Lista todos os canais nos quais você tem acesso"
+msgstr ""
#, c-format
msgid "List for mode %c is full."
msgstr ""
-#, fuzzy
msgid "List loaded modules"
-msgstr " MODLIST Lista os módulos carregados"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "List of entries matching %s:"
-msgstr "Lista de nicks no grupo %s:"
+msgstr ""
#, c-format
msgid "List of nicknames in the group of %s:"
-msgstr "Lista de nicks no grupo %s:"
+msgstr ""
msgid "List of nicknames in your group:"
-msgstr "Lista de nicks no grupo:"
+msgstr ""
-#, fuzzy
msgid "List your memos"
-msgstr " LIST Lista suas mensagens"
+msgstr ""
-#, fuzzy
msgid ""
"Lists all available bots on this network.\n"
"Bots prefixed by a * are reserved for IRC Operators."
msgstr ""
-"Sintaxe: BOTLIST\n"
-"\n"
-"Lista todos os bots disponíveis nesta Rede."
-#, fuzzy
msgid "Lists all channel records"
-msgstr " CHANLIST Lista todos os canais em uso na Rede"
+msgstr ""
-#, fuzzy
msgid ""
"Lists all channels currently in use on the IRC network, whether they\n"
"are registered or not.\n"
@@ -4882,14 +4258,6 @@ msgid ""
"specified, lists only channels matching pattern that have the +s or\n"
"+p mode."
msgstr ""
-"Sintaxe: CHANLIST [{padrão | nick} [SECRET]]\n"
-"\n"
-"Lista todos os canais em uso na Rede, sejam eles registrados ou não.\n"
-"\n"
-"Se um padrão é fornecido, listará apenas canais que combinem com\n"
-"ele. Se um nick é fornecido, listará apenas canais que o usuário\n"
-"estiver usando. Se SECRET é especificado, listará apenas canais\n"
-"combinando com o padrão e que tenham modo +s ou +p."
msgid ""
"Lists all channels you have access on.\n"
@@ -4899,17 +4267,12 @@ msgid ""
"limited to Services Operators"
msgstr ""
-#, fuzzy
msgid "Lists all nicknames in your group"
-msgstr "Lista de nicks no grupo:"
+msgstr ""
-#, fuzzy
msgid "Lists all registered channels matching the given pattern"
msgstr ""
-" LIST Lista todos os canais registrados que combinam com o padrão "
-"fornecido"
-#, fuzzy
msgid ""
"Lists all registered channels matching the given pattern.\n"
"Channels with the PRIVATE option set will only be\n"
@@ -4938,35 +4301,7 @@ msgid ""
" LIST #51-100\n"
" Lists all registered channels within the given range (51-100)."
msgstr ""
-"Sintaxe: LIST padrão [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\n"
-"\n"
-"Lista todos os nicks registrados que combinem com o padrão\n"
-"fornecido (formato nick!ident@host). Nicks com opção PRIVATE\n"
-"serão somente exibidos para os Administradores dos Services.\n"
-"Nicks com opção NOEXPIRE ajustada terão um ! preposto ao nick\n"
-"na lista quando for a pedido de Administrador dos Services.\n"
-"\n"
-"Se as opções FORBIDDEN, SUSPENDED, NOEXPIRE ou UNCONFIRMED são fornecidas, "
-"apenas\n"
-"nicks que são, respectivamente, FORBIDDEN, SUSPENDED, UNCONFIRMED ou têm a "
-"opção\n"
-"NOEXPIRE ativa, serão exibidos. Se todas as três opções forem fornecidas,\n"
-"todos os três tipos de nicks serão exibidos. Estas opções são limitas aos\n"
-"Administradores dos Services.\n"
-"\n"
-"Exemplos:\n"
-"\n"
-" LIST *!ident@servidor.com.br\n"
-" Lista todos os nicks de *!ident@servidor.com.br.\n"
-"\n"
-" LIST *Bot*!*@*\n"
-" Lista todos os nicks registrados com Bot em seus nomes.\n"
-"\n"
-" LIST * NOEXPIRE\n"
-" Lista todos os nicks registrados cujos registros foram\n"
-" ajustados para não expirar."
-#, fuzzy
msgid ""
"Lists all registered nicknames which match the given\n"
"pattern, in nick!user@host format. Nicks with the PRIVATE\n"
@@ -4997,61 +4332,20 @@ msgid ""
" LIST #51-100\n"
" Lists all registered nicks within the given range (51-100)."
msgstr ""
-"Sintaxe: LIST padrão [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\n"
-"\n"
-"Lista todos os nicks registrados que combinem com o padrão\n"
-"fornecido (formato nick!ident@host). Nicks com opção PRIVATE\n"
-"serão somente exibidos para os Administradores dos Services.\n"
-"Nicks com opção NOEXPIRE ajustada terão um ! preposto ao nick\n"
-"na lista quando for a pedido de Administrador dos Services.\n"
-"\n"
-"Se as opções FORBIDDEN, SUSPENDED, NOEXPIRE ou UNCONFIRMED são fornecidas, "
-"apenas\n"
-"nicks que são, respectivamente, FORBIDDEN, SUSPENDED, UNCONFIRMED ou têm a "
-"opção\n"
-"NOEXPIRE ativa, serão exibidos. Se todas as três opções forem fornecidas,\n"
-"todos os três tipos de nicks serão exibidos. Estas opções são limitas aos\n"
-"Administradores dos Services.\n"
-"\n"
-"Exemplos:\n"
-"\n"
-" LIST *!ident@servidor.com.br\n"
-" Lista todos os nicks de *!ident@servidor.com.br.\n"
-"\n"
-" LIST *Bot*!*@*\n"
-" Lista todos os nicks registrados com Bot em seus nomes.\n"
-"\n"
-" LIST * NOEXPIRE\n"
-" Lista todos os nicks registrados cujos registros foram\n"
-" ajustados para não expirar."
-#, fuzzy
msgid "Lists all user records"
-msgstr " USERLIST Lista todos os usuários online na Rede"
+msgstr ""
-#, fuzzy
msgid ""
"Lists all users currently online on the IRC network, whether their\n"
"nick is registered or not.\n"
" \n"
"If pattern is given, lists only users that match it (it must be in\n"
"the format nick!user@host[#realname]). If channel is given, lists\n"
-"only users that are on the given channel. If INVISIBLE is specified, only "
-"users\n"
+"only users that are on the given channel. If INVISIBLE is specified, only users\n"
"with the +i flag will be listed."
msgstr ""
-"Sintaxe: USERLIST [{padrão | canal} [INVISIBLE]]\n"
-"\n"
-"Lista todos os usuários online na Rede, tenham eles nicks\n"
-"registrados ou não.\n"
-"\n"
-"Se um padrão é fornecido, listará apenas usuários que combinem\n"
-"com ele (deve estar no formato nick!ident@host). Se um canal é\n"
-"fornecido, listará apenas usuários que estão no canal dado.\n"
-"estiver usando. Se INVISIBLE é especificado, listará apenas usuários\n"
-"que tenham o modo +i."
-#, fuzzy
msgid ""
"Lists any memos you currently have. With NEW, lists only\n"
"new (unread) memos. Unread memos are marked with a \"*\"\n"
@@ -5060,29 +4354,16 @@ msgid ""
" LIST 2-5,7-9\n"
" Lists memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Sintaxe: LIST [canal] [list | NEW]\n"
-"\n"
-"Lista quaisquer mensagens que você tiver. Com NEW, lista apenas\n"
-"as novas mensagens (não lidas). Mensagens não lidas são marcadas\n"
-"com \"*\" à esquerda do número. Você também pode especificar uma\n"
-"lista de números, como no exemplo abaixo:\n"
-"\n"
-"LIST 2-5,7-9\n"
-" Lista mensagens numeradas de 2 a 5 e de 7 a 9."
-#, fuzzy
msgid "Lists available bots"
-msgstr " BOTLIST Lista os bots disponíveis"
+msgstr ""
-#, fuzzy
msgid "Lists currently loaded modules."
-msgstr " MODLIST Lista os módulos carregados"
+msgstr ""
-#, fuzzy
msgid "Lists information about the specified registered channel"
-msgstr " INFO Mostra informações sobre algum canal registrado"
+msgstr ""
-#, fuzzy
msgid ""
"Lists information about the specified registered channel,\n"
"including its founder, time of registration, last\n"
@@ -5091,27 +4372,16 @@ msgid ""
"successor, last topic set, settings and expiration\n"
"time will also be displayed when applicable."
msgstr ""
-"Sintaxe: INFO canal\n"
-"\n"
-"Lista as informações referentes ao canal registrado dado,\n"
-"incluindo seu fundador, data do registro, última vez que\n"
-"foi usado, descrição, e trava dos modos (se existirem).\n"
-"\n"
-"Se você está identificado como fundador do canal que está\n"
-"solicitando informações e a opção ALL é especificada,\n"
-"informações sobre a mensagem de entrada e sobre o sucessor\n"
-"do canal também serão mostradas."
-#, fuzzy
msgid "Load a module"
-msgstr " MODLOAD Carrega um módulo"
+msgstr ""
msgid "Local channels cannot be registered."
-msgstr "Canais locais não podem ser registrados."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Log list for %s:"
-msgstr "Lista de acesso para %s:"
+msgstr ""
#, c-format
msgid "Logging changed for command %s on %s, now using log method %s%s%s."
@@ -5131,18 +4401,18 @@ msgstr ""
#, c-format
msgid "Logon news item #%d deleted."
-msgstr "Logon news removido #%d."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Logon news item #%s not found!"
-msgstr "Logon news não encontrado #%d!"
+msgstr ""
msgid "Logon news items:"
-msgstr "Logon News itens:"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Logout from %s"
-msgstr "Lista de acesso para %s:"
+msgstr ""
#, c-format
msgid ""
@@ -5164,22 +4434,17 @@ msgstr ""
#, c-format
msgid ""
-"Mainly controls mode locks and mode access (which is different from channel "
-"access)\n"
+"Mainly controls mode locks and mode access (which is different from channel access)\n"
"on a channel.\n"
" \n"
-"The %s LOCK command allows you to add, delete, and view mode locks on a "
-"channel.\n"
-"If a mode is locked on or off, services will not allow that mode to be "
-"changed. The SET\n"
-"command will clear all existing mode locks and set the new one given, while "
-"ADD and DEL\n"
+"The %s LOCK command allows you to add, delete, and view mode locks on a channel.\n"
+"If a mode is locked on or off, services will not allow that mode to be changed. The SET\n"
+"command will clear all existing mode locks and set the new one given, while ADD and DEL\n"
"modify the existing mode lock.\n"
"Example:\n"
" MODE #channel LOCK ADD +bmnt *!*@*aol*\n"
" \n"
-"The %s SET command allows you to set modes through services. Wildcards * "
-"and ? may\n"
+"The %s SET command allows you to set modes through services. Wildcards * and ? may\n"
"be given as parameters for list and status modes.\n"
"Example:\n"
" MODE #channel SET +v *\n"
@@ -5188,20 +4453,16 @@ msgid ""
" MODE #channel SET -b ~c:*\n"
" Clears all extended bans that start with ~c:\n"
" \n"
-"The %s CLEAR command is an easy way to clear modes on a channel. what may "
-"be\n"
-"any mode name. Examples include bans, excepts, inviteoverrides, ops, "
-"halfops, and voices. If what\n"
+"The %s CLEAR command is an easy way to clear modes on a channel. what may be\n"
+"any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If what\n"
"is not given then all basic modes are removed."
msgstr ""
-#, fuzzy
msgid "Maintain the AutoKick list"
-msgstr " AKICK Faz a manutenção da Lista de Autokick"
+msgstr ""
-#, fuzzy
msgid "Maintains network bot list"
-msgstr " BOT Mantém a lista de bots da Rede"
+msgstr ""
#, c-format
msgid ""
@@ -5238,12 +4499,12 @@ msgid ""
"of -1."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Maintains the bad words list for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
+"type %s HELP KICK %s.\n"
" \n"
"The ADD command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -5255,198 +4516,126 @@ msgid ""
"be issued every time word is said by a user.\n"
" \n"
msgstr ""
-"Sintaxe: BADWORDS canal ADD palavra [SINGLE | START | END]\n"
-" BADWORDS canal DEL {palavra | núm-entrada | lista}\n"
-" BADWORDS canal LIST [máscara | lista]\n"
-" BADWORDS canal CLEAR\n"
-"\n"
-"Faz a manutenção da lista de palavrões em um canal.\n"
-"Essa lista determina quais são as palavras que deverão\n"
-"ser motivo de kick em um canal quando a opção BADWORDS\n"
-"estiver ativada. Para maiores informações, digite\n"
-"/msg %s HELP KICK BADWORDS.\n"
-"\n"
-"O comando BADWORDS ADD adiciona a palavra na lista\n"
-"de palavrões. A opção SINGLE, quando especificada, só\n"
-"kicka o usuário se ele escrever a palavra inteira.\n"
-"A opção START, quando especificada, irá kickar o usuário\n"
-"que escrever uma palavra que comece com a palavra.\n"
-"A opção END se tiver sido especificada só kicka o usuário\n"
-"que escrever uma palavra que termine com a palavra.\n"
-"Se você não especificar nada, o bot irá kickar sempre\n"
-"que a palavra for escrita pelo usuário.\n"
-"\n"
-"O comando BADWORDS DEL remove uma palavra da lista de\n"
-"palavrões de um determinado canal. Se uma lista de números\n"
-"de entrada for fornecida, essas entradas serão apagadas\n"
-"(veja o exemplo para LIST abaixo).\n"
-"\n"
-"O comando BADWORDS LIST mostra a lista de palavrões.\n"
-"Se forem usados coringas, apenas aquelas entradas com\n"
-"as determinadas máscaras serão mostradas. Se uma lista\n"
-"de números de entrada for dada, apenas aquelas entradas\n"
-"serão mostradas; por exemplo:\n"
-"\n"
-" BADWORDS #canal LIST 2-5,7-9\n"
-" Lista as entradas dos palavrões numeradas de 2 a 5\n"
-" e de 7 a 9.\n"
-"\n"
-"O comando BADWORDS CLEAR limpa todas entradas da lista."
-#, fuzzy
msgid "Maintains the bad words list"
-msgstr " BADWORDS Configura os palavrões"
+msgstr ""
-#, fuzzy
msgid "Makes the bot do the equivalent of a \"/me\" command"
msgstr ""
-" ACT Faz com que o bot faça o mesmo que o comando \"/me\""
-#, fuzzy
msgid ""
"Makes the bot do the equivalent of a \"/me\" command\n"
"on the specified channel using the specified text."
msgstr ""
-"Sintaxe: ACT canal texto\n"
-"\n"
-"Faz com que o bot faça o mesmo que o comando \"/me\"\n"
-"em um determinado canal com o determinado texto."
-#, fuzzy
msgid "Makes the bot say the specified text on the specified channel"
msgstr ""
-" SAY Faz com que o bot diga determinado texto no canal dado"
-#, fuzzy
msgid "Makes the bot say the specified text on the specified channel."
msgstr ""
-" SAY Faz com que o bot diga determinado texto no canal dado"
-#, fuzzy
msgid ""
"Makes the given message the greet of the nickname, that\n"
"will be displayed when joining a channel that has GREET\n"
"option enabled, provided that the user has the necessary\n"
"access on it."
msgstr ""
-"Syntax: SASET nickname GREET message\n"
-"\n"
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary \n"
-"access on it."
-#, fuzzy
msgid ""
"Makes the given message the greet of your nickname, that\n"
"will be displayed when joining a channel that has GREET\n"
"option enabled, provided that you have the necessary\n"
"access on it."
msgstr ""
-"Sintaxe: SET GREET mensagem\n"
-"\n"
-"Faz com que a mensagen escolhida se torne a sua mensagem\n"
-"de entrada que aparecerá sempre quando você entrar em um canal\n"
-"que tenha a opção GREET habilitada, e também tenha acesso a isto."
-#, fuzzy
msgid "Manage DNS zones for this network"
-msgstr "Você não pode remover o e-mail nesta Rede."
+msgstr ""
-#, fuzzy
msgid "Manage the channel's entry messages"
-msgstr " PERSIST Set the channel as permanent"
+msgstr ""
-#, fuzzy
msgid "Manage the memo ignore list"
-msgstr " IGNORE Modifica a lista de ignorados dos Services"
+msgstr ""
-#, fuzzy
msgid "Manage your auto join list"
-msgstr " AKICK Faz a manutenção da Lista de Autokick"
+msgstr ""
+
+msgid "Manages your pending message queue."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Manipulate the %s list"
-msgstr " AKILL Manipula a lista de AKILL"
+msgstr ""
-#, fuzzy
msgid "Manipulate the AKILL list"
-msgstr " AKILL Manipula a lista de AKILL"
+msgstr ""
-#, fuzzy
msgid "Manipulate the DefCon system"
-msgstr " DEFCON Manipula o sistema DefCon"
+msgstr ""
-#, fuzzy
msgid "Manipulate the topic of the specified channel"
-msgstr " TOPIC Modifica o tópico de um canal"
+msgstr ""
msgid "Mask"
msgstr ""
-#, fuzzy, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "A máscara %s já se encontra em sua lista de acesso."
-
msgid "Mask must be in the form user@host."
msgstr ""
-#, fuzzy
msgid "Masks and unregistered users may not be on access lists."
-msgstr "A máscara %s já se encontra em sua lista de acesso."
+msgstr ""
-#, fuzzy
msgid "Matches and returns all users that registered using given email"
msgstr ""
-" GETEMAIL Encontra e retorna todos os usuários que se\n"
-" registraram usando o email fornecido"
-#, fuzzy, c-format
+#, c-format
msgid "Matches for %s:"
-msgstr " Trava de modo: %s"
+msgstr ""
#, c-format
msgid "Maximum users: %d (%s)"
-msgstr "Máximo atingido: %d (%s)"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Memo %d from %s (%s)."
-msgstr " Trava de modo: %s"
+msgstr ""
#, c-format
msgid "Memo %d has been deleted."
-msgstr "Memo %d foi apagado."
+msgstr ""
+
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr ""
-#, fuzzy
msgid "Memo ignore list is empty."
-msgstr "Lista de Ignore dos Services vazia."
+msgstr ""
#, c-format
msgid "Memo limit disabled for %s."
-msgstr "Limite de memos desativado para %s."
+msgstr ""
#, c-format
msgid "Memo limit for %s set to %d."
-msgstr "Limite de memos para %s é agora de %d."
+msgstr ""
#, c-format
msgid "Memo limit for %s set to 0."
-msgstr "Limite de memos para %s é agora de 0."
+msgstr ""
#, c-format
msgid "Memo sent to %s."
-msgstr "Memo enviado para %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Memos for %s:"
-msgstr " Trava de modo: %s"
+msgstr ""
-#, fuzzy
msgid "Message"
-msgstr "GLOBAL mensagem"
+msgstr ""
msgid "Message mode"
-msgstr "Modo mensagem"
+msgstr ""
msgid "Method"
msgstr ""
@@ -5455,24 +4644,27 @@ msgstr ""
msgid "Missing parameter for mode %c."
msgstr ""
+#, c-format
+msgid "Missing passwords: %zu"
+msgstr ""
+
msgid "Mode"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Mode %s is a virtual mode and can't be cleared."
-msgstr "Nick %s é um nick ilegal e não pode ser usado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Mode %s is not a status or list mode."
-msgstr "%s não encontrado na lista de Ignore."
+msgstr ""
-#, fuzzy
msgid "Mode lock"
-msgstr " Trava de modo: %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Mode locks for %s:"
-msgstr " Trava de modo: %s"
+msgstr ""
msgid "Modes"
msgstr ""
@@ -5481,50 +4673,6 @@ msgstr ""
msgid "Modes cleared on %s and the channel destroyed."
msgstr ""
-#, fuzzy, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
-msgstr ""
-"Sintaxe: ACCESS ADD máscara\n"
-" ACCESS DEL máscara\n"
-" ACCESS LIST\n"
-"\n"
-"Modifica ou mostra a lista de acesso do seu nick. Esta é\n"
-"a lista de endereços a qual será automaticamente reconhecida\n"
-"pelo %s como as permitidas a usarem seu nick. Se você\n"
-"quer usar um nick de um endereço diferente, você deve usar o\n"
-"comando IDENTIFY para identificar-se ao %s\n"
-"\n"
-"Exemplos:\n"
-"\n"
-" ACCESS ADD nick@*.provedor.com.br\n"
-" Permite o acesso do usuário nick de qualquer\n"
-" máquina com o domínio provedor.com.br.\n"
-"\n"
-" ACCESS DEL nick@*.provedor.com.br\n"
-" Reverte o comando anterior\n"
-"\n"
-" ACCESS LIST\n"
-" Mostra a lista de acesso atual."
-
msgid ""
"Modifies or displays the certificate list for your nick.\n"
"If you connect to IRC and provide a client certificate with a\n"
@@ -5534,64 +4682,55 @@ msgid ""
" \n"
msgstr ""
-#, fuzzy
-msgid "Modify the Services ignore list"
-msgstr " IGNORE Modifica a lista de ignorados dos Services"
-
-#, fuzzy, c-format
+#, c-format
msgid "Modify the list of %s users"
-msgstr " AOP Modifica a lista de AOP (AutoOP) de um canal"
-
-#, fuzzy
-msgid "Modify the list of authorized addresses"
-msgstr " ACCESS Modifica a lista de endereços autorizados"
+msgstr ""
-#, fuzzy
msgid "Modify the list of privileged users"
-msgstr " ACCESS Modifica a lista de usuários privilegiados"
+msgstr ""
-#, fuzzy
msgid "Modify the nickname client certificate list"
-msgstr " IGNORE Modifica a lista de ignorados dos Services"
+msgstr ""
+
+msgid "Modify the services ignore list"
+msgstr ""
-#, fuzzy
msgid "Modify the session-limit exception list"
-msgstr " EXCEPTION Modifica a lista de limite de sessões"
+msgstr ""
#, c-format
msgid "Module %s is already loaded."
-msgstr "Module %s is already loaded."
+msgstr ""
#, c-format
msgid "Module %s isn't loaded."
-msgstr "Module %s isn't loaded."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Module %s loaded."
-msgstr "Módulo %s carregado"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Module %s reloaded."
-msgstr "Módulo %s carregado"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Module %s unloaded."
-msgstr "Módulo %s descarregado"
+msgstr ""
-#, fuzzy
msgid "Module Name"
-msgstr "Módulo %s carregado"
+msgstr ""
msgid "Module settings:"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Module: %s Version: %s Author: %s Loaded: %s"
-msgstr "Módulo: %s Versão: %s Autor: %s Carregado: %s"
+msgstr ""
#, c-format
msgid "Module: %s [%s] [%s]"
-msgstr "Módulo: %s [%s] [%s]"
+msgstr ""
msgid "Name"
msgstr ""
@@ -5599,194 +4738,195 @@ msgstr ""
msgid "Name Type"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Network stats for %s:"
-msgstr "Lista de acesso para %s:"
+msgstr ""
msgid "Never"
msgstr ""
-#, fuzzy
+msgid "Never-op"
+msgstr ""
+
msgid "Nick"
-msgstr "INFO nick"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s has been confirmed."
-msgstr "O nick %s foi desregistrado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is already an operator."
-msgstr "O nick %s já está registrado!"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is already confirmed."
-msgstr "O nick %s já está registrado!"
+msgstr ""
#, c-format
msgid "Nick %s is an illegal nickname and cannot be used."
-msgstr "Nick %s é um nick ilegal e não pode ser usado."
+msgstr ""
#, c-format
msgid "Nick %s is currently in use."
-msgstr "Nick %s está atualmente em uso."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is forbidden by %s: %s"
-msgstr "Nick %s está atualmente em uso."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is forbidden."
-msgstr "Nick %s não está em uso no momento."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is not a Services Operator."
-msgstr "%s is a services operator of type %s."
+msgstr ""
#, c-format
msgid "Nick %s is part of this Network's Services."
-msgstr "Nick %s é parte dos Services desta Rede."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s isn't currently in use."
-msgstr "Nick %s está atualmente em uso."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s isn't registered."
-msgstr "Nick %s registrado."
+msgstr ""
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Nick %s foi truncado para %d caracteres."
+msgid "Nick %s was truncated to %zu characters."
+msgstr ""
#, c-format
msgid "Nick %s will expire."
-msgstr "Nick %s will expire."
+msgstr ""
#, c-format
msgid "Nick %s will not expire."
-msgstr "Nick %s will not expire."
+msgstr ""
#, c-format
msgid "Nick %s doesn't have a memo from you."
-msgstr "O nick %s não possui nenhum memo seu."
+msgstr ""
#, c-format
msgid "Nick %s has been logged out."
-msgstr "O nick %s foi desconectado."
+msgstr ""
#, c-format
msgid "Nick %s has been ungrouped from %s."
-msgstr "Nick %s has been ungrouped from %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is currently suspended."
-msgstr "Nick %s foi suspendido."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is not in your group."
-msgstr "The nick %s is not in your group."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nick %s is not suspended."
-msgstr "Nick %s foi suspendido."
+msgstr ""
#, c-format
msgid "Nick %s is now released."
-msgstr "Nick %s foi liberado."
+msgstr ""
#, c-format
msgid "Nick %s is now suspended."
-msgstr "Nick %s foi suspendido."
+msgstr ""
+
+msgid "Nick registered"
+msgstr ""
#, c-format
-msgid "Nick too long, max length is %u characters."
+msgid "Nick too long, max length is %zu characters."
msgstr ""
#, c-format
msgid "Nickname %s has been dropped."
-msgstr "O nick %s foi desregistrado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nickname %s is already registered!"
-msgstr "O canal %s já está registrado!"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nickname %s may not be registered."
-msgstr "O canal %s não pode ser registrado."
-
-#, fuzzy, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr "O nick %s foi registrado em sua conta: %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Nickname %s registered."
-msgstr "Nick %s registrado."
+msgstr ""
-#, fuzzy
msgid "No auto-op"
-msgstr "Auto-op"
+msgstr ""
msgid "No bot"
-msgstr "Sem bot"
+msgstr ""
-#, fuzzy
msgid "No expire"
-msgstr "não expira"
+msgstr ""
#, c-format
msgid "No help available for %s."
-msgstr "Nenhuma ajuda disponível para %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No information about module %s is available."
-msgstr "Nenhuma informação sobre o módulo %s está disponível."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No limit is set on %s."
-msgstr "Limite de memos para %s é agora de %d."
+msgstr ""
msgid "No logon news items to delete!"
-msgstr "Nenhum logon news para remover!"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No matches for %s found."
-msgstr "Nenhum email listado para %s."
+msgstr ""
+
+msgid "No matching entries in your message queue."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No matching entries on %s %s list."
-msgstr "Resultado não encontrado na lista de AOP do %s."
+msgstr ""
#, c-format
msgid "No matching entries on %s access list."
-msgstr "Resultado não encontrado na lista de acesso do %s."
+msgstr ""
#, c-format
msgid "No matching entries on %s autokick list."
-msgstr "Nenhum resultado encontrado na lista de akick do %s."
+msgstr ""
#, c-format
msgid "No matching entries on %s bad words list."
-msgstr "Nenhum resultado correspondente encontrado na lista do %s."
+msgstr ""
msgid "No matching entries on session-limit exception list."
-msgstr "Nenhum resultado encontrado na lista de limite de sessões."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No matching entries on the %s list."
-msgstr "Resultado não encontrado na lista de AOP do %s."
+msgstr ""
msgid "No matching entries on the AKILL list."
-msgstr "Nenhum resultado equivalente na lista de AKILL."
+msgstr ""
msgid "No memo was cancelable."
-msgstr "Nenhum memo foi cancelado."
+msgstr ""
msgid "No memos to display."
msgstr ""
-#, fuzzy
msgid "No modules currently loaded matching that criteria."
-msgstr "Nenhum módulo carregado atualmente."
+msgstr ""
msgid "No one is using your nick, and services are not holding it."
msgstr ""
@@ -5795,17 +4935,17 @@ msgid "No oper block for your nick."
msgstr ""
msgid "No oper news items to delete!"
-msgstr "Nenhum OperNews para remover!"
+msgstr ""
msgid "No random news items to delete!"
-msgstr "Nenhum item RandomNews para deletar!"
+msgstr ""
msgid "No records to display."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No registrations matching %s were found."
-msgstr "* Impedido o registro de novos nicks"
+msgstr ""
#, c-format
msgid "No request for nick %s found."
@@ -5814,32 +4954,32 @@ msgstr ""
msgid "No signed kick when SIGNKICK LEVEL is used"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No stats for %s."
-msgstr "Lista de acesso para %s:"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No such info \"%s\" on %s."
-msgstr "%s has been invited to %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No users on %s match %s."
-msgstr "Modos do usuário %s alterados."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No-bot mode is now off on channel %s."
-msgstr "Modo NOBOT está agora ATIVADO no canal %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "No-bot mode is now on on channel %s."
-msgstr "Modo NOBOT está agora ATIVADO no canal %s."
+msgstr ""
#, c-format
msgid "Non-status modes cleared on %s."
msgstr ""
msgid "None"
-msgstr "Nenhuma"
+msgstr ""
#, c-format
msgid ""
@@ -5856,51 +4996,40 @@ msgid "Number"
msgstr ""
msgid "OPERNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "OPERNEWS {ADD|DEL|LIST} [texto|núm]"
+msgstr ""
-#, fuzzy
msgid "Online from"
-msgstr " Está online em: %s"
+msgstr ""
#, c-format
-msgid ""
-"Oper %s is configured in the configuration file(s) and can not be removed by "
-"this command."
+msgid "Oper %s is configured in the configuration file(s) and can not be removed by this command."
msgstr ""
msgid "Oper Info"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Oper info list for %s is empty."
-msgstr "Lista de acesso para %s está vazia."
+msgstr ""
#, c-format
msgid "Oper news item #%d deleted."
-msgstr "OperNews removido #%d."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Oper news item #%s not found!"
-msgstr "OperNews não encontrado #%d!"
+msgstr ""
msgid "Oper news items:"
-msgstr "Oper News itens:"
+msgstr ""
#, c-format
msgid "Oper privileges removed from %s (%s)."
msgstr ""
-#, fuzzy, c-format
-msgid "Oper type %s has not been configured."
-msgstr "O nick %s foi desregistrado."
-
#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "As Operflags %s foram adicionadas para %s."
-
-#, fuzzy, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "As Operflags %s foram adicionadas para %s."
+msgid "Oper type %s has not been configured."
+msgstr ""
#, c-format
msgid "Opertype %s has no allowed commands."
@@ -5915,101 +5044,93 @@ msgid "Opertype %s receives modes %s once identified."
msgstr ""
msgid "Ops protection"
-msgstr "Proteção de OPs"
+msgstr ""
-#, fuzzy
msgid "Options"
-msgstr " Opções: %s"
+msgstr ""
-#, fuzzy
msgid "POOL server.name"
-msgstr "NOOP {SET|REVOKE} servidor"
+msgstr ""
msgid "Param"
msgstr ""
msgid "Password accepted - you are now recognized."
-msgstr "Senha aceita - você está agora reconhecido."
+msgstr ""
-#, fuzzy
msgid "Password accepted."
-msgstr "Senha incorreta."
-
-msgid "Password authentication required for that command."
msgstr ""
-#, fuzzy, c-format
-msgid "Password for %s changed to %s."
-msgstr "Successor do canal %s alterado para %s."
-
-#, fuzzy, c-format
-msgid "Password for %s changed."
-msgstr "Senha para %s foi enviada."
-
#, c-format
-msgid "Password for %s is %s."
-msgstr "Senha para %s é %s."
+msgid "Password for %s changed."
+msgstr ""
-#, fuzzy
msgid "Password incorrect."
-msgstr "Senha incorreta."
+msgstr ""
#, c-format
msgid "Password reset email for %s has been sent."
-msgstr "Password reset email for %s has been sent."
+msgstr ""
+
+msgid "Passwords can not be changed right now. Please try again later."
+msgstr ""
+
+#, c-format
+msgid "Passwords encrypted with %s: %zu"
+msgstr ""
msgid "Peace"
-msgstr "Paz"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Peace option for %s is now off."
-msgstr "Opção Peace para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Peace option for %s is now on."
-msgstr "Opção Peace para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy
msgid "Persistent"
-msgstr "Persistant"
+msgstr ""
+
+#, c-format
+msgid "Please confirm that you want to drop %s with %s DROP %s %s"
+msgstr ""
-msgid "Please contact an Operator to get a vHost assigned to this nick."
+msgid "Please contact an Operator to get a vhost assigned to this nick."
msgstr ""
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab "
-"characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
-#, fuzzy
msgid "Please use a valid server name when juping."
-msgstr "Por favor, use um nome de servidor válido quando estiver \"jupando\"."
+msgstr ""
msgid "Please use the symbol of # when attempting to register."
msgstr ""
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Por favor aguarde %d segundos e tente novamente."
+msgid "Please wait %lu seconds and retry."
+msgstr ""
-#, fuzzy, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Por favor aguarde %d segundos antes de usar o comando SEND novamente."
+#, c-format
+msgid "Please wait %lu seconds before requesting a new vhost."
+msgstr ""
-#, fuzzy, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Por favor aguarde %d segundos antes de usar o comando SEND novamente."
+#, c-format
+msgid "Please wait %lu seconds before using the %s command again."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Por favor espere %d segundos antes de usar o comando GROUP novamente."
+msgid "Please wait %lu seconds before using the GROUP command again."
+msgstr ""
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
+msgid "Please wait %lu seconds before using the REGISTER command again."
msgstr ""
-"Por favor espere %d segundos antes de usar o comando REGISTER novamente."
#, c-format
msgid "Pooled %s."
@@ -6024,61 +5145,50 @@ msgstr ""
msgid "Prevent a bot from being assigned by non IRC operators"
msgstr ""
-#, fuzzy
msgid "Prevent a bot from being assigned to a channel"
msgstr ""
-" SUSPEND Previne um canal de ser registrado/usado,\n"
-" preservando os dados do canal e suas configurações"
-#, fuzzy
msgid "Prevent a channel from being used preserving channel data and settings"
msgstr ""
-" SUSPEND Previne um canal de ser registrado/usado,\n"
-" preservando os dados do canal e suas configurações"
-#, fuzzy
msgid "Prevent the channel from expiring"
-msgstr " NOEXPIRE Prevent the channel from expiring"
+msgstr ""
-#, fuzzy
msgid "Prevent the nickname from appearing in the LIST command"
msgstr ""
-" PRIVATE Prevent the nickname from appearing in a\n"
-" /msg %s LIST"
-#, fuzzy
msgid "Prevent the nickname from expiring"
-msgstr " NOEXPIRE Prevent the nickname from expiring"
+msgstr ""
-msgid "Prevents users being kicked by Services"
+msgid "Prevents users being kicked by services"
msgstr ""
msgid "Private"
-msgstr "Privado"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Private mode of bot %s is now off."
-msgstr "Modo Privado do bot %s está agora ATIVADO."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Private mode of bot %s is now on."
-msgstr "Modo Privado do bot %s está agora ATIVADO."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Private option for %s is now off."
-msgstr "Opção Private para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Private option for %s is now on."
-msgstr "Opção Private para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Private option is now off for %s."
-msgstr "Private option is now ON for %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Private option is now on for %s."
-msgstr "Private option is now ON for %s."
+msgstr ""
#, c-format
msgid "Privilege %s added to %s on %s, new flags are +%s"
@@ -6089,41 +5199,35 @@ msgid "Privilege %s removed from %s on %s, new flags are +%s"
msgstr ""
msgid "Protection"
-msgstr "Proteção"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Protection is now off for %s."
-msgstr "Protection is now ON for %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Protection is now on for %s, with a reduced delay."
-msgstr "Protection is now ON for %s, with a reduced delay."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Protection is now on for %s, with no delay."
-msgstr "Protection is now ON for %s, with no delay."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Protection is now on for %s."
-msgstr "Protection is now ON for %s."
+msgstr ""
-#, fuzzy
msgid ""
"Puts an AKILL for every nick on the specified channel. It\n"
"uses the entire real ident@host for every nick, and\n"
"then enforces the AKILL."
msgstr ""
-"Sintaxe: CHANKILL [+tempo] canal motivo\n"
-"Adiciona um AKILL para cada nick no canal especificado. Isso\n"
-"usa por completo todo o host real ident@host para cada nick;\n"
-"em seguida, força o AKILL."
-#, fuzzy
msgid "Quick protection"
-msgstr "Proteção de Voices"
+msgstr ""
msgid "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "RANDOMNEWS {ADD|DEL|LIST} [texto|núm]"
+msgstr ""
msgid "REGONLY enforced by "
msgstr ""
@@ -6131,39 +5235,35 @@ msgstr ""
msgid "RESTRICTED enforced by "
msgstr ""
-#, fuzzy
msgid "REVOKE server"
-msgstr "NOOP {SET|REVOKE} servidor"
+msgstr ""
#, c-format
msgid "Random news item #%d deleted."
-msgstr "RandomNews item #%d deletado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Random news item #%s not found!"
-msgstr "RandomNews item #%d não encontrado!"
+msgstr ""
msgid "Random news items:"
-msgstr "Random News itens:"
+msgstr ""
-#, fuzzy
msgid "Read a memo or memos"
-msgstr " READ Lê a(s) mensagem(ns)"
+msgstr ""
-#, fuzzy
msgid "Real name"
-msgstr " RealName: %s"
+msgstr ""
-#, fuzzy
msgid "Realname"
-msgstr " RealName: %s"
+msgstr ""
msgid "Reason"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Reason for %s updated."
-msgstr "Successor do canal %s removido."
+msgstr ""
msgid ""
"Recovers your nick from another user or from services.\n"
@@ -6174,17 +5274,14 @@ msgid ""
"forced off of the nick."
msgstr ""
-#, fuzzy
msgid "Redefine the meanings of access levels"
-msgstr " LEVELS Redefine os níveis de acesso"
+msgstr ""
-#, fuzzy
msgid "Regains control of your nick"
-msgstr " RELEASE Retoma a custódia do seu nick após um RECOVER"
+msgstr ""
-#, fuzzy
msgid "Regex is disabled."
-msgstr "%s está ativada"
+msgstr ""
#, c-format
msgid ""
@@ -6198,35 +5295,32 @@ msgid ""
"Enclose your pattern in // if this is desired."
msgstr ""
-#, fuzzy
msgid "Register a channel"
-msgstr " REGISTER Registra um nick"
+msgstr ""
-#, fuzzy
msgid "Register a nickname"
-msgstr " REGISTER Registra um nick"
+msgstr ""
-#, fuzzy
msgid "Registered"
-msgstr " Hora de registro: %s"
+msgstr ""
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
msgstr ""
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
msgstr ""
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
msgstr ""
#, c-format
msgid "Registered only enforced on %s."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Registers a channel in the %s database. In order\n"
"to use this command, you must first be a channel operator\n"
@@ -6238,28 +5332,10 @@ msgid ""
"\"founder\" of the channel. The channel founder is allowed\n"
"to change all of the channel settings for the channel;\n"
"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel."
+"channel operator privileges when they enter the channel."
msgstr ""
-"Sintaxe: REGISTER canal descrição\n"
-"\n"
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which must be included, is a\n"
-"general description of the channel's purpose.\n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel.\n"
-"See the ACCESS command (/msg %s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname. If you haven't,\n"
-"/msg %s HELP for information on how to do so."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Registers your nickname in the %s database. Once\n"
"your nick is registered, you can use the SET and ACCESS\n"
@@ -6276,98 +5352,48 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
-"Sintaxe: REGISTER senha [email]\n"
-"\n"
-"Registra seu nick no banco de dados do %s. Uma vez\n"
-"que seu nick está registrado, você pode usar os comandos\n"
-"SET e ACCESS para configurar as opções do seu nick como\n"
-"você preferir depois. Certifique-se de lembrar sua senha\n"
-"durante o registro, você precisará dela para fazer alterações\n"
-"no seu nick futuramente.\n"
-"(Lembre-se que maiúsculas diferem, como: ANOPE, Anope e \n"
-"anope são senhas diferentes!)\n"
-"\n"
-"Sugestões ao escolher sua senha:\n"
-"\n"
-"As senhas não devem ser de fácil adivinhação. Por exemplo,\n"
-"usar seu nome como senha é uma péssima idéia. Utilizar seu\n"
-"nick como senha é uma idéia muito pior e, de fato, o %s\n"
-"não permitirá isso. Da mesma maneira, senhas curtas são\n"
-"vulneráveis a testes de erro-e-acerto, então você deve\n"
-"escolher uma senha com pelo menos 5 caracteres. Finalmente,\n"
-"o caractere \"ESPAÇO\" não pode ser usado em senhas.\n"
-"\n"
-"O parâmetro email é opcional e servirá para setar um\n"
-"email para seu nick. Entretanto, o email pode ser obrigatório\n"
-"em algumas Redes de IRC.\n"
-"Sua privacidade é respeitada; este e-mail nunca será dado\n"
-"para terceiros.\n"
-"\n"
-"Este comando servirá também para criar um GRUPO para o seu\n"
-"nick, e irá permitir que você registre outros nicks e divida\n"
-"as mesmas configurações, os mesmos memos e os mesmos \n"
-"privilégios em canais. Para maiores informações neste recurso,\n"
-"digite /msg %s HELP GROUP."
-#, fuzzy
msgid "Registration is currently disabled."
-msgstr "Desculpe, o registro de canais está temporariamente desativado."
+msgstr ""
-#, fuzzy
msgid "Regulate the use of critical commands"
-msgstr " PEACE Regula o uso de comandos críticos"
+msgstr ""
-#, fuzzy
-msgid "Reject the requested vHost for the given nick."
-msgstr " STATUS Retorna o status do owner de um determinado nick"
+msgid "Reject the requested vhost for the given nick."
+msgstr ""
-#, fuzzy
-msgid "Reject the requested vHost of a user"
-msgstr " DEL Deleta o vHost de outro usuário"
+msgid "Reject the requested vhost of a user"
+msgstr ""
-#, fuzzy
msgid "Releases a suspended channel"
-msgstr " UNSUSPEND Libera um canal suspenso"
+msgstr ""
-#, fuzzy
msgid ""
"Releases a suspended channel. All data and settings\n"
"are preserved from before the suspension."
msgstr ""
-"Sintaxe: UNSUSPEND canal\n"
-"\n"
-"Libera um canal suspenso. Todos os dados e configurações\n"
-"são preservados de antes da suspensão."
-#, fuzzy
msgid "Reload a module"
-msgstr " MODLOAD Carrega um módulo"
+msgstr ""
-#, fuzzy
msgid "Reload services' configuration file"
-msgstr " RELOAD Recarrega o arquivo de configuração dos Services"
+msgstr ""
-#, fuzzy
msgid "Remove a nick from a group"
-msgstr " UNGROUP Remove a nick from a group"
+msgstr ""
-#, fuzzy
msgid "Remove all bans preventing a user from entering a channel"
msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-#, fuzzy
msgid "Remove all operators from a server remotely"
msgstr ""
-" NOOP Remove temporariamente todas as O:lines de um \n"
-" servidor remotamente"
-#, fuzzy, c-format
+#, c-format
msgid "Removed IP %s from %s."
-msgstr " Trava de modo: %s"
+msgstr ""
#, c-format
msgid "Removed server %s from zone %s."
@@ -6383,13 +5409,12 @@ msgid ""
"not given, it will de%s you."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Removes %s status from you or the specified nick on a channel"
-msgstr " OP Atribui status de OP a um nick no canal"
+msgstr ""
-#, fuzzy
msgid "Removes a selected nicks status from a channel"
-msgstr " KICK Kicka (expulsa) um nick de um canal"
+msgstr ""
msgid ""
"Removes a selected nicks status modes on a channel. If nick is\n"
@@ -6401,152 +5426,75 @@ msgstr ""
msgid "Removing %s because %s covers it."
msgstr ""
-#, fuzzy
msgid "Repeat kicker"
-msgstr " Kick por repetição: %s"
+msgstr ""
-#, fuzzy
-msgid "Request a vHost for your nick"
-msgstr "Não há endereço de email ajustado para o seu nick."
+msgid "Request a vhost for your nick"
+msgstr ""
msgid ""
-"Request the given vHost to be activated for your nick by the\n"
+"Request the given vhost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."
msgstr ""
-#, fuzzy
msgid "Resend registration confirmation email"
-msgstr " RELOAD Recarrega o arquivo de configuração dos Services"
+msgstr ""
-#, fuzzy
msgid "Restrict access to the channel"
-msgstr " RESTRICTED Acesso restrito ao canal"
+msgstr ""
-#, fuzzy
msgid "Restricted access"
-msgstr "Acesso restrito"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Restricted access option for %s is now off."
-msgstr "Opção de acesso restrito para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Restricted access option for %s is now on."
-msgstr "Opção de acesso restrito para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Restricted enforced on %s."
-msgstr "Acesso restrito"
+msgstr ""
-#, fuzzy
msgid "Retain modes when channel is not in use"
-msgstr " KEEPTOPIC Mantem o tópico quando o canal não está em uso"
+msgstr ""
-#, fuzzy
msgid "Retain topic when channel is not in use"
-msgstr " KEEPTOPIC Mantem o tópico quando o canal não está em uso"
-
-#, fuzzy
-msgid "Retrieve the password for a nickname"
-msgstr " GETPASS Recupera a senha de um determinado nick"
+msgstr ""
msgid "Retrieves the vhost requests"
msgstr ""
-#, fuzzy
msgid "Returns the key of the given channel"
-msgstr " GETKEY Retorna a key (do modo +k) do canal fornecido"
+msgstr ""
-#, fuzzy
msgid "Returns the key of the given channel."
-msgstr " GETKEY Retorna a key (do modo +k) do canal fornecido"
-
-#, fuzzy
-msgid "Returns the matching accounts that used given email."
-msgstr " GETKEY Retorna a key (do modo +k) do canal fornecido"
-
-#, fuzzy
-msgid "Returns the owner status of the given nickname"
-msgstr " STATUS Retorna o status do owner de um determinado nick"
-
-#, fuzzy
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
msgstr ""
-"Sintaxe: GETPASS nick\n"
-"\n"
-"Mostra a senha de um nick especificado.\n"
-"Note que sempre que este comando for usado, uma mensagem\n"
-"incluindo o nick da pessoa que emitiu o comando e o nick\n"
-"no qual foi usado serão gravados e enviados para WALLOPS/GLOBOPS.\n"
-"\n"
-"Este comando não fica disponível quando a encriptação está habilitada."
-#, fuzzy
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
+msgid "Returns the matching accounts that used given email."
msgstr ""
-"Sintaxe: STATUS nick...\n"
-"\n"
-"Retorna se o usuário que está usando um determinado nick\n"
-"é reconhecio como dono do nick. \n"
-"A resposta tem este formato:\n"
-"\n"
-" nick código-de-status account\n"
-"\n"
-"where nick is the nickname sent with the command,\n"
-"código-de-status is one of the following, and account\n"
-"is the account they are logged in as.\n"
-"\n"
-" 0 - usuário não está conectado ou o nick não está registrado\n"
-" 1 - usuário não reconhecido como dono do nick\n"
-" 2 - usuário reconhecido como dono só pela lista de acesso\n"
-" 3 - usuário reconhecido como dono via identificação por senha\n"
-"\n"
-"Até 16 nicks podem ser enviados com cada comando; o resto será\n"
-"ignorado. Se nenhum nick for fornecido, seu status será exibido."
-#, fuzzy
msgid "Reverses kicker"
-msgstr " Kick por reversos: %s"
+msgstr ""
-#, fuzzy
msgid "Reverses the effect of the IDENTIFY command"
-msgstr " LOGOUT Reverte o efeito do comando IDENTIFY"
+msgstr ""
-#, fuzzy
msgid "SET server"
-msgstr "NOOP {SET|REVOKE} servidor"
+msgstr ""
msgid "SET server.name option value"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "SSL certificate fingerprint accepted, you are now identified to %s."
-msgstr "Senha aceita - você está agora reconhecido."
+msgstr ""
-#, fuzzy
msgid "SSL certificate fingerprint accepted, you are now identified."
-msgstr "Senha aceita - você está agora reconhecido."
+msgstr ""
#, c-format
msgid "SSL only enforced on %s."
@@ -6555,162 +5503,104 @@ msgstr ""
msgid "SSLONLY enforced by "
msgstr ""
-#, fuzzy
-msgid "Save databases and restart Services"
-msgstr " RESTART Salva os dados e reinicia os Services"
+msgid "Save databases and restart services"
+msgstr ""
msgid "Searches logs for a matching pattern"
msgstr ""
-#, fuzzy
msgid "Secure founder"
-msgstr "Founder Seguro"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Secure founder option for %s is now off."
-msgstr "Opção Secure Founder para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Secure founder option for %s is now on."
-msgstr "Opção Secure Founder para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy
msgid "Secure ops"
-msgstr "OPs Seguros"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Secure ops option for %s is now off."
-msgstr "Opção Secure OPs para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Secure ops option for %s is now on."
-msgstr "Opção Secure OPs para %s está agora ATIVADA."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now off."
-msgstr "Opção Secure para %s está agora ATIVADA."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now on."
-msgstr "Opção Secure para %s está agora ATIVADA."
-
-#, fuzzy, c-format
-msgid "Secure option is now off for %s."
-msgstr "Secure option is now ON for %s."
-
-#, fuzzy, c-format
-msgid "Secure option is now on for %s."
-msgstr "Secure option is now ON for %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Secureops enforced on %s."
-msgstr "Secure option is now ON for %s."
-
-msgid "Security"
-msgstr "Segurança"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the access list."
msgstr ""
-"Digite /msg %s HELP SET opção para maiores informações\n"
-"sobre uma opção em particular."
+"Veja %s HELP %s para obter mais informações\n"
+"sobre a lista de acesso."
-#, fuzzy, c-format
+#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the flags system."
msgstr ""
-"Digite /msg %s HELP SET opção para maiores informações\n"
-"sobre uma opção em particular."
+"Veja %s HELP %s para obter mais informações\n"
+"sobre o sistema de flags."
-#, fuzzy
msgid "Send a memo to a nick or channel"
-msgstr " SEND Envia uma mensagem para um nick ou para um canal"
+msgstr ""
-#, fuzzy
msgid "Send a memo to all opers/admins"
-msgstr " STAFF Envia um memo para todos os opers/admins"
+msgstr ""
-#, fuzzy
msgid "Send a memo to all registered users"
-msgstr " SENDALL Envia um memo para todos os usuários registrados"
+msgstr ""
-#, fuzzy
msgid "Send a message to all users"
-msgstr " GLOBAL Envia uma mensagem para todos usuários"
+msgstr ""
+
+msgid "Send a message to all users on a server"
+msgstr ""
-#, fuzzy
msgid "Sender"
-msgstr "Founder Seguro"
+msgstr ""
-#, fuzzy
msgid "Sends a memo and requests a read receipt"
-msgstr " RSEND Envia um memo e pede uma confirmação de leitura"
+msgstr ""
-#, fuzzy
msgid ""
"Sends a passcode to the nickname with instructions on how to\n"
"reset their password. Email must be the email address associated\n"
"to the nickname."
msgstr ""
-"Syntax: RESETPASS nickname\n"
-"\n"
-"Sends a codekey to the nickname with the instructions on how to\n"
-"reset their psasword."
-#, fuzzy
msgid "Sends all registered users a memo containing memo-text."
msgstr ""
-"Sintaxe: SENDALL mensagem\n"
-"\n"
-"Envia um memo para todos os usuários registrados\n"
-"contendo uma mensagem."
-#, fuzzy
msgid "Sends all services staff a memo containing memo-text."
msgstr ""
-"Sintaxe: STAFF mensagem\n"
-"\n"
-"Envia um memo a todos os membros da Staff dos Services\n"
-"contendo uma mensagem."
-#, fuzzy
msgid ""
"Sends the named nick or channel a memo containing\n"
"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
+"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered."
msgstr ""
-"Sintaxe: SEND {nick | canal} mensagem\n"
-"\n"
-"Envia um memo ao nick ou ao canal determinado contendo\n"
-"a mensagem. Quando enviada para o destinatário, este\n"
-"receberá um aviso que possui uma nova mensagem. O nick/canal\n"
-"de destino deverá estar registrado."
-#, fuzzy
msgid ""
"Sends the named nick or channel a memo containing\n"
"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
+"receive a notice that they have a new memo. The target\n"
"nickname/channel must be registered.\n"
"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
+"memo will be sent to the sender informing them that the memo\n"
"has been read."
msgstr ""
-"Sintaxe: RSEND {nick | canal} mensagem\n"
-"\n"
-"Envia para um nick ou canal um memo contendo uma\n"
-"mensagem. Quando enviar a um nick, o destinatário receberá\n"
-"um aviso de que ele tem um novo memo. O destino (nick/canal)\n"
-"deve ser registrado.\n"
-"Uma vez que o memo for lido pelo destinatário, uma notificação\n"
-"automática será enviada ao remetente informando-o que o memo\n"
-"foi lido."
-#, fuzzy
msgid ""
"Sends you the text of the memos specified. If LAST is\n"
"given, sends you the memo you most recently received. If\n"
@@ -6722,251 +5612,210 @@ msgid ""
" READ 2-5,7-9\n"
" Displays memos numbered 2 through 5 and 7 through 9."
msgstr ""
-"Sintaxe: READ [canal] {núm | list | LAST | NEW}\n"
-"\n"
-"Mostra as mensagens especificadas. Se LAST é fornecido, envia\n"
-"a você a mensagem recebida mais recentemente. Se NEW é fornecido,\n"
-"envia a você todas as suas novas mensagens. Caso contrário, envia\n"
-"a você a mensagem de número núm. Você também pode fornecer uma\n"
-"lista de números, como neste exemplo:\n"
-"\n"
-"READ 2-5,7-9\n"
-" Mostra as mensagens numeradas de 2 a 5 e de 7 a 9."
-#, fuzzy
msgid "Server"
-msgstr "NOOP {SET|REVOKE} servidor"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
+msgid "Server %s is not linked to the network."
+msgstr ""
+
+#, c-format
msgid "Server %s added to zone %s."
-msgstr " %s (does not expire)"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s already exists."
-msgstr "Bot %s já existe."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s does not exist."
-msgstr " %s (does not expire)"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s has no configured IPs."
-msgstr "O nick %s foi desregistrado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s is already in zone %s."
-msgstr "You are already in %s! "
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s is already pooled."
-msgstr "Module %s is already loaded."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s is not currently linked."
-msgstr "%s está online neste momento."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s is not in zone %s."
-msgstr " %s (does not expire)"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s is not linked to the network."
-msgstr "Não possui mais nenhum bot associado ao canal %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Server %s is not pooled."
-msgstr " %s (does not expire)"
+msgstr ""
#, c-format
msgid "Server %s must be quit before it can be deleted."
msgstr ""
-#, fuzzy
msgid "Servers"
-msgstr "NOOP {SET|REVOKE} servidor"
+msgstr ""
#, c-format
msgid "Servers found: %d"
-msgstr "Servers found: %d"
+msgstr ""
-#, fuzzy
msgid "Service"
-msgstr "Servers found: %d"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Service's hold on %s has been released."
-msgstr "Seu nick foi derrubado e pode ser usado."
+msgstr ""
-#, fuzzy
msgid "Services Operator commands"
-msgstr "%s is a services operator of type %s."
+msgstr ""
-#, fuzzy
msgid "Services are in DefCon mode, please try again later."
msgstr ""
-"Este serviço está temporariamente desabilitado, por favor tente novamente "
-"mais tarde"
-#, fuzzy
-msgid "Services are in read-only mode!"
-msgstr "Services estão agora no modo somente leitura."
-
-#, fuzzy, c-format
+#, c-format
msgid "Services are now at DEFCON %d."
-msgstr "Services estão agora em DEFCON %d"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Services are now in debug mode (level %d)."
-msgstr "Services estão agora no modo debug (nível %d)."
+msgstr ""
-#, fuzzy
msgid "Services are now in debug mode."
-msgstr "Services estão agora no modo debug."
+msgstr ""
msgid "Services are now in expire mode."
-msgstr "Services estão agora no modo expira."
+msgstr ""
msgid "Services are now in no expire mode."
-msgstr "Services estão agora no modo não expira."
+msgstr ""
-#, fuzzy
msgid "Services are now in non-debug mode."
-msgstr "Services não estão mais no modo debug."
+msgstr ""
msgid "Services are now in read-only mode."
-msgstr "Services estão agora no modo somente leitura."
+msgstr ""
msgid "Services are now in read-write mode."
-msgstr "Services estão agora no modo leitura e gravação."
+msgstr ""
+
+msgid "Services are temporarily in read-only mode."
+msgstr ""
msgid "Services have been configured to not send mail."
-msgstr "Os services foram configurados para não enviar e-mail."
+msgstr ""
-#, fuzzy
msgid "Services ignore list:"
-msgstr " IGNORE Modifica a lista de ignorados dos Services"
+msgstr ""
-#, fuzzy
-msgid ""
-"Services is unable to change modes. Are your servers' U:lines configured "
-"correctly?"
+msgid "Services is unable to change modes. Are your servers' U:lines configured correctly?"
msgstr ""
-"Os Services não conseguiram alterar os modos. As U:lines dos seus servidores "
-"estão configuradas corretamente?"
-#, fuzzy, c-format
+#, c-format
msgid "Services up %s."
-msgstr "Servers found: %d"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Services will from now on set status modes on %s in channels."
-msgstr "Services will no longer autoop %s in channels."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Services will no longer automatically give modes to users in %s."
-msgstr "Services will no longer autoop %s in channels."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Services will no longer set status modes on %s in channels."
-msgstr "Services will no longer autoop %s in channels."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Services will now automatically give modes to users in %s."
-msgstr "Services will now autoop %s in channels."
+msgstr ""
#, c-format
msgid "Services will now reply to %s with messages."
-msgstr "Services will now reply to %s with messages."
+msgstr ""
#, c-format
msgid "Services will now reply to %s with notices."
-msgstr "Services will now reply to %s with notices."
+msgstr ""
-#, fuzzy
msgid "Services' configuration has been reloaded."
-msgstr "Arquivos de configuração dos Services foram recarregados."
+msgstr ""
msgid "Session"
msgstr ""
#, c-format
msgid "Session limit for %s set to %d."
-msgstr "Limite de sessões para %s é agora de %d."
+msgstr ""
msgid "Session limiting is disabled."
-msgstr "Opção de limite de sessões desabilitada."
+msgstr ""
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
msgstr ""
-#, fuzzy
msgid "Set SET-options on another nickname"
-msgstr " SASET Set SET-options on another nickname"
+msgstr ""
-#, fuzzy
msgid "Set channel options and information"
-msgstr " SET Ajusta as opções e informações do canal"
+msgstr ""
-#, fuzzy
-msgid "Set how Services make bans on the channel"
-msgstr " BANTYPE Ajusta como os Services devem fazer o ban"
+msgid "Set how services make bans on the channel"
+msgstr ""
-#, fuzzy
msgid "Set options related to memos"
-msgstr " SET Ajusta opções relacionadas às mensagens"
+msgstr ""
-#, fuzzy
msgid "Set options, including kill protection"
-msgstr " SET Ajusta opções, incluindo proteção de kill"
+msgstr ""
-#, fuzzy
msgid "Set the channel as permanent"
-msgstr " PERSIST Set the channel as permanent"
+msgstr ""
-#, fuzzy
msgid "Set the channel description"
-msgstr " DESC Ajusta a descrição do canal"
+msgstr ""
-#, fuzzy
-msgid "Set the display of your group in Services"
-msgstr " DISPLAY Mostra o seu grupo nos Services"
+msgid "Set the display of your group in services"
+msgstr ""
-#, fuzzy
msgid "Set the founder of a channel"
-msgstr " FOUNDER Ajusta o fundador do canal"
+msgstr ""
-#, fuzzy
-msgid "Set the language Services will use when messaging you"
+msgid "Set the language services will use when messaging you"
msgstr ""
-" LANGUAGE Ajusta a linguagem dos Services quando\n"
-" mensagens são enviadas à você"
-#, fuzzy
msgid "Set the nickname password"
-msgstr " PASSWORD Set the nickname password"
+msgstr ""
-#, fuzzy
msgid "Set the successor for a channel"
-msgstr " SUCCESSOR Ajusta o sucessor do canal"
+msgstr ""
-#, fuzzy
msgid "Set the vhost for all nicks in a group"
-msgstr " SETALL Ajusta o vHost de todos os nicks de um grupo"
+msgstr ""
-#, fuzzy
msgid "Set the vhost of another user"
-msgstr " SET Ajusta o vHost de outro usuário"
+msgstr ""
-#, fuzzy
-msgid "Set various global Services options"
-msgstr " SET Configura várias opções globais dos Services"
+msgid "Set various global services options"
+msgstr ""
-#, fuzzy
msgid "Set your nickname password"
-msgstr " PASSWORD Ajusta a senha do seu nick"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Sets the AMSG kicker on or off. When enabled, the bot will\n"
"kick users who send the same message to multiple channels\n"
@@ -6976,41 +5825,21 @@ msgid ""
"before they get banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Sets the bad words kicker on or off. When enabled, this\n"
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
+"BADWORDS command. Type %s HELP BADWORDS for\n"
"more information.\n"
" \n"
"ttb is the number of times a user can be kicked\n"
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal BADWORDS {ON|OFF} [ttb]\n"
-"\n"
-"Ativa ou desativa o kick por palavrões. Quando ativado\n"
-"o bot irá kickar usuários que disserem determinadas\n"
-"palavras no canal.\n"
-"\n"
-"Você pode definir os palavrões para um canal usando o\n"
-"comando BADWORDS. Digite /msg %s HELP BADWORDS para\n"
-"maiores informações.\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the ban type that will be used by services whenever\n"
"they need to ban someone from your channel.\n"
@@ -7022,19 +5851,7 @@ msgid ""
"2: ban in the form *!*@host\n"
"3: ban in the form *!*user@*.domain"
msgstr ""
-"Sintaxe: %s canal BANTYPE tipo-de-ban\n"
-"\n"
-"Seleciona o tipo de ban que será usado sempre que os Services\n"
-"precisarem banir alguém do seu canal.\n"
-"\n"
-"O tipo-de-ban é um número entre 0 e 3 que significa:\n"
-"\n"
-"0: ban na forma *!user@host\n"
-"1: ban na forma *!*user@host\n"
-"2: ban na forma *!*@host\n"
-"3: ban na forma *!*user@*.domain"
-#, fuzzy
msgid ""
"Sets the bolds kicker on or off. When enabled, this\n"
"option tells the bot to kick users who use bolds.\n"
@@ -7043,16 +5860,8 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal BOLDS {ON|OFF} [ttb]\n"
-"\n"
-"Ativa ou desativa o kick por negrito. Quando ativado\n"
-"o bot irá kickar os usuários que usarem negrito.\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Sets the caps kicker on or off. When enabled, this\n"
"option tells the bot to kick users who are talking in\n"
@@ -7066,21 +5875,7 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal CAPS {ON|OFF} [ttb [mínimo [porcentagem]]]\n"
-"\n"
-"Ativa ou desativa o kick por caps. Quando ativado\n"
-"o bot irá kickar os usuários que usarem CAPS (maiúsculas).\n"
-"\n"
-"O bot irá kickar apenas se usarem pelo menos um mínimo de\n"
-"caps e eles constituírem pelo menos porcentagem%% do total \n"
-"do texto (se não for especificado, o padrão é 10 caracteres\n"
-"e 25%%).\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the colors kicker on or off. When enabled, this\n"
"option tells the bot to kick users who use colors.\n"
@@ -7089,26 +5884,12 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal COLORS {ON|OFF} [ttb]\n"
-"\n"
-"Ativa ou desativa o kick por cores. Quando ativado\n"
-"o bot irá kickar os usuários que usarem cores.\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the description for the channel, which shows up with\n"
"the LIST and INFO commands."
msgstr ""
-"Sintaxe: %s canal DESC descrição\n"
-"\n"
-"Ajusta a descrição para o canal, que são mostradas com\n"
-"os comandos LIST e INFO."
-#, fuzzy
msgid ""
"Sets the flood kicker on or off. When enabled, this\n"
"option tells the bot to kick users who are flooding\n"
@@ -7119,19 +5900,7 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal FLOOD {ON|OFF} [ttb [linhas [segs]]]\n"
-"\n"
-"Ativa ou desativa o kick por flood. Quando ativado o\n"
-"o bot irá kickar por flood no canal desde que sejam\n"
-"pelo menos linhas linhas em segs segundos.\n"
-"(se não for especificado, o padrão é 6 linhas em\n"
-"10 segundos).\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the italics kicker on or off. When enabled, this\n"
"option tells the bot to kick users who use italics.\n"
@@ -7140,14 +5909,7 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-#, fuzzy
msgid ""
"Sets the repeat kicker on or off. When enabled, this\n"
"option tells the bot to kick users who are repeating\n"
@@ -7158,18 +5920,7 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal REPEAT {ON|OFF} [ttb [núm]]\n"
-"\n"
-"Ativa ou desativa o kick por repetição. Quando ativado\n"
-"o bot irá kickar os usuários que fizerem repetições (onde\n"
-"núm é o número de repetições para kick; se não for fornecido,\n"
-"o padrão é 3).\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the reverses kicker on or off. When enabled, this\n"
"option tells the bot to kick users who use reverses.\n"
@@ -7178,16 +5929,7 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal REVERSES {ON|OFF} [ttb]\n"
-"\n"
-"Ativa ou desativa o kick por reverso. Quando ativado\n"
-"o bot irá kickar os usuários que usarem reverso.\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the underlines kicker on or off. When enabled, this\n"
"option tells the bot to kick users who use underlines.\n"
@@ -7196,48 +5938,25 @@ msgid ""
"before it gets banned. Don't give ttb to disable\n"
"the ban system once activated."
msgstr ""
-"Sintaxe: KICK canal UNDERLINES {ON|OFF} [ttb]\n"
-"\n"
-"Ativa ou desativa o kick por sublinhado. Quando ativado\n"
-"o bot irá kickar os usuários que usarem sublinhado.\n"
-"\n"
-"ttb é o número de vezes que o usuário será kickado\n"
-"antes de ser banido. Não forneça ttb para desabilitar\n"
-"o sistema de ban que foi uma vez ativado."
-#, fuzzy
msgid ""
"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
+"of the given nick. If your IRCD supports vidents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
"added to the group after this command was used."
msgstr ""
-"Sintaxe: SETALL <nick> <hostmask>.\n"
-"Ajusta o vhost para todos os nicks no mesmo grupo do\n"
-"nick fornecido. Caso seu IRCd suporte vIdents, então\n"
-"usando SETALL <nick> <ident>@<hostmask> ajustará idents\n"
-"para usuários, assim como vhosts.\n"
-"* NOTA: isto não irá atualizar o vhost de nenhum nick\n"
-"adicionado ao grupo depois que o comando foi usado."
-#, fuzzy
msgid ""
"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
+"hostmask. If your IRCD supports vidents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."
msgstr ""
-"Sintaxe: SET <nick> <hostmask>.\n"
-"Ajusta o vhost para o nick dado com a hostmask fornecida.\n"
-"Caso seu IRCd suporte vIdents, então usando\n"
-"SET <nick> <ident>@<hostmask> ajustará idents para\n"
-"usuários, assim como vhosts."
-#, fuzzy
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -7245,19 +5964,8 @@ msgid ""
" SUPERADMIN Activate or deactivate super admin mode\n"
" LIST List the options"
msgstr ""
-"Sintaxe: SET opção seleção\n"
-"\n"
-"Ajusta várias opções globais dos Services. Os nomes de opção\n"
-"atualmente definidas são:\n"
-" READONLY Ativa o modo read-only ou read-write\n"
-" LOGCHAN Ativa ou desativa envio de log a um canal\n"
-" DEBUG Ativa ou desativa o modo de depuração (debug)\n"
-" NOEXPIRE Ativa ou desativa o modo não-expira\n"
-" SUPERADMIN Ativa ou desativa o modo Super-Admin\n"
-" IGNORE Ativa ou desativa o modo Ignore\n"
-" LIST Lista as opções atuais"
-
-#, fuzzy, c-format
+
+#, c-format
msgid ""
"Sets various memo options. option can be one of:\n"
" \n"
@@ -7266,44 +5974,25 @@ msgid ""
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
-"Sintaxe: SET opção parâmetros\n"
-"\n"
-"Ajusta várias opções de mensagens. A opção pode ser uma dessas:\n"
-"\n"
-" NOTIFY Altera quando você será notificado sobre novas\n"
-" mensagens (só para nicks)\n"
-" LIMIT Ajusta o número máximo de mensagens que você\n"
-" pode receber.\n"
-"\n"
-"Digite /msg %s HELP SET opção, para mais informações sobre\n"
-"uma opção específica."
-#, fuzzy
msgid "Sets various nickname options. option can be one of:"
msgstr ""
-"Sintaxe: SET opção parâmetros\n"
-"\n"
-"Ajusta várias opções de nick. A opção pode ser:"
-msgid ""
-"Sets whether services should set channel status modes on you automatically."
+msgid "Sets whether services should set channel status modes on you automatically."
msgstr ""
-#, fuzzy
msgid ""
"Sets whether the given channel will expire. Setting this\n"
"to ON prevents the channel from expiring."
msgstr ""
-"Sintaxe: SET canal NOEXPIRE {ON | OFF}\n"
-"\n"
-"Determina se o canal poderá ter seu registro expirado.\n"
-"Ajustando para ON, evita que o canal seja desregistrado\n"
-"por passar do tempo de expiração."
-#, fuzzy, c-format
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr ""
+
+#, c-format
msgid ""
"Sets whether the given nickname will be given its status modes\n"
"in channels automatically. Set to ON to allow %s\n"
@@ -7311,194 +6000,112 @@ msgid ""
"is entering channels. Note that depending on channel settings\n"
"some modes may not get set automatically."
msgstr ""
-"Syntax: SASET nickname AUTOOP {ON | OFF}\n"
-"\n"
-"Sets whether the given nickname will be opped automatically.\n"
-"Set to ON to allow ChanServ to op the given nickname \n"
-"automatically when joining channels."
-#, fuzzy
msgid ""
"Sets whether the given nickname will expire. Setting this\n"
"to ON prevents the nickname from expiring."
msgstr ""
-"Syntax: SASET nickname NOEXPIRE {ON | OFF}\n"
-"\n"
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
-#, fuzzy, c-format
+msgid "Sets whether you can be added to a channel access list."
+msgstr ""
+
+#, c-format
msgid ""
"Sets whether you will be given your channel status modes automatically.\n"
"Set to ON to allow %s to set status modes on you automatically\n"
"when entering channels. Note that depending on channel settings some modes\n"
"may not get set automatically."
msgstr ""
-"Syntax: SET AUTOOP {ON | OFF}\n"
-"\n"
-"Sets whether you will be opped automatically. Set to ON to \n"
-"allow ChanServ to op you automatically when entering channels."
-#, fuzzy, c-format
-msgid ""
-"Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
+#, c-format
+msgid "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
msgstr ""
-"Level %s desconhecido. Digite /msg %s HELP LEVELS DESC para uma lista de "
-"Levels válidos."
-#, fuzzy
msgid "Setting for DEBUG must be ON, OFF, or a positive number."
-msgstr "Configuração do DEBUG deve ser ON, OFF, ou um número positivo."
+msgstr ""
-#, fuzzy
msgid "Setting for NOEXPIRE must be ON or OFF."
-msgstr "Opção NOEXPIRE deve ser ON ou OFF."
+msgstr ""
-#, fuzzy
msgid "Setting for READONLY must be ON or OFF."
-msgstr "Configuração do READONLY deve ser ON ou OFF."
+msgstr ""
-#, fuzzy
msgid "Setting for super admin must be ON or OFF."
-msgstr "Configuração do READONLY deve ser ON ou OFF."
+msgstr ""
-#, fuzzy
msgid "Should services automatically give status to users"
-msgstr " AUTOOP Should services op you automatically. "
+msgstr ""
-#, fuzzy
-msgid "Show status of Services and network"
-msgstr " STATS Mostra estatísticas dos Services e da Rede"
+msgid "Show status of services and network"
+msgstr ""
#, c-format
-msgid "Showed %d/%d matches for %s."
+msgid "Showed %zu/%zu matches for %s."
msgstr ""
-#, fuzzy
msgid "Sign kicks that are done with the KICK command"
-msgstr " SIGNKICK Assinatura dos kicks feitos pelo comando KICK"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Signed kick option for %s is now off."
-msgstr "Opção Signed Kicks para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Signed kick option for %s is now on, but depends of the\n"
"level of the user that is using the command."
msgstr ""
-"Opção Signed Kicks para %s está agora ATIVADA, mas depende\n"
-"do nível de acesso do usuário que está usando o comando."
-#, fuzzy, c-format
+#, c-format
msgid "Signed kick option for %s is now on."
-msgstr "Opção Signed Kicks para %s está agora ATIVADA."
+msgstr ""
msgid "Signed kicks"
-msgstr "Kicks assinados"
-
-#, fuzzy, c-format
-msgid "Sorry, %s currently has too many memos and cannot receive more."
-msgstr "%s possui muitos memos atualmente e não pode receber mais nenhum."
-
-#, c-format
-msgid "Sorry, I have not seen %s."
msgstr ""
-#, fuzzy
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr "Desculpe, o comando BADWORDS está temporariamente desatvado."
-
-#, fuzzy
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr "Desculpe, o comando SET está temporariamente desativado."
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "Desculpe, comando CHANGE temporariamente desativado."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr "Desculpe, o comando SET está temporariamente desativado."
-
-#, fuzzy
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr "Desculpe, o comando SET está temporariamente desativado."
-
-#, fuzzy, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
+#, c-format
+msgid "Sorry, %s currently has too many memos and cannot receive more."
msgstr ""
-"Desculpe, a modificação da lista de AOP está temporariamente desabilitada."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr "Desculpe, o registro de canais está temporariamente desativado."
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr "Desculpe, o comando AKICK está temporariamente desativado."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr "Desculpe, o comando DROP está temporariamente desativado."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Desculpe, o registro de canais está temporariamente desativado."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
+#, c-format
+msgid "Sorry, %s is temporarily unavailable."
msgstr ""
-"Desculpe, as configurações do kicker estão temporariamente desativadas."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr "Desculpe, a opção SET está temporariamente desativada."
-
-#, fuzzy
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr "Desculpe, a opção SET está temporariamente desativada."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Desculpe, o comando DROP está temporariamente desativado."
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Desculpe, o comando GROUP está temporariamente desativado."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Desculpe, registros de nick estão temporariamente desativados."
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
+#, c-format
+msgid "Sorry, I have not seen %s."
msgstr ""
-"Desculpe, você pode ter apenas %d entradas na lista de acesso do canal."
#, c-format
msgid "Sorry, the maximum of %d auto join entries has been reached."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Sorry, the maximum of %d certificate entries has been reached."
-msgstr "Desculpe, você pode ter somente %d entradas em sua lista de acesso."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Sorry, the memo ignore list for %s is full."
-msgstr "Greet message for %s unset."
+msgstr ""
-#, fuzzy, c-format
-msgid ""
-"Sorry, you can only have %d access entries on a channel, including access "
-"entries from other channels."
+#, c-format
+msgid "Sorry, you can only have %d access entries on a channel, including access entries from other channels."
msgstr ""
-"Desculpe, você pode ter apenas %d entradas na lista de acesso do canal."
#, c-format
msgid "Sorry, you can only have %d autokick masks on a channel."
-msgstr "Desculpe, você pode ter apenas %d akicks na lista do canal."
+msgstr ""
#, c-format
msgid "Sorry, you can only have %d bad words entries on a channel."
-msgstr "Desculpe, você pode ter apenas %d palavrões em sua lista."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Sorry, you have already exceeded your limit of %d channels."
-msgstr "Desculpe, você pode ter apenas %d palavrões em sua lista."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Sorry, you have already reached your limit of %d channels."
-msgstr "Desculpe, você pode ter apenas %d palavrões em sua lista."
+msgstr ""
msgid "State"
msgstr ""
@@ -7507,48 +6114,42 @@ msgid "Statistics and maintenance for seen data"
msgstr ""
msgid "Statistics reset."
-msgstr "Resetar estatísticas."
+msgstr ""
msgid "Status updated (memos, vhost, chmodes, flags)."
-msgstr "Status atualizado (memos, vhost, chmodes, flags)."
+msgstr ""
msgid "Stop flooding!"
-msgstr "Pare de floodar!"
+msgstr ""
msgid "Stop repeating yourself!"
-msgstr "Pare de ficar repetindo!"
+msgstr ""
-#, fuzzy
msgid "Stricter control of channel founder status"
-msgstr " SECUREFOUNDER Controle rigoroso do status de Fundador do Canal"
+msgstr ""
-#, fuzzy
msgid "Stricter control of chanop status"
-msgstr " SECUREOPS Controle rigoroso do status de OP"
+msgstr ""
msgid "Successor"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Successor for %s changed to %s."
-msgstr "Successor do canal %s alterado para %s."
+msgstr ""
#, c-format
msgid "Successor for %s unset."
-msgstr "Successor do canal %s removido."
+msgstr ""
-#, fuzzy
-msgid ""
-"Super admin can not be set because it is not enabled in the configuration."
-msgstr "Opção SuperAdmin não habilitada no arquivo services.conf"
+msgid "Super admin can not be set because it is not enabled in the configuration."
+msgstr ""
-#, fuzzy
msgid "Suspend a given nick"
-msgstr " SUSPEND Suspende o nick fornecido"
+msgstr ""
-#, fuzzy
msgid "Suspend reason"
-msgstr "JUPE servidor [motivo]"
+msgstr ""
msgid "Suspended"
msgstr ""
@@ -7556,57 +6157,41 @@ msgstr ""
msgid "Suspended by"
msgstr ""
-#, fuzzy
msgid "Suspended on"
-msgstr " SUSPEND Suspende o nick fornecido"
+msgstr ""
-#, fuzzy
msgid ""
"Suspends a registered nickname, which prevents it from being used\n"
"while keeping all the data for that nick. If an expiry is given\n"
"the nick will be unsuspended after that period of time, else the\n"
"default expiry from the configuration is used."
msgstr ""
-"Sintaxe: SUSPEND canal [motivo]\n"
-"\n"
-"Proibe qualquer um de registrar ou usar o canal dado.\n"
-"Pode ser cancelado usando o comando UNSUSPEND para\n"
-"preservar todos os dados/configurações anteriores do canal.\n"
-"\n"
-"Um motivo pode ser necessário em algumas redes."
-#, fuzzy
msgid "Suspension expires"
-msgstr " %s (does not expire)"
+msgstr ""
-#, fuzzy
msgid "Sync users channel modes"
-msgstr "%s alterou seus modos de usuário."
+msgstr ""
msgid ""
"Syncs all modes set on users on the channel with the modes\n"
"they should have based on their access."
msgstr ""
-#, fuzzy
msgid "Syncs the vhost for all nicks in a group"
msgstr ""
-" GROUP Sincroniza um mesmo vHost para todos os nicks de um grupo"
msgid "Syntax"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Syntax: %s\n"
" \n"
"Lists all nicks in your group."
msgstr ""
-"Sintaxe: GLIST\n"
-"\n"
-"Lista todos os nicks do grupo."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Syntax: %s [nickname]\n"
" \n"
@@ -7617,14 +6202,7 @@ msgid ""
"group of the given nick.\n"
"Specifying a nick is limited to Services Operators."
msgstr ""
-"Sintaxe: GLIST [nick]\n"
-"\n"
-"Sem nenhum parâmetro, lista todos os nicks no seu grupo.\n"
-"Com um parâmetro, lista todos os nicks no grupo determinado.\n"
-"\n"
-"Este comando é limitado aos Administradores dos Services."
-#, fuzzy
msgid ""
"Syntax: DEBUG {ON | OFF}\n"
" \n"
@@ -7633,16 +6211,8 @@ msgid ""
"This option is equivalent to the command-line option\n"
"--debug."
msgstr ""
-"Sintaxe: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Ativa ou desativa o modo NOEXPIRE. Se estiver ativado, os\n"
-"nicks, canais, akills e exceções não irão expirar enquanto a \n"
-"opção não for desativada.\n"
-"\n"
-"Esta opção é equivalente à opção da linha de comando\n"
-"-noexpire."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Syntax: LIMIT [channel] limit\n"
" \n"
@@ -7651,14 +6221,8 @@ msgid ""
"able to send any memos to you. However, you cannot set\n"
"this any higher than %d."
msgstr ""
-"Sintaxe: SET LIMIT [canal] limite\n"
-"\n"
-"Ajusta o número máximo de mensagens que você (ou o canal fornecido)\n"
-"podem ter. Se você ajustar para 0, ninguém será capaz de enviar\n"
-"mensagens para você. Entretanto, você não pode ajustar este\n"
-"limite para mais que %d."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Syntax: LIMIT [user | channel] {limit | NONE} [HARD]\n"
" \n"
@@ -7680,37 +6244,14 @@ msgid ""
"remove their limit, may not set a limit above %d, and may\n"
"not set a hard limit."
msgstr ""
-"Sintaxe: SET LIMIT [usuário | canal] {limite | NONE} [HARD]\n"
-"\n"
-"Ajusta o número máximo de mensagens que um usuário ou canal podem\n"
-"ter. Ajustando o limite para 0, previne o usuário de receber\n"
-"qualquer mensagem; ajustando o limite em NONE permite que o\n"
-"usuário receba e mantenha quantas mensagens quiser. Se você\n"
-"não fornecer o nick ou canal, seu próprio limite será ajustado.\n"
-"\n"
-"Adicionando HARD previne que o usuário mude o limite.\n"
-"Não adicionando HARD tem o efeito contrário, permitindo\n"
-"que o usuário mude o limite (mesmo se um limite anterior\n"
-"foi ajustado com HARD).\n"
-"\n"
-"Este uso do comando SET LIMIT é limitado aos Administradores\n"
-"dos Services. Outros usuários somente ajustarão seus\n"
-"próprios limites ou de um canal onde tenham privilégios\n"
-"para isso, não podem remover seu próprio limite, não\n"
-"podem ajustar o limite acima de %d, e não podem ajustar\n"
-"um limite máximo (HARD)."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Syntax: LIST\n"
" \n"
"Display the various %s settings."
msgstr ""
-"Sintaxe: SET LIST\n"
-"\n"
-"Exibe as várias configurações do %s."
-#, fuzzy
msgid ""
"Syntax: NOEXPIRE {ON | OFF}\n"
" \n"
@@ -7721,16 +6262,7 @@ msgid ""
"This option is equivalent to the command-line option\n"
"--noexpire."
msgstr ""
-"Sintaxe: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Ativa ou desativa o modo NOEXPIRE. Se estiver ativado, os\n"
-"nicks, canais, akills e exceções não irão expirar enquanto a \n"
-"opção não for desativada.\n"
-"\n"
-"Esta opção é equivalente à opção da linha de comando\n"
-"-noexpire."
-#, fuzzy
msgid ""
"Syntax: NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
" \n"
@@ -7750,57 +6282,24 @@ msgid ""
" \n"
"ON is essentially LOGON and NEW combined."
msgstr ""
-"Sintaxe: SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-"\n"
-"Altera quando você será notificado sobre novas mensagens:\n"
-"\n"
-" ON Você será notificado sobre mensagens quando você\n"
-" conectar, quando voltar de um /AWAY e quando\n"
-" são enviadas a você.\n"
-" LOGON Você só será notificado sobre mensagens quando você\n"
-" conectar ou quando voltar de um /AWAY.\n"
-" NEW Você só será notificado sobre mensagens quando elas\n"
-" forem enviadas a você.\n"
-" MAIL You will be notified of memos by email aswell as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF Você não receberá nenhuma notificação sobre mensagens.\n"
-"\n"
-"ON é essencialmente a combinação de LOGON e NEW."
-#, fuzzy
msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"users will not be allowed to modify any services data,\n"
+"including channel access lists, etc. Server operators\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
"--readonly."
msgstr ""
-"Sintaxe: SET READONLY {ON | OFF}\n"
-"\n"
-"Ativa ou desativa o modo read-only (somente leitura).\n"
-"No modo read-only, usuários normais não serão capazes de\n"
-"modificar nenhum dado nos Services, incluindo lista de acesso\n"
-"de canais e nicks etc. IRCops com privilégios suficientes\n"
-"nos Services serão capazes de modificar a lista de AKILL\n"
-"e de proibir ou cancelar o registro de canais ou nicks,\n"
-"embora quaisquer mudanças não serão salvas no banco de\n"
-"dados a menos que o modo read-only seja desativado antes\n"
-"dos Services serem terminados ou reiniciados.\n"
-"\n"
-"Esta opção é equivalente à opção da linha de comando\n"
-"-readonly."
-#, fuzzy
msgid ""
"Syntax: SUPERADMIN {ON | OFF}\n"
" \n"
@@ -7810,14 +6309,8 @@ msgid ""
"This option is not persistent, and should only be used when\n"
"needed, and set back to OFF when no longer needed."
msgstr ""
-"Sintaxe: SET SUPERADMIN {ON | OFF}\n"
-"\n"
-"Ativando esta opção, lhe serão concedidos privilégios extras como a\n"
-"habilidade de ser \"founder\" em todos os canais etc.\n"
-"Esta opção não é permanente, e deve ser usada somente quando\n"
-"necessária, e desativada quando não for mais necessária."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Tells %s that you are really the owner of this\n"
"nick. Many commands require you to authenticate yourself\n"
@@ -7825,14 +6318,8 @@ msgid ""
"should be the same one you sent with the REGISTER\n"
"command."
msgstr ""
-"Sintaxe: IDENTIFY [account] senha\n"
-"\n"
-"Identifica você ao %s como sendo dono do nick.\n"
-"Muitos comandos exigem que você se identifique com este\n"
-"comando antes de você usá-los. A senha deve ser a mesma que\n"
-"você enviou com o comando REGISTER."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Tells %s to invite you or an optionally specified\n"
"nick into the given channel.\n"
@@ -7840,13 +6327,8 @@ msgid ""
"By default, limited to AOPs or those with level 5 access and above\n"
"on the channel."
msgstr ""
-"Sintaxe: INVITE #canal\n"
-"\n"
-"Manda o %s dar um invite em você para o canal dado.\n"
-"Por padrão, é limitado aos AOPs ou àqueles que possuem\n"
-"nível de acesso 5 ou superior no canal."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Tells %s to remove all bans preventing you or the given\n"
"user from entering the given channel. If no channel is\n"
@@ -7856,18 +6338,10 @@ msgid ""
"By default, limited to AOPs or those with level 5 access and above\n"
"on the channel."
msgstr ""
-"Sintaxe: UNBAN #canal [nick]\n"
-"\n"
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel.\n"
-"\n"
-"Por padrão, é limitado aos AOPs ou àqueles que possuem\n"
-"nível de acesso 5 ou superior no canal."
-#, fuzzy
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7875,27 +6349,15 @@ msgid ""
"text \"Juped by <nick>\", showing the nickname of the\n"
"person who jupitered the server."
msgstr ""
-"Sintaxe: JUPE servidor [motivo]\n"
-"\n"
-"Diz aos Services para \"jupar\" um servidor -- isto é, criar\n"
-"um falso servidor conectado aos Services que previne que o\n"
-"servidor real com aquele nome se conecte na rede. O jupe\n"
-"pode ser removido usando um SQUIT padrão. Se um motivo\n"
-"é dado, ele é colocado no campo de informação do servidor;\n"
-"caso contrário, o campo de informação do servidor irá conter\n"
-"o texto \"Jupado por <nick>\", mostrando o nick de quem mascarou\n"
-"o servidor."
msgid "Tells you about the last time a user was seen"
msgstr ""
-#, fuzzy
-msgid "Terminate Services WITHOUT saving"
-msgstr " SHUTDOWN Termina os Services salvando os dados"
+msgid "Terminate services WITHOUT saving"
+msgstr ""
-#, fuzzy
msgid "Terminate services with save"
-msgstr " SHUTDOWN Termina os Services salvando os dados"
+msgstr ""
msgid "Text"
msgstr ""
@@ -7934,15 +6396,12 @@ msgid ""
"access list."
msgstr ""
-msgid ""
-"The CLEAR command clears the channel access list. This requires channel "
-"founder access."
+msgid "The CLEAR command clears the channel access list. This requires channel founder access."
msgstr ""
#, c-format
msgid ""
-"The CLEAR command lets you clean the database by removing all entries from "
-"the\n"
+"The CLEAR command lets you clean the database by removing all entries from the\n"
"database that were added within time.\n"
" \n"
"Example:\n"
@@ -7950,7 +6409,6 @@ msgid ""
" Will remove all entries that were added within the last 30 minutes."
msgstr ""
-#, fuzzy
msgid ""
"The DEL command removes the given word from the\n"
"bad words list. If a list of entry numbers is given, those\n"
@@ -7967,41 +6425,6 @@ msgid ""
"The CLEAR command clears all entries from the\n"
"bad words list."
msgstr ""
-"Sintaxe: HOP canal ADD nick\n"
-" HOP canal DEL {nick | entrada | lista-entradas}\n"
-" HOP canal LIST [máscara | lista-entradas]\n"
-" HOP canal CLEAR\n"
-"\n"
-"Mantém a lista de HOP (HalfOP) para um canal. A lista\n"
-"de HOP dá a um usuário o direito de receber HalfOP\n"
-"automaticamente ao entrar no canal.\n"
-"\n"
-"O comando HOP ADD adiciona o nick fornecido à lista de HOP.\n"
-"\n"
-"O comando HOP DEL remove o nick fornecido da lista de HOP.\n"
-"Se uma lista de números de entrada é fornecida, essas entradas\n"
-"são deletadas. (Veja o exemplo para LIST abaixo.)\n"
-"\n"
-"O comando HOP LIST exibe a lista de HOP. Se uma máscara\n"
-"é fornecida, apenas as entradas que combinarem com ela serão\n"
-"mostradas. Se uma lista de números de entrada é fornecida,\n"
-"apenas essas entradas são mostradas; por exemplo:\n"
-"\n"
-" HOP #canal LIST 2-5,7-9\n"
-" Lista as entradas de HOP numeradas de 2 a 5 e de\n"
-" 7 a 9.\n"
-"\n"
-"O comando HOP CLEAR remove todas as entradas da lista de HOP.\n"
-"\n"
-"Os comandos HOP ADD, HOP DEL e HOP LIST são limitados\n"
-"aos AOPs ou acima, enquanto o comando HOP CLEAR pode ser usado\n"
-"apenas pelo Fundador do canal.\n"
-"\n"
-"Este comando pode ter sido desabilitado para seu canal\n"
-"e, nesse caso, você precisa usar a lista de acesso. Veja\n"
-"/msg %s HELP ACCESS para informações sobre a lista\n"
-"de acesso, e /msg %s HELP SET XOP para saber como\n"
-"escolher entre a lista de acesso e o sistema de listas xOP."
msgid ""
"The ENTRYMSG ADD command adds the given message to\n"
@@ -8028,9 +6451,9 @@ msgid ""
msgstr ""
msgid "The IMMED option is not available on this network."
-msgstr "O comando IMMED não está disponível nesta Rede."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"The LEVELS command allows fine control over the meaning of\n"
"the numeric access levels used for channels. With this\n"
@@ -8042,7 +6465,7 @@ msgid ""
"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
"disables an automatic feature or disallows access to a\n"
"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it). Use LEVELS SET founder to make a level\n"
+"can always re-enable it). Use LEVELS SET founder to make a level\n"
"founder only.\n"
" \n"
"LEVELS LIST shows the current levels for each function or\n"
@@ -8052,69 +6475,31 @@ msgid ""
"For a list of the features and functions whose levels can be\n"
"set, see HELP LEVELS DESC."
msgstr ""
-"Sintaxe: LEVELS canal SET tipo [nível|FOUNDER]\n"
-" LEVELS canal {DIS | DISABLE} tipo\n"
-" LEVELS canal LIST\n"
-" LEVELS canal RESET\n"
-"\n"
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-"\n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it).\n"
-"\n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel (see\n"
-"HELP ACCESS LEVELS).\n"
-"\n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
msgid ""
-"The LIST command allows you to list existing entries on the channel access "
-"list.\n"
-"If a mask is given, the mask is wildcard matched against all existing "
-"entries on the\n"
-"access list, and only those entries are returned. If a set of flags is "
-"given, only those\n"
+"The LIST command allows you to list existing entries on the channel access list.\n"
+"If a mask is given, the mask is wildcard matched against all existing entries on the\n"
+"access list, and only those entries are returned. If a set of flags is given, only those\n"
"on the access list with the specified flags are returned."
msgstr ""
msgid ""
"The MODIFY command allows you to modify the access list. If the mask is\n"
"not already on the access list it is added, then the changes are applied.\n"
-"If the mask has no more flags, then the mask is removed from the access "
-"list.\n"
-"Additionally, you may use +* or -* to add or remove all flags, respectively. "
-"You are\n"
-"only able to modify the access list if you have the proper permission on the "
-"channel,\n"
-"and even then you can only give other people access to the equivalent of "
-"what your access is."
+"If the mask has no more flags, then the mask is removed from the access list.\n"
+"Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n"
+"only able to modify the access list if you have the proper permission on the channel,\n"
+"and even then you can only give other people access to the equivalent of what your access is."
msgstr ""
-msgid ""
-"The STATS command prints out statistics about stored nicks and memory usage."
+msgid "The STATS command prints out statistics about stored nicks and memory usage."
msgstr ""
-#, fuzzy
msgid ""
"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
+"for your nick immediately. You may also wish to SET HIDE it\n"
"after registering if it isn't the default setting already."
msgstr ""
-"Digite /msg %s SET EMAIL e-mail para setar seu e-mail.\n"
-"Sua privacidade é respeitada; seu e-mail não será dado\n"
-"para terceiros."
#, c-format
msgid ""
@@ -8139,42 +6524,29 @@ msgid ""
" ACCESS command on ChanServ on the channel."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "The %s list for %s is full."
-msgstr "Greet message for %s unset."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "The %s list has been cleared."
-msgstr "Lista de AKILL apagada."
+msgstr ""
msgid "The AKILL list has been cleared."
-msgstr "Lista de AKILL apagada."
-
-#, fuzzy, c-format
-msgid "The Defcon level is now at: %d"
-msgstr "O Nível do Defcon está agora no Nível: %d"
-
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr "The E-mail address of %s will now be hidden from %s INFO displays."
+msgstr ""
#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr "The E-mail address of %s will now be shown in %s INFO displays."
+msgid "The Defcon level is now at: %d"
+msgstr ""
msgid "The available flags are:"
msgstr ""
-#, fuzzy
msgid ""
"The defcon system can be used to implement a pre-defined\n"
"set of restrictions to services useful during an attempted\n"
"attack on the network."
msgstr ""
-"Sintaxe: DEFCON [1|2|3|4|5]\n"
-"O sistema Defcon pode ser usado para implementar um conjunto\n"
-"pré-definido de restrições aos Services, útil durante uma\n"
-"tentativa de ataque à Rede."
#, c-format
msgid "The email address %s has reached its usage limit of %d users."
@@ -8184,9 +6556,17 @@ msgstr ""
msgid "The email address %s has reached its usage limit of 1 user."
msgstr ""
-#, fuzzy, c-format
+#, c-format
+msgid "The email address of %s will now be hidden from %s INFO displays."
+msgstr ""
+
+#, c-format
+msgid "The email address of %s will now be shown in %s INFO displays."
+msgstr ""
+
+#, c-format
msgid "The entry message list for %s is full."
-msgstr "Greet message for %s unset."
+msgstr ""
msgid "The following feature/function names are available:"
msgstr ""
@@ -8196,93 +6576,82 @@ msgid ""
"access list from the other channel up to the given level."
msgstr ""
-#, fuzzy, c-format
-msgid ""
-"The host %s currently has %d sessions with a limit of %d because it matches "
-"entry: %s."
-msgstr "O host %s possui atualmente %d sessões com um limite de %d."
+#, c-format
+msgid "The host %s currently has %d sessions with a limit of %d because it matches entry: %s."
+msgstr ""
#, c-format
msgid "The last memo you sent to %s (sent on %s) has been read."
-msgstr "O último memo que você enviou para %s (enviado em %s) foi lido."
+msgstr ""
#, c-format
msgid "The last memo you sent to %s (sent on %s) has not yet been read."
msgstr ""
-"O último memo que você enviou para %s (enviado em %s) ainda não foi lido."
#, c-format
msgid "The last quit message of %s will now be hidden from %s INFO displays."
-msgstr "The last quit message of %s will now be hidden from %s INFO displays."
+msgstr ""
#, c-format
msgid "The last quit message of %s will now be shown in %s INFO displays."
-msgstr "The last quit message of %s will now be shown in %s INFO displays."
+msgstr ""
#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
+msgid "The last seen user@host mask of %s will now be hidden from %s INFO displays."
msgstr ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
+msgid "The last seen user@host mask of %s will now be shown in %s INFO displays."
msgstr ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
-#, fuzzy, c-format
+#, c-format
msgid "The limit on %s is not valid."
-msgstr "O limite de memos para %s não pode ser mudado."
+msgstr ""
msgid "The mask must contain at least one non wildcard character."
msgstr ""
#, c-format
msgid "The memo limit for %s may not be changed."
-msgstr "O limite de memos para %s não pode ser mudado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "The mode lock list of %s is full."
-msgstr "Greet message for %s unset."
+msgstr ""
#, c-format
msgid "The new display MUST be a nickname of the nickname group %s."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "The new display is now %s."
-msgstr "O Nível do Defcon está agora no Nível: %d"
+msgstr ""
#, c-format
msgid "The nick %s is now being changed to %s."
-msgstr "O nick %s está sendo alterado para %s."
+msgstr ""
msgid "The old information is the same as the new information specified."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "The oper info already exists on %s."
-msgstr "Bot %s já existe."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "The oper info list for %s is full."
-msgstr "Greet message for %s unset."
+msgstr ""
#, c-format
-msgid ""
-"The services access status of %s will now be hidden from %s INFO displays."
+msgid "The services access status of %s will now be hidden from %s INFO displays."
msgstr ""
-"The services access status of %s will now be hidden from %s INFO displays."
#, c-format
msgid "The services access status of %s will now be shown in %s INFO displays."
msgstr ""
-"The services access status of %s will now be shown in %s INFO displays."
-#, fuzzy
msgid "The session exception list is empty."
-msgstr " EXCEPTION Modifica a lista de limite de sessões"
+msgstr ""
msgid ""
"The user with your nick has been removed. Use this command again\n"
@@ -8290,113 +6659,97 @@ msgid ""
msgstr ""
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "Existem %d memos para o canal %s."
+msgid "There are %zu memos on channel %s."
+msgstr ""
msgid ""
"There are no bots available at this time.\n"
"Ask a Services Operator to create one!"
msgstr ""
-"Não existem bots disponíveis no momento.\n"
-"Peça a um Administrador dos Services para criar mais bots!"
msgid "There are no configured servers."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "There are no forbids of type %s."
-msgstr "Existem %d memos para o canal %s."
+msgstr ""
-#, fuzzy
msgid "There are too many nicks in your group."
-msgstr " DELALL Deleta o vHost de todos os nicks de um grupo"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "There currently are no logging configurations for %s."
-msgstr " RELOAD Recarrega o arquivo de configuração dos Services"
+msgstr ""
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "Existe %d memo para o canal %s."
+msgid "There is %zu memo on channel %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
-msgstr "Digite /msg %s READ %d para ler."
+"Type %s READ %s %zu to read it."
+msgstr ""
#, c-format
msgid "There is no bot assigned to %s anymore."
-msgstr "Não possui mais nenhum bot associado ao canal %s."
+msgstr ""
msgid "There is no logon news."
-msgstr "Não existem logon news."
+msgstr ""
msgid "There is no oper news."
-msgstr "Não existe nenhum oper news."
+msgstr ""
msgid "There is no random news."
-msgstr "Não há RandomNews."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "There is no such configuration block %s."
-msgstr " RELOAD Recarrega o arquivo de configuração dos Services"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "There is no such mode %s."
-msgstr "Não existe nenhum oper news."
+msgstr ""
msgid "There's no email address set for your nick."
-msgstr "Não há endereço de email ajustado para o seu nick."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "This channel has been forbidden: %s"
-msgstr "Este canal foi registrado com o %s."
+msgstr ""
-#, fuzzy
msgid "This channel has been suspended."
-msgstr "Este canal não pode ser usado."
+msgstr ""
-#, fuzzy
msgid "This channel is suspended."
-msgstr "Este canal não pode ser usado."
+msgstr ""
msgid "This channel may not be used."
-msgstr "Este canal não pode ser usado."
+msgstr ""
msgid ""
-"This command allows managing DNS zones used for controlling what servers "
-"users\n"
-"are directed to when connecting. Omitting all parameters prints out the "
-"status of\n"
+"This command allows managing DNS zones used for controlling what servers users\n"
+"are directed to when connecting. Omitting all parameters prints out the status of\n"
"the DNS zone.\n"
" \n"
-"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to "
-"this\n"
+"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to this\n"
"zone with the ADDSERVER command.\n"
" \n"
-"The ADDSERVER command adds a server to the given zone. When a query is done, "
-"the\n"
-"zone in question is served if it exists, else all servers in all zones are "
-"served.\n"
+"The ADDSERVER command adds a server to the given zone. When a query is done, the\n"
+"zone in question is served if it exists, else all servers in all zones are served.\n"
"A server may be in more than one zone.\n"
" \n"
"The ADDIP command associates an IP with a server.\n"
" \n"
-"The POOL and DEPOOL commands actually add and remove servers to their given "
-"zones."
+"The POOL and DEPOOL commands actually add and remove servers to their given zones."
msgstr ""
-#, fuzzy
msgid ""
"This command allows users to set the vhost of their\n"
"CURRENT nick to be the vhost for all nicks in the same\n"
"group."
msgstr ""
-"Sintaxe: GROUP\n"
-"\n"
-"Este comando permite aos usuários ajustar o vhost do seu\n"
-"nick ATUAL para ser o vhost de todos os nicks no mesmo grupo."
msgid ""
"This command also creates a new group for your nickname,\n"
@@ -8409,7 +6762,6 @@ msgstr ""
msgid "This command is an alias to the command %s."
msgstr ""
-#, fuzzy
msgid ""
"This command is used by several commands as a way to confirm\n"
"changes made to your account.\n"
@@ -8420,26 +6772,10 @@ msgid ""
"This is also used after the RESETPASS command has been used to\n"
"force identify you to your nick so you may change your password."
msgstr ""
-"Syntax: CONFIRM passcode\n"
-"\n"
-"This is the second step of nickname registration process.\n"
-"You must perform this command in order to get your nickname\n"
-"registered with %s. The passcode (or called auth code also)\n"
-"is sent to your e-mail address in the first step of the\n"
-"registration process. For more information about the first\n"
-"stage of the registration process, type: /msg %s HELP REGISTER\n"
-"\n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-#, fuzzy
msgid "This command lists information about the specified loaded module."
msgstr ""
-"Sintaxe: MODINFO NomeDoArquivo\n"
-"\n"
-"Este comando lista informações sobre um módulo carregado."
-#, fuzzy
msgid ""
"This command lists registered vhosts to the operator.\n"
"If a key is specified, only entries whose nick or vhost match\n"
@@ -8449,28 +6785,12 @@ msgid ""
"and Y will be displayed, e.g. #1-3 will display the first 3\n"
"nick/vhost entries."
msgstr ""
-"Sintaxe: LIST [<key>|<#X-Y>]\n"
-"Este comando lista ao Operador os vhosts registrados.\n"
-"Se uma Key é especificada, apenas entradas cujo nick ou vhost\n"
-"combinem com o padrão fornecido em <key> serão exibidas.\n"
-"Ex.: Rob* mostra todas as entradas começando com \"Rob\"\n"
-"Se o estilo #X-Y for usado, apenas entradas entre o alvo X\n"
-"e Y serão exibidas. Ex.: #1-3 irá mostrar as 3 primeiras\n"
-"entradas de nick/vhost.\n"
-"A lista usa o valor de NSListMax como limite do número de\n"
-"itens para exibir a um Operator de uma vez só."
-#, fuzzy
msgid ""
"This command loads the module named modname from the modules\n"
"directory."
msgstr ""
-"Sintaxe: MODLOAD NomeDoArquivo\n"
-"\n"
-"Este comando carrega o módulo chamado NomeDoArquivo\n"
-"do diretório de módulos."
-#, fuzzy
msgid ""
"This command makes your nickname join the target nickname's\n"
"group. password is the password of the target nickname.\n"
@@ -8499,36 +6819,6 @@ msgid ""
" \n"
"Note: all the nicknames of a group have the same password."
msgstr ""
-"Sintaxe: GROUP alvo senha\n"
-"\n"
-"Este comando faz seu nick entrar no grupo de um nick alvo.\n"
-"A senha é a senha do nick alvo.\n"
-"\n"
-"Entrando em um grupo permitirá a você compartilhar suas\n"
-"configurações, memos e privilégios em canais com todos os\n"
-"nicks do grupo.\n"
-"\n"
-"Um grupo existe por quanto tempo for necessário. Isso\n"
-"significa que mesmo se um nick do grupo for desregistrado,\n"
-"você não perderá os recursos compartilhados citados acima,\n"
-"durante o tempo em que houver pelo menos um nick restando\n"
-"no grupo.\n"
-"\n"
-"Você pode usar este comando mesmo se não ainda não tiver\n"
-"registrado seu nick. Se seu nick já estiver registrado,\n"
-"você precisará identificá-lo antes de usar este comando.\n"
-"Digite /msg %s HELP IDENTIFY para mais informação; talvez\n"
-"isso não seja possível em algumas redes.\n"
-"\n"
-"É recomendável usar este comando com nicks não-registrados,\n"
-"pois eles serão automaticamente registrados ao usar o comando.\n"
-"Você pode usar isto com um nick registrado (para alterar seu\n"
-"grupo) apenas se for permitido na rede.\n"
-"\n"
-"Você só pode estar em um grupo por vez. Mesclar grupos não é\n"
-"possível.\n"
-"\n"
-"Atenção: todos os nicks do grupo terão a mesma senha."
msgid ""
"This command manages your auto join list. When you identify\n"
@@ -8537,24 +6827,17 @@ msgid ""
"auto join lists."
msgstr ""
-msgid ""
-"This command may not be used on this network because nickname ownership is "
-"disabled."
+msgid "This command may not be used on this network because nickname ownership is disabled."
msgstr ""
-#, fuzzy
msgid "This command reloads the module named modname."
msgstr ""
-"Sintaxe: MODLOAD NomeDoArquivo\n"
-"\n"
-"Este comando carrega o módulo chamado NomeDoArquivo\n"
-"do diretório de módulos."
msgid "This command retrieves the vhost requests."
msgstr ""
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -8575,46 +6858,27 @@ msgid ""
"access entries on the channel."
msgstr ""
-#, fuzzy
msgid ""
-"This command ungroups your nick, or if given, the specificed nick,\n"
+"This command ungroups your nick, or if given, the specified nick,\n"
"from the group it is in. The ungrouped nick keeps its registration\n"
"time, password, email, greet, language, and url. Everything else\n"
"is reset. You may not ungroup yourself if there is only one nick in\n"
"your group."
msgstr ""
-"Syntax: UNGROUP [nick]\n"
-"\n"
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, url, and icq. Everything\n"
-"else is reset. You may not ungroup yourself if there is only one\n"
-"nick in your group."
-#, fuzzy
msgid "This command unloads the module named modname."
msgstr ""
-"Sintaxe: MODLOAD NomeDoArquivo\n"
-"\n"
-"Este comando carrega o módulo chamado NomeDoArquivo\n"
-"do diretório de módulos."
msgid "This command will resend you the registration confirmation email."
msgstr ""
#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
-msgstr ""
-
-#, fuzzy, c-format
msgid "This nickname has been forbidden: %s"
-msgstr "Este nick está atualmente suspenso, motivo: %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "This nickname has been recovered by %s."
-msgstr "Este nick está atualmente suspenso, motivo: %s"
+msgstr ""
#, c-format
msgid ""
@@ -8622,28 +6886,26 @@ msgid ""
"this then %s may have your password, and you should change it."
msgstr ""
-#, fuzzy
msgid "This nickname has been registered; you may not use it."
-msgstr "Este canal foi registrado com o %s."
+msgstr ""
-#, fuzzy
msgid "This nickname is suspended."
-msgstr "Este canal não pode ser usado."
+msgstr ""
#, c-format
msgid ""
"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
+"nick, type %s IDENTIFY password. Otherwise,\n"
"please choose a different nick."
msgstr ""
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr "Memo %d de %s (%s). Para apagar, digite: /msg %s DEL %s %d"
+#, c-format
+msgid "To delete, type: %s %s %d"
+msgstr ""
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr "Memo %d de %s (%s). Para apagar, digite: /msg %s DEL %s %d"
+#, c-format
+msgid "To delete, type: %s %s %s %d"
+msgstr ""
msgid "To protect ops against bot kicks"
msgstr ""
@@ -8655,64 +6917,53 @@ msgid ""
"To search for channels starting with #, search for the channel\n"
"name without the #-sign prepended (anope instead of #anope)."
msgstr ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
-#, fuzzy, c-format
+#, c-format
msgid "Too many results for %s."
-msgstr "Lista de acesso para %s:"
+msgstr ""
#, c-format
msgid "Top %i of %s"
msgstr ""
-#, fuzzy
msgid "Topic"
-msgstr "Trava de tópico"
+msgstr ""
-#, fuzzy
msgid "Topic lock"
-msgstr "Trava de tópico"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Topic lock option for %s is now off."
-msgstr "Trava de tópico para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Topic lock option for %s is now on."
-msgstr "Trava de tópico para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy
msgid "Topic retention"
-msgstr "Retenção de tópico"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Topic retention option for %s is now off."
-msgstr "Retenção de tópico para %s está agora ATIVADA."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Topic retention option for %s is now on."
-msgstr "Retenção de tópico para %s está agora ATIVADA."
+msgstr ""
msgid "Topic set by"
msgstr ""
msgid "Turn caps lock OFF!"
-msgstr "Desligue o CAPS LOCK!"
+msgstr ""
-#, fuzzy
msgid "Turn chanstats statistics on or off"
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
-
-#, fuzzy
-msgid "Turn nickname security on or off"
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr ""
-#, fuzzy
msgid "Turn protection on or off"
-msgstr " KILL Ativa/Desativa a proteção de kill para o seu nick"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Turns %s's privacy option on or off for the nick.\n"
"With PRIVATE set, the nickname will not appear in\n"
@@ -8720,15 +6971,8 @@ msgid ""
"(However, anyone who knows the nickname can still get\n"
"information on it using the INFO command.)"
msgstr ""
-"Syntax: SASET nickname PRIVATE {ON | OFF}\n"
-"\n"
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
-#, fuzzy, c-format
+#, c-format
msgid ""
"Turns %s's privacy option on or off for your nick.\n"
"With PRIVATE set, your nickname will not appear in\n"
@@ -8736,43 +6980,14 @@ msgid ""
"(However, anyone who knows your nickname can still get\n"
"information on it using the INFO command.)"
msgstr ""
-"Sintaxe: SET PRIVATE {ON | OFF}\n"
-"\n"
-"Torna a opção de privacidade do %s sobre o seu nick\n"
-"em ativada (ON) ou desativada (OFF). Com o PRIVATE ativado,\n"
-"seu nick não aparecerá nas listagens de nicks geradas com\n"
-"o comando %s's LIST. (Entretando, alguém que sabe do seu\n"
-"nick ainda pode obter informações usando o comando INFO)."
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Sintaxe: SET SECURE {ON | OFF}\n"
-"\n"
-"Torna os recursos de segurança do %s ativados (ON) ou\n"
-"desativados (OFF) sobre o seu nick. Com o SECURE acionado\n"
-"você deve entrar com sua senha antes de ser reconhecido como\n"
-"usuário do nick, independentemente do fato do seu endereço\n"
-"constar na lista de acesso. Entretanto, se você está na\n"
-"lista de acesso, o %s não irá dar auto-kill em você de\n"
-"acordo com os ajustes da opção KILL."
-
-#, fuzzy
+
msgid "Turns chanstats channel statistics ON or OFF for this user."
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr ""
-#, fuzzy
msgid "Turns chanstats statistics ON or OFF."
-msgstr " SECURE Ativa/Desativa os recursos de segurança para o seu nick"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"Turns the automatic protection option for the nick\n"
"on or off. With protection on, if another user\n"
@@ -8787,22 +7002,8 @@ msgid ""
"do not use this option unless necessary. Also, your\n"
"network's administrators may have disabled this option."
msgstr ""
-"Syntax: SASET nickname KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-"\n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-#, fuzzy, c-format
+#, c-format
msgid ""
"Turns the automatic protection option for your nick\n"
"on or off. With protection on, if another user\n"
@@ -8817,93 +7018,64 @@ msgid ""
"do not use this option unless necessary. Also, your\n"
"network's administrators may have disabled this option."
msgstr ""
-"Sintaxe: SET KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Possibilita a proteção de KILL do seu nick. Com a proteção\n"
-"de KILL acionada, se outro usuário tentar tomar seu nick,\n"
-"será dado 1 minuto para este mudar de nick; após isso, será\n"
-"forçado pelo %s a trocar de nick, ou será desconectado da\n"
-"rede (esse último não acontece em todas elas).\n"
-"\n"
-"Se você selecionar QUICK, será dado ao usuário somente 20\n"
-"segundos para mudar de nick ao invés do usual (60 segundos).\n"
-"Se você selecionar a opção IMMED, o nick será mudado\n"
-"imediatamente sem mesmo ser avisado antes; é recomendado\n"
-"não usar essa opção, a não ser que seja necessário. Pode\n"
-"acontecer do Administrador da Rede desabilitar essa opção."
msgid "Type"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
-"Digite /msg %s HELP SET opção para maiores informações\n"
-"sobre uma opção em particular."
+"Digite %s HELP %s opção para obter mais informações\n"
+"sobre uma opção específica."
-#, fuzzy, c-format
+#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
"level SET."
msgstr ""
-"Type /msg %s HELP SASET option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname. "
-#, fuzzy, c-format
+#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option. The options will be set on the given\n"
"nickname."
msgstr ""
-"Type /msg %s HELP SASET option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname. "
-#, fuzzy, c-format
+#, c-format
msgid ""
-"Type %s%s HELP %s option for more information on a\n"
+"Type %s HELP %s option for more information on a\n"
"particular option."
msgstr ""
-"Digite /msg %s HELP SET opção para maiores informações\n"
-"sobre uma opção em particular."
+"Digite %s HELP %s opção para obter mais informações\n"
+"sobre uma opção específica."
-#, fuzzy, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
+#, c-format
+msgid "Type %s SET EMAIL email in order to set your email."
msgstr ""
-"Digite /msg %s SET EMAIL e-mail para setar seu e-mail.\n"
-"Sua privacidade é respeitada; seu e-mail não será dado\n"
-"para terceiros."
-#, fuzzy
msgid "Un-Load a module"
-msgstr " MODUNLOAD Descarrega um módulo"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unable to find regex engine %s."
-msgstr "Impossível remover o módulo %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unable to load module %s."
-msgstr "Impossível carregar o módulo %s"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unable to remove module %s."
-msgstr "Impossível remover o módulo %s"
+msgstr ""
-#, fuzzy
msgid "Unassigns a bot from a channel"
-msgstr " UNASSIGN Desassocia um bot de um canal"
+msgstr ""
-#, fuzzy
msgid ""
"Unassigns a bot from a channel. When you use this command,\n"
"the bot won't join the channel anymore. However, bot\n"
@@ -8911,68 +7083,60 @@ msgid ""
"be able to reassign a bot later without having to reconfigure\n"
"it entirely."
msgstr ""
-"Sintaxe: UNASSIGN canal\n"
-"\n"
-"Desassocia um bot de um canal. Quando você usa este comando,\n"
-"o bot não irá entrar mais no canal. Entretando, será mantida\n"
-"a configuração do bot para aquele canal, para que você possa\n"
-"sempre poder associá-lo àquele canal mais tarde sem ter que\n"
-"configurar tudo novamente."
-#, fuzzy
msgid "Underlines kicker"
-msgstr " Kick por sublinhado: %s"
+msgstr ""
-#, fuzzy
msgid "Unknown SET option."
-msgstr "Unknown SASET option %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unknown STATS option: %s"
-msgstr "Opção STATS desconhecida: %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unknown command %s."
-msgstr "Opção desconhecida: %s."
+msgstr ""
+
+#, c-format
+msgid "Unknown command %s. \"%s HELP\" for help."
+msgstr ""
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s?"
+msgstr ""
-#, fuzzy, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Comando desconhecido %s. Digite %s%s HELP para ajuda."
+#, c-format
+msgid "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unknown mode character %c ignored."
-msgstr "Modo %c desconhecido e ignorado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Unknown parameter: %s"
-msgstr "SET opção configuração"
+msgstr ""
+
+#, c-format
+msgid "Unknown passwords: %zu"
+msgstr ""
msgid "Unpooled"
msgstr ""
-#, fuzzy
msgid ""
"Unregisters the named channel. Can only be used by\n"
"the channel founder."
msgstr ""
-"Sintaxe: DROP canal\n"
-"\n"
-"Cancela o registro do canal. So poderá ser usado pelo\n"
-"fundador do canal."
-#, fuzzy
msgid ""
"Unregisters the specified channel. Only Services Operators\n"
"can drop a channel of which they are not the founder of."
msgstr ""
-"Sintaxe: DROP canal\n"
-"\n"
-"Cancela o registro de um canal. Somente Administradores dos\n"
-"Services podem cancelar canais que pertencem a outros usuários."
-#, fuzzy
msgid "Unsuspend a given nick"
-msgstr " UNSUSPEND Libera o nick fornecido"
+msgstr ""
msgid "Unsuspends a nickname which allows it to be used again."
msgstr ""
@@ -8983,36 +7147,28 @@ msgid ""
"your channel status is updated on every channel you are in."
msgstr ""
-#, fuzzy
msgid "Updates a selected nicks status on a channel"
-msgstr " BAN Bane o nick selecionado em um canal"
+msgstr ""
-#, fuzzy
msgid "Updates your current status, i.e. it checks for new memos"
msgstr ""
-" UPDATE Atualiza seu status atual, ou seja, verifica novos memos"
-#, fuzzy
msgid ""
"Updates your current status, i.e. it checks for new memos,\n"
"sets needed channel modes and updates your vhost and\n"
"your userflags (lastseentime, etc)."
msgstr ""
-"Sintaxe: UPDATE\n"
-"Atualiza seu status atual, ou seja, checa por novos memos,\n"
-"seta modos de canal necessários (ModeonID) e atualiza seu\n"
-"vHost e suas flags de usuário (Último horário visto etc)."
msgid "Updating databases."
-msgstr "Atualizando banco de dados."
+msgstr ""
#, c-format
msgid "Uplink capab: %s"
-msgstr "Uplink capab: %s"
+msgstr ""
#, c-format
msgid "Uplink server: %s"
-msgstr "Uplink server: %s"
+msgstr ""
#, c-format
msgid "Use the %s ALL command to list all commands and their descriptions."
@@ -9021,70 +7177,76 @@ msgstr ""
msgid "Used on"
msgstr ""
-#, fuzzy
msgid "Used to manage channels"
-msgstr "%s alterou seus modos de usuário."
+msgstr ""
-#, fuzzy
msgid "Used to manage the list of privileged users"
-msgstr " ACCESS Modifica a lista de usuários privilegiados"
+msgstr ""
msgid "Used to modify the channel status of you or other users"
msgstr ""
-#, fuzzy
+#, c-format
+msgid "User %s isn't currently logged in to an account."
+msgstr "O utilizador %s não está atualmente ligado a uma conta."
+
msgid "User has been banned from the channel"
-msgstr "Você não está mais banido do %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "User limit for %s removed."
-msgstr "vhost para %s removido."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "User limit for %s set to %d."
-msgstr "Limite de memos para %s é agora de %d."
+msgstr ""
-#, fuzzy
msgid "Users"
-msgstr "Lista de bots:"
+msgstr ""
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
msgstr ""
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
msgstr ""
-#, fuzzy
msgid "Users list:"
-msgstr "Lista de bots:"
+msgstr ""
msgid "VHost"
msgstr ""
-#, fuzzy, c-format
+#, c-format
+msgid "VHost for %s removed."
+msgstr ""
+
+#, c-format
msgid "VHost for %s set to %s."
-msgstr "vhost de %s ajustado para %s."
+msgstr ""
-#, fuzzy, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "vhost de %s ajustado para %s@%s."
+#, c-format
+msgid "VHost for %s has been activated."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
+msgid "VHost for %s has been rejected."
+msgstr ""
+
+#, c-format
msgid "VHost for group %s set to %s."
-msgstr "vhost do grupo %s ajustado para %s."
+msgstr ""
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "vhost do grupo %s ajustado para %s@%s."
+#, c-format
+msgid "VHosts for group %s have been removed."
+msgstr ""
msgid "VIEW host"
msgstr ""
-#, fuzzy
msgid "VIEW [mask | list | id]"
-msgstr "LIST [canal] [list | NEW]"
+msgstr ""
msgid "VIEW [mask | list]"
msgstr ""
@@ -9092,33 +7254,24 @@ msgstr ""
msgid "Value"
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Value of %s:%s changed to %s"
-msgstr "Founder do canal %s alterado para %s."
-
-msgid "Vhost"
msgstr ""
-#, fuzzy, c-format
-msgid "Vhost for %s removed."
-msgstr "vhost para %s removido."
-
-#, fuzzy
msgid "View and change Services Operators"
-msgstr "%s is a services operator of type %s."
+msgstr ""
msgid "View and change configuration file settings"
msgstr ""
-#, fuzzy
msgid "View the list of host sessions"
-msgstr " SESSION Mostra a lista de sessões de host"
+msgstr ""
msgid "Voices protection"
-msgstr "Proteção de Voices"
+msgstr ""
msgid "Watch your language!"
-msgstr "Cuidado com suas palavras!"
+msgstr ""
#, c-format
msgid ""
@@ -9126,7 +7279,6 @@ msgid ""
"%s's %s command."
msgstr ""
-#, fuzzy
msgid ""
"Without a parameter, displays information on the number of\n"
"memos you have, how many of them are unread, and how many\n"
@@ -9139,20 +7291,7 @@ msgid ""
"for the given nickname. This is limited to Services\n"
"Operators."
msgstr ""
-"Sintaxe: INFO [nick | canal]\n"
-"\n"
-"Sem um parâmetro, informa o número de mensagens que você\n"
-"tem, quantas mensagens ainda não foram lidas, e quantas\n"
-"mensagens no total você pode receber.\n"
-"\n"
-"Com o parâmetro do canal, mostra a mesma informação para\n"
-"o canal fornecido.\n"
-"\n"
-"Com o parâmetro de nick, mostra a mesma informação para\n"
-"o nick fornecido. Esta derivação do comando é limitada aos\n"
-"Administradores dos Services."
-#, fuzzy
msgid ""
"Without a parameter, reverses the effect of the IDENTIFY\n"
"command, i.e. make you not recognized as the real owner of the nick\n"
@@ -9160,27 +7299,14 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
-"Sintaxe: LOGOUT [nick [REVALIDATE]]\n"
-"\n"
-"Sem nenhum parâmetro, reverte o efeito do comando IDENTIFY,\n"
-"ou seja, faz com que você não seja mais reconhecido como o\n"
-"verdadeiro dono do nick. Note, entretanto, que ele não pedirá\n"
-"que você se identifique novamente.\n"
-"\n"
-"Com um parâmetro, fará o mesmo para o nick determinado. Se você\n"
-"especificar REVALIDATE também, os Services irão pedir que o nick\n"
-"em questão se identifique novamente. \n"
-"\n"
-"Comando limitado aos Administradores dos Services."
-#, fuzzy
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -9188,6 +7314,9 @@ msgid ""
"The RESET option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
+"The PASSWORD option displays the encryption algorithms used\n"
+"for user passwords.\n"
+" \n"
"The UPLINK option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
" \n"
@@ -9195,98 +7324,64 @@ msgid ""
" \n"
"The ALL option displays all of the above statistics."
msgstr ""
-"Sintaxe: STATS [AKILL | ALL | RESET]\n"
-"\n"
-"Sem nenhuma opção, mostra o número atual de usuários e\n"
-"IRCops online (excluindo Services), o número máximo de\n"
-"usuários online conectados simultaneamente desde que os\n"
-"Services foram iniciados na rede, e o tempo pelo qual os\n"
-"Services estão rodando sem interrupções.\n"
-"\n"
-"Com a opção AKILL, será mostrado o tamanho atual da\n"
-"listas de AKILL e SQLINE e o tempo padrão para um AKILL\n"
-"ou SQLINE expirar.\n"
-"\n"
-"A opção ALL está disponível apenas para os Administradores\n"
-"dos Services, e mostra informações sobre o consumo de memória\n"
-"dos Services. O uso deste comando pode congelar os Services\n"
-"por um curto período de tempo em redes grandes, então não\n"
-"abuse deste comando!\n"
-"\n"
-"A opção RESET reinicia a contagem do máximo de usuários\n"
-"para o número de usuários atualmente conectados na rede."
msgid "Word"
msgstr ""
#, c-format
msgid "You are already a member of the group of %s."
-msgstr "Você já é um membro do grupo %s."
+msgstr ""
msgid "You are already identified."
-msgstr "Você já está identificado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "You are already in %s!"
-msgstr "You are already in %s! "
+msgstr ""
-#, fuzzy
msgid "You are no longer a super admin."
-msgstr "Você não é mais um Super-Admin"
+msgstr ""
-#, fuzzy
msgid "You are not identified."
-msgstr "Você já está identificado."
+msgstr ""
-#, fuzzy
msgid "You are not permitted to be on this channel."
-msgstr "Você não tem permissão para mudar seu limite de memos."
+msgstr ""
msgid "You are not permitted to change your memo limit."
-msgstr "Você não tem permissão para mudar seu limite de memos."
+msgstr ""
-#, fuzzy
msgid "You are not using a client certificate."
-msgstr "Você já está identificado."
+msgstr ""
-#, fuzzy
msgid "You are now a super admin."
-msgstr "Você é agora um Super-Admin"
-
-msgid "You are now an IRC Operator."
-msgstr "Você agora é um Operador de IRC."
+msgstr ""
-#, fuzzy
msgid "You are now identified for your nick. Change your password now."
-msgstr "You are now identified for your nick. Change your password now."
+msgstr ""
#, c-format
msgid "You are now in the group of %s."
-msgstr "Você é agora um membro do grupo %s."
+msgstr ""
-#, fuzzy, c-format
-msgid ""
-"You are over your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
+#, c-format
+msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr ""
-"Atenção: Você ultrapassou seu número máximo de memos (%d). Não será possível "
-"receber novos memos enquanto você não apagar alguns."
-msgid "You can not NOOP Services."
+msgid "You can not NOOP services."
msgstr ""
-msgid ""
-"You can not disable the founder privilege because it would be impossible to "
-"reenable it at a later time."
+msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
msgstr ""
-#, fuzzy
msgid "You can not jupe an already juped server."
-msgstr "You can not jupe your services server or your uplink server."
+msgstr ""
-#, fuzzy
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "You can not jupe your services server or your uplink server."
+msgid "You can not jupe your services' pseudoserver or your uplink server."
+msgstr ""
+
+msgid "You can not queue any more messages."
+msgstr ""
#, c-format
msgid "You can not reload this module directly, instead reload %s."
@@ -9294,76 +7389,77 @@ msgstr ""
msgid "You can not request a receipt when sending a memo to yourself."
msgstr ""
-"Você não pode pedir uma notificação ao enviar uma mensagem a si próprio."
-#, fuzzy, c-format
+msgid "You can not send a single message while you have messages queued."
+msgstr ""
+
+#, c-format
msgid "You can't %s yourself!"
-msgstr "Você não pode usar o comando GHOST em si mesmo!"
+msgstr ""
-#, fuzzy
msgid "You can't add a channel to its own access list."
-msgstr "Resultado não encontrado na lista de acesso do %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "You can't logout %s, they are a Services Operator."
msgstr ""
-"Impossível fazer logout em %s porque ele é um Administrador dos Services."
-
-#, fuzzy, c-format
-msgid "You cannot %s on this network."
-msgstr "Você não pode remover o e-mail nesta Rede."
-#, fuzzy, c-format
+#, c-format
msgid "You cannot set the %c flag."
-msgstr "You cannot use this command."
+msgstr ""
#, c-format
msgid "You cannot set the memo limit for %s higher than %d."
-msgstr "Você não pode colocar o limite de memos para %s maior que %d."
+msgstr ""
#, c-format
msgid "You cannot set your memo limit higher than %d."
-msgstr "Você não pode colocar seu limite de memos maior que %d."
+msgstr ""
-#, fuzzy
msgid "You cannot unassign bots while persist is set on the channel."
-msgstr "You can not unassign bots while persist is set on the channel."
+msgstr ""
-msgid "You cannot unset the e-mail on this network."
-msgstr "Você não pode remover o e-mail nesta Rede."
+msgid "You cannot unset the email on this network."
+msgstr ""
msgid "You cannot use this command."
-msgstr "You cannot use this command."
+msgstr ""
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Você possui atualmente %d memos, dos quais %d não foram lidos."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr ""
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Você possui atualmente %d memos, dos quais 1 não foi lido."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr ""
#, c-format
-msgid "You currently have %d memos."
-msgstr "Você possui atualmente %d memos."
+msgid "You currently have %zu memos."
+msgstr ""
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Você possui atualmente %d memos; dos quais nenhum foi lido."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr ""
msgid "You currently have 1 memo, and it has not yet been read."
-msgstr "Você possui atualmente 1 memo, e este ainda não foi lido."
+msgstr ""
msgid "You currently have 1 memo."
-msgstr "Você possui atualmente 1 memo."
+msgstr ""
msgid "You currently have no memos."
-msgstr "Você não possui nenhum memo atualmente."
+msgstr ""
#, c-format
msgid "You do not have access to set mode %c."
msgstr ""
+msgid "You do not have any messages queued and did not specify a message to send."
+msgstr ""
+
+msgid "You do not have any queued messages."
+msgstr ""
+
#, c-format
msgid "You do not have the access to change %s's modes."
msgstr ""
@@ -9374,110 +7470,88 @@ msgstr ""
#, c-format
msgid "You have %d new memos."
-msgstr "Você tem %d novos memos."
+msgstr ""
msgid "You have 1 new memo."
-msgstr "Você tem 1 novo memo."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
-msgstr "Digite /msg %s READ %d para ler."
+"Type %s READ %zu to read it."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "You have been invited to %s by %s."
-msgstr "You have been invited to %s."
+msgstr ""
#, c-format
msgid "You have been invited to %s."
-msgstr "You have been invited to %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "You have been logged in as %s."
-msgstr "Seu nick foi desconectado."
+msgstr ""
-#, fuzzy
msgid "You have been logged out."
-msgstr "Seu nick foi desconectado."
+msgstr ""
#, c-format
msgid "You have been unbanned from %s."
-msgstr "Você não está mais banido do %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "You have been unbanned from %d channels."
-msgstr "Você não está mais banido do %s."
+msgstr ""
msgid "You have no limit on the number of memos you may keep."
-msgstr "Você não possui limite de memos que pode guardar."
+msgstr ""
-#, fuzzy
msgid "You have no memos."
-msgstr "Você tem %d novos memos."
+msgstr ""
+
+msgid "You have no messages queued."
+msgstr ""
-#, fuzzy
msgid "You have no new memos."
-msgstr "Você tem %d novos memos."
+msgstr ""
-#, fuzzy, c-format
-msgid ""
-"You have reached your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
+#, c-format
+msgid "You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr ""
-"Atenção: Você atingiu seu número máximo de memos (%d). Não será possível "
-"receber novos memos enquanto você não apagar alguns."
-#, fuzzy, c-format
+#, c-format
msgid "You have regained control of %s."
-msgstr "You have been invited to %s."
+msgstr ""
-#, fuzzy
msgid "You may drop any nick within your group."
-msgstr " DELALL Deleta o vHost de todos os nicks de um grupo"
+msgstr ""
#, c-format
msgid "You may not (un)lock mode %c."
msgstr ""
-#, fuzzy
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "Você não pode remover o e-mail nesta Rede."
-
-#, fuzzy
msgid "You may not change the email of an unconfirmed account."
-msgstr "Você não pode remover o e-mail nesta Rede."
+msgstr ""
-#, fuzzy
-msgid "You may not change the password of other Services Operators."
+msgid "You may not change the email of other Services Operators."
msgstr ""
-"Impossível fazer logout em %s porque ele é um Administrador dos Services."
-#, fuzzy
-msgid "You may not drop other Services Operators' nicknames."
-msgstr "%s is a services operator of type %s."
+msgid "You may not change the password of other Services Operators."
+msgstr ""
-#, fuzzy
-msgid "You may not get the password of other Services Operators."
+#, c-format
+msgid "You may not drop %s as it is the display nick for the account."
msgstr ""
-"Impossível fazer logout em %s porque ele é um Administrador dos Services."
-#, fuzzy
-msgid "You may not suspend other Services Operators' nicknames."
+msgid "You may not drop other Services Operators' nicknames."
msgstr ""
-"Impossível fazer logout em %s porque ele é um Administrador dos Services."
-#, fuzzy
-msgid ""
-"You may view but not modify the access list of other Services Operators."
+msgid "You may not suspend other Services Operators' nicknames."
msgstr ""
-"Impossível fazer logout em %s porque ele é um Administrador dos Services."
-#, fuzzy
-msgid ""
-"You may view but not modify the certificate list of other Services Operators."
+msgid "You may view but not modify the certificate list of other Services Operators."
msgstr ""
-"Impossível fazer logout em %s porque ele é um Administrador dos Services."
#, c-format
msgid "You might see yourself in the mirror, %s."
@@ -9487,92 +7561,70 @@ msgid "You must assign a bot to the channel before using this command."
msgstr ""
msgid "You must be a channel operator to register the channel."
-msgstr "Você deve ser no mínimo um operador para registrar o canal."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "You must be in %s to use this command."
-msgstr "You need to be identified to use this command."
+msgstr ""
+
+msgid "You must be logged into an account to use that command."
+msgstr ""
-#, fuzzy
msgid "You must confirm your account before you can register a channel."
-msgstr "Você deve ser no mínimo um operador para registrar o canal."
+msgstr ""
-#, fuzzy
msgid "You must confirm your account before you may request a vhost."
-msgstr "Você deve ser no mínimo um operador para registrar o canal."
+msgstr ""
-#, fuzzy
msgid "You must confirm your account before you may send a memo."
-msgstr "Você deve ser no mínimo um operador para registrar o canal."
-
-#, c-format
-msgid ""
-"You must enter the channel name twice as a confirmation that you wish to drop"
-" %s."
msgstr ""
#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
+msgid "You must have been using this nick for at least %lu seconds to register."
msgstr ""
-"Você deve estar conectado há mais de %d segundos para registrar seu nick."
-#, fuzzy, c-format
+#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
-msgstr "You need to be identified to use this command."
+msgstr ""
msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
+"You must now supply an email for your nick.\n"
+"This email will allow you to retrieve your password in\n"
"case you forget it."
msgstr ""
-"Você deve agora setar um e-mail para seu nick.\n"
-"Este e-mail permitirá que você receba sua senha por ele\n"
-"caso você se esqueça dela."
msgid "You need to be identified to use this command."
-msgstr "You need to be identified to use this command."
+msgstr ""
-#, fuzzy
msgid "You will be notified by message and by mail when new memos arrive."
-msgstr "Você será notificado de novos memos quando eles forem enviados."
+msgstr ""
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon and when they arrive, and by mail "
-"when they arrive."
+msgid "You will be notified of new memos at logon and when they arrive, and by mail when they arrive."
msgstr ""
-"Você será notificado de novos memos quando conectar e quando eles forem "
-"enviados."
msgid "You will be notified of new memos at logon and when they arrive."
msgstr ""
-"Você será notificado de novos memos quando conectar e quando eles forem "
-"enviados."
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon, and by mail when they arrive."
+msgid "You will be notified of new memos at logon, and by mail when they arrive."
msgstr ""
-"Você será notificado de novos memos quando conectar e quando eles forem "
-"enviados."
msgid "You will be notified of new memos at logon."
-msgstr "Você será notificado de novos memos quando conectar."
+msgstr ""
msgid "You will be notified when new memos arrive."
-msgstr "Você será notificado de novos memos quando eles forem enviados."
+msgstr ""
msgid "You will no longer be able to receive memos."
-msgstr "Você não poderá mais receber memos."
+msgstr ""
msgid "You will no longer be informed via email."
-msgstr "Você não será mais notificado por email."
+msgstr ""
msgid "You will not be notified of new memos."
-msgstr "Você será notificado de novos memos."
+msgstr ""
msgid "You will now be informed about new memos via email."
-msgstr "Você será notificado sobre novos memos por email."
+msgstr ""
msgid "Your IRCd does not support SVSJOIN."
msgstr ""
@@ -9583,210 +7635,191 @@ msgstr ""
msgid "Your IRCd does not support SVSPART."
msgstr ""
-msgid ""
-"Your IRCd does not support vIdent's, if this is incorrect, please report "
-"this as a possible bug"
+msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
msgstr ""
-#, fuzzy, c-format
+#, c-format
+msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
+msgstr ""
+
+#, c-format
msgid "Your account %s has been successfully created."
-msgstr "Bot %s foi removido."
+msgstr ""
-#, fuzzy
msgid "Your account is already confirmed."
-msgstr "Você já está identificado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Your account will expire, if not confirmed, in %s."
-msgstr "Você já está identificado."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Your email address has been changed to %s."
-msgstr "E-mail address for %s changed to %s."
+msgstr ""
-#, fuzzy
msgid "Your email address is not allowed, choose a different one."
-msgstr "Todas as O:lines do servidor %s foram removidas."
+msgstr ""
-msgid ""
-"Your email address is not confirmed. To confirm it, follow the instructions "
-"that were emailed to you."
+msgid "Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you."
msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Your email address of %s has been confirmed."
-msgstr "Todas as O:lines do servidor %s foram removidas."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Your email has been updated to %s"
-msgstr "E-mail address for %s changed to %s."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Your email has been updated to %s."
-msgstr "E-mail address for %s changed to %s."
+msgstr ""
msgid "Your memo limit has been disabled."
-msgstr "Seu limite de memos foi desativado."
+msgstr ""
#, c-format
msgid "Your memo limit has been set to %d."
-msgstr "Seu limite de memo é agora de %d."
+msgstr ""
#, c-format
msgid "Your memo limit is %d, and may not be changed."
-msgstr "Seu limite de memos é de %d, e não pode ser alterado."
+msgstr ""
#, c-format
msgid "Your memo limit is %d."
-msgstr "Seu limite de memos é de %d."
+msgstr ""
msgid "Your memo limit is 0; you will not receive any new memos."
-msgstr "Seu limite de memos é de 0; você não pode receber novos memos."
+msgstr ""
-#, fuzzy
-msgid ""
-"Your memo limit is 0; you will not receive any new memos. You cannot change "
-"this limit."
+msgid "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
+msgstr ""
+
+msgid "Your message has been queued."
+msgstr ""
+
+msgid "Your message queue has been cleared."
msgstr ""
-"Seu limite de memos é de 0; você não pode receber novos memos. Você não pode "
-"alterar esse limite."
msgid "Your nick has been logged out."
-msgstr "Seu nick foi desconectado."
+msgstr ""
-#, fuzzy
msgid "Your nick is already registered."
-msgstr "Seu nick já está registrado; digite /msg %s DROP primeiro."
+msgstr ""
msgid "Your nick is not grouped to anything, you can't ungroup it."
-msgstr "Your nick is not grouped to anything, you can't ungroup it."
+msgstr ""
-#, fuzzy
msgid "Your nick isn't registered."
-msgstr "Nick %s registrado."
+msgstr ""
#, c-format
msgid "Your nickname is now being changed to %s"
-msgstr "Seu nick está sendo mudado para %s."
+msgstr ""
msgid "Your oper block doesn't require logging in."
msgstr ""
#, c-format
msgid "Your passcode has been re-sent to %s."
-msgstr "Seu passcode foi re-enviado para %s."
+msgstr ""
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Sua senha é %s - guarde ela para uso posterior."
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr ""
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
+msgid "Your password is too short. It must be longer than %u characters."
msgstr ""
msgid "Your password reset request has expired."
-msgstr "Your password reset request has expired."
+msgstr ""
-#, fuzzy
-msgid "Your vHost has been requested."
-msgstr "Bot %s foi removido."
+msgid "Your vhost has been requested."
+msgstr ""
#, c-format
msgid "Your vhost of %s is now activated."
-msgstr "Seu vhost %s está agora ativado."
-
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "Seu vhost %s@%s está agora ativado."
+msgstr ""
msgid "Your vhost was removed and the normal cloaking restored."
-msgstr "Your vhost was removed and the normal cloaking restored."
+msgstr ""
-#, fuzzy
msgid "Zone"
-msgstr "Nenhuma"
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Zone %s already exists."
-msgstr "Bot %s já existe."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Zone %s does not exist."
-msgstr "Bot %s já existe."
+msgstr ""
-#, fuzzy, c-format
+#, c-format
msgid "Zone %s removed."
-msgstr "vhost para %s removido."
+msgstr ""
-#, fuzzy
msgid "[1|2|3|4|5]"
-msgstr "DEFCON [1|2|3|4|5]"
+msgstr ""
#, c-format
msgid "[Logon News - %s] %s"
-msgstr "[Logon News - %s] %s"
+msgstr ""
#, c-format
msgid "[Oper News - %s] %s"
-msgstr "[Oper News - %s] %s"
+msgstr ""
#, c-format
msgid "[Random News - %s] %s"
-msgstr "[Random News - %s] %s"
+msgstr ""
-#, fuzzy
msgid "[account] password"
-msgstr "IDENTIFY senha"
+msgstr ""
-#, fuzzy
msgid "[channel [nick]]"
-msgstr "OP #channel [nick]"
+msgstr ""
-#, fuzzy
msgid "[channel] ADD entry"
-msgstr "AOP canal {ADD|DEL|LIST|CLEAR} [nick | entrada]"
+msgstr ""
-#, fuzzy
msgid "[channel] DEL entry"
-msgstr "MODE canal modos"
+msgstr ""
-#, fuzzy
msgid "[channel] LIST"
-msgstr "DROP canal"
+msgstr ""
-#, fuzzy
msgid "[channel] [list | NEW]"
-msgstr "LIST [canal] [list | NEW]"
+msgstr ""
-#, fuzzy
msgid "[channel] [nick]"
-msgstr "OP #channel [nick]"
+msgstr ""
-#, fuzzy
msgid "[channel] {num | list | LAST | ALL}"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr ""
-#, fuzzy
msgid "[channel] {num | list | LAST | NEW | ALL}"
-msgstr "DEL [canal] {núm | list | ALL}"
+msgstr ""
msgid "[key|#X-Y]"
msgstr ""
-#, fuzzy
+msgid "[message]"
+msgstr ""
+
msgid "[nick | channel]"
-msgstr "CANCEL {nick | canal}"
+msgstr ""
-#, fuzzy
msgid "[nick]"
-msgstr "INFO nick"
+msgstr ""
msgid "[nickname [REVALIDATE]]"
msgstr ""
-#, fuzzy
msgid "[nickname]"
-msgstr "CHECK nick"
+msgstr ""
msgid "[parameter]"
msgstr ""
@@ -9794,9 +7827,8 @@ msgstr ""
msgid "[+daysd] [+limitl] pattern"
msgstr ""
-#, fuzzy
msgid "[+expiry] channel reason"
-msgstr "CHANKILL [+tempo] {#canal} [motivo]"
+msgstr ""
msgid "[Hostname hidden]"
msgstr ""
@@ -9807,37 +7839,34 @@ msgstr ""
msgid "[Unconfirmed]"
msgstr ""
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been approved."
-msgstr "[Auto-Memo] O memo que você enviou para %s foi lido."
+#, c-format
+msgid "[auto memo] VHost %s has been requested by %s."
+msgstr "[auto memo] VHost %s foi solicitado por %s."
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been rejected."
-msgstr "[Auto-Memo] O memo que você enviou para %s foi lido."
+msgid "[auto memo] Your requested vhost has been approved."
+msgstr "[auto memo] Seu vhost solicitado foi aprovado."
-#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr ""
+msgid "[auto memo] Your requested vhost has been rejected."
+msgstr "[auto memo] Seu vhost solicitado foi rejeitado."
-#, fuzzy, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "Último memo enviado para %s foi cancelado."
+#, c-format
+msgid "[auto memo] Your requested vhost has been rejected. Reason: %s"
+msgstr "[auto memo] Seu vhost solicitado foi rejeitado. Razão: %s"
msgid "[{pattern | channel} [INVISIBLE]]"
-msgstr ""
+msgstr "[{padrão | canal} [INVISIBLE]]"
msgid "[{pattern | nick} [SECRET]]"
-msgstr ""
+msgstr "[{padrão | nick} [SECRET]]"
msgid "day"
-msgstr ""
+msgstr "dia"
msgid "days"
-msgstr ""
+msgstr "dias"
-#, fuzzy
msgid "does not expire"
-msgstr " %s (does not expire)"
+msgstr "não expira"
#, c-format
msgid "expires in %d day"
@@ -9871,68 +7900,51 @@ msgstr "expira em %d minuto"
msgid "expires in %d minutes"
msgstr "expira em %d minutos"
-#, fuzzy
msgid "expires momentarily"
-msgstr "expira em %d dia"
+msgstr "expira momentaneamente"
msgid "hour"
-msgstr ""
+msgstr "hora"
msgid "hours"
-msgstr ""
+msgstr "horas"
#, c-format
msgid "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
+msgstr "letras: %s, palavras: %s, linhas: %s, smileys: %s, ações: %s"
msgid "minute"
-msgstr ""
+msgstr "minuto"
msgid "minutes"
-msgstr ""
+msgstr "minutos"
msgid "not assigned yet"
-msgstr ""
+msgstr "ainda não atribuído"
msgid "second"
-msgstr ""
+msgstr "segundo"
-#, fuzzy
msgid "seconds"
-msgstr "Comandos do %s:"
-
-#, fuzzy, c-format
-msgid "vHost for %s has been activated."
-msgstr "Seu vhost %s está agora ativado."
-
-#, fuzzy, c-format
-msgid "vHost for %s has been rejected."
-msgstr "Bot %s foi removido."
+msgstr "segundos"
msgid "vhost"
-msgstr ""
-
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "vhosts do grupo %s foi removido."
+msgstr "vhost"
msgid "year"
-msgstr ""
+msgstr "ano"
msgid "years"
-msgstr ""
+msgstr "anos"
msgid "{MODIFY|VIEW} [block name item name item value]"
-msgstr ""
+msgstr "{MODIFY|VIEW} [nome-do-bloco nome-do-item valor-do-item]"
-#, fuzzy
msgid "{channel | nickname}"
-msgstr "UNBAN canal [nick]"
+msgstr "{canal | nickname}"
-#, fuzzy
msgid "{nick | channel}"
-msgstr "CANCEL {nick | canal}"
+msgstr "{nick | canal}"
-#, fuzzy
msgid "{nick | channel} memo-text"
-msgstr "SEND {nick | canal} texto"
+msgstr "{nick | canal} texto-do-memo"
diff --git a/language/anope.ru_RU.po b/language/anope.ru_RU.po
deleted file mode 100644
index 1f28c401f..000000000
--- a/language/anope.ru_RU.po
+++ /dev/null
@@ -1,10224 +0,0 @@
-# Anope IRC Services language file
-# Copyright (C) 2011
-# This file is distributed under the same license as the Anope IRC Services package.
-# Adam <adam@anope.org>, 2011.
-#
-msgid ""
-msgstr ""
-"Project-Id-Version: Anope\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-01-06 18:19+0100\n"
-"PO-Revision-Date: 2010-09-19 21:10-0400\n"
-"Last-Translator: Adam <adam@anope.org>\n"
-"Language-Team: Russian\n"
-"Language: ru_RU\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-#, c-format
-msgid "%d channel(s) cleared, and %d channel(s) dropped."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%d nickname(s) dropped."
-msgstr "Ваш ник успешно удален из базы данных сервисов."
-
-#, fuzzy, c-format
-msgid "%s added to %s %s list."
-msgstr "Запись вида %s успешно добавлена в список AKILL'ов."
-
-#, c-format
-msgid "%s added to %s access list at level %d."
-msgstr "%s добавлен в список доступа канала %s с уровнем доступа %d."
-
-#, fuzzy, c-format
-msgid "%s added to %s access list at privilege %s (level %d)"
-msgstr "%s добавлен в список доступа канала %s с уровнем доступа %d."
-
-#, c-format
-msgid "%s added to %s autokick list."
-msgstr "Запись вида %s успешно добавлена в список автокиков канала %s."
-
-#, c-format
-msgid "%s added to %s bad words list."
-msgstr "Запись вида %s успешно добавлена в список плохих слов канала %s."
-
-#, fuzzy, c-format
-msgid "%s added to %s's access list."
-msgstr "Маска вида %s успешно добавлена в ваш список доступа."
-
-#, fuzzy, c-format
-msgid "%s added to %s's certificate list."
-msgstr "Маска вида %s успешно добавлена в ваш список доступа."
-
-#, fuzzy, c-format
-msgid "%s added to ignore list."
-msgstr "Маска вида %s успешно добавлена в ваш список доступа."
-
-#, fuzzy, c-format
-msgid "%s added to the %s list."
-msgstr "Запись вида %s успешно добавлена в список AKILL'ов."
-
-#, c-format
-msgid "%s added to the AKILL list."
-msgstr "Запись вида %s успешно добавлена в список AKILL'ов."
-
-#, c-format
-msgid ""
-"%s allows you to execute \"fantasy\" commands in the channel.\n"
-"Fantasy commands are commands that can be executed from messaging a\n"
-"channel, and provide a more convenient way to execute commands. Commands "
-"that\n"
-"require a channel as a parameter will automatically have that parameter\n"
-"given.\n"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to have a bot on your own channel.\n"
-"It has been created for users that can't host or\n"
-"configure a bot, or for use on networks that don't\n"
-"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
-"more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s позволяет Вам установить бота на свой канал.\n"
-"Даный сервис сделан для тех пользователей, которые\n"
-"не могут иначе установить или настроить бота, или же,\n"
-"использование ботов запрещено в IRC сети. Доступные\n"
-"команды перечислены ниже, чтобы использовать их, напишите\n"
-"/msg %s команда. Для получения более подробной\n"
-"информации по конкретной команде, напишите\n"
-"/msg %s HELP команда."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register a nickname and\n"
-"prevent others from using it. The following\n"
-"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s - это сервис, предназначенный для \"регистрации\" вашего\n"
-"ника и защиты его от использования еще кем-либо кроме вас. Ниже\n"
-"представлен список команд, позволяющих осуществлять регистрацию и\n"
-"настройку ников. Чтобы использовать команду, пошлите запрос вида\n"
-"/msg %s команда.\n"
-"Для более подробной информации по какой-либо команде используйте:\n"
-"/msg %s HELP команда."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register an account.\n"
-"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
-"For more information on a specific command, type\n"
-"%s%s %s command.\n"
-msgstr ""
-"%s - это сервис, предназначенный для \"регистрации\" вашего\n"
-"ника и защиты его от использования еще кем-либо кроме вас. Ниже\n"
-"представлен список команд, позволяющих осуществлять регистрацию и\n"
-"настройку ников. Чтобы использовать команду, пошлите запрос вида\n"
-"/msg %s команда.\n"
-"Для более подробной информации по какой-либо команде используйте:\n"
-"/msg %s HELP команда."
-
-#, fuzzy, c-format
-msgid ""
-"%s allows you to register and control various\n"
-"aspects of channels. %s can often prevent\n"
-"malicious users from \"taking over\" channels by limiting\n"
-"who is allowed channel operator privileges. Available\n"
-"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
-msgstr ""
-"%s позволяет вам регистрировать канал и управлять его различными\n"
-"настройками. Также, %s поможет вам обезопасить ваш канал от\n"
-"злонамеренных пользователей, желающих его \"захватить\", используя\n"
-"ограничение возможности получения статуса опа на канале и другие\n"
-"настройки безопасности. Список доступных команд представлен ниже,\n"
-"чтобы использовать их, пошлите запрос вида\n"
-"/msg %s команда\n"
-"Для более подробной информации о конкретной команде, воспользуйтесь:\n"
-"/msg %s HELP команда\n"
-" "
-
-#, c-format
-msgid "%s already exists in %s bad words list."
-msgstr "Запись вида %s уже содержится в списке плохих слов канала %s."
-
-#, c-format
-msgid "%s already exists on %s autokick list."
-msgstr "Запись вида %s уже присутствует в списке автокиков канала %s."
-
-#, c-format
-msgid "%s already exists on the EXCEPTION list."
-msgstr "Запись вида %s уже присутствует в списке исключений из лимита сессий."
-
-#, c-format
-msgid "%s cannot be taken as times to ban."
-msgstr "Значение вида %s не может быть использовано как кол-во киков до бана."
-
-#, fuzzy, c-format
-msgid "%s changed your usermodes to %s."
-msgstr "%s принудительно изменил ваши пользовательские режимы."
-
-#, fuzzy, c-format
-msgid "%s channel list:"
-msgstr "Конец списка каналов."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s %s list."
-msgstr "%s успешно удален из AOP'ов канала %s."
-
-#, c-format
-msgid "%s deleted from %s access list."
-msgstr "Ник %s успешно удален из списка доступа канала %s."
-
-#, c-format
-msgid "%s deleted from %s autokick list."
-msgstr "Запись вида %s удалена из списка автокиков канала %s."
-
-#, c-format
-msgid "%s deleted from %s bad words list."
-msgstr "Запись вида %s успешно удалена из списка плохих слов канала %s."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s's access list."
-msgstr "Ник %s успешно удален из списка доступа канала %s."
-
-#, fuzzy, c-format
-msgid "%s deleted from %s's certificate list."
-msgstr "Маска вида %s успешно удалена из вашего списка доступа."
-
-#, c-format
-msgid "%s deleted from session-limit exception list."
-msgstr "Запись вида %s успешно удалена из списка исключений лимита сессий."
-
-#, fuzzy, c-format
-msgid "%s deleted from the %s list."
-msgstr "%s успешно удален из AOP'ов канала %s."
-
-#, c-format
-msgid "%s deleted from the AKILL list."
-msgstr "Запись вида %s успешно удалена из списка AKILL'ов."
-
-#, c-format
-msgid "%s disabled on channel %s."
-msgstr "Уровень доступа к %s на канале %s отключен."
-
-#, c-format
-msgid "%s has been invited to %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "%s has been joined to %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "%s has been parted from %s."
-msgstr "%s has been unbanned from %s."
-
-#, c-format
-msgid "%s has been unbanned from %s."
-msgstr "%s has been unbanned from %s."
-
-#, fuzzy, c-format
-msgid "%s has no access in any channels."
-msgstr "Уровень доступа к %s на канале %s отключен."
-
-#, fuzzy, c-format
-msgid "%s has no access on %s."
-msgstr "%s has been invited to %s."
-
-#, c-format
-msgid "%s has too many channels registered."
-msgstr "%s имеет слишком много зарегистрированных каналов."
-
-#, fuzzy, c-format
-msgid "%s is a super administrator."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy, c-format
-msgid ""
-"%s is a utility allowing IRC users to send short\n"
-"messages to other IRC users, whether they are online at\n"
-"the time or not, or to channels(*). Both the sender's\n"
-"nickname and the target nickname or channel must be\n"
-"registered in order to send a memo.\n"
-"%s's commands include:"
-msgstr ""
-"Основное предназначение %s - это дать зарегистрированным\n"
-"пользователям возможность посылать друг-другу короткие \"записки\",\n"
-"называемые так же мемо-сообщениями. Данный сервис особенно удобен,\n"
-"когда вам необходимо что-то сообщить интересующему вас человеку, а\n"
-"он на данный момент вне сети (offline).\n"
-"В качестве отправителя вы можете указать как ник, так и имя канала*.\n"
-"Помните, что отправка сообщения возможна лишь зарегистрированному\n"
-"на сервисах адресату!\n"
-"\n"
-"Список команд %s:"
-
-#, fuzzy, c-format
-msgid "%s is already in %s!"
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is already in %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is already on the ignore list."
-msgstr "Маска вида %s успешно добавлена в ваш список доступа."
-
-#, fuzzy, c-format
-msgid "%s is already suspended."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is not a registered unforbidden nick or channel."
-msgstr ""
-"Указанный параметр %s не является ником бота или зарегистрированным каналом."
-
-#, c-format
-msgid "%s is not a valid ban type."
-msgstr "Число %s не является валидным номером шаблона банмаски."
-
-#, c-format
-msgid "%s is not a valid bot or registered channel."
-msgstr ""
-"Указанный параметр %s не является ником бота или зарегистрированным каналом."
-
-#, fuzzy, c-format
-msgid "%s is not a valid e-mail address."
-msgstr "Число %s не является валидным номером шаблона банмаски."
-
-#, fuzzy, c-format
-msgid "%s is not currently on channel %s."
-msgstr "Уровень доступа к %s на канале %s отключен."
-
-#, fuzzy, c-format
-msgid "%s is not in %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "%s is not on the ignore list."
-msgstr "Ник %s в списке игнорируемых не обнаружен."
-
-#, fuzzy, c-format
-msgid "%s is on the auto kick list of %s (%s)."
-msgstr "Запись вида %s успешно добавлена в список автокиков канала %s."
-
-#, fuzzy, c-format
-msgid "%s is the founder of %s."
-msgstr "Уровень доступа к %s на канале %s отключен."
-
-#, c-format
-msgid "%s matches access entry %s (from entry %s), which has privilege %s."
-msgstr ""
-
-#, c-format
-msgid "%s matches access entry %s, which has privilege %s."
-msgstr ""
-
-#, c-format
-msgid ""
-"%s matches an except on %s and cannot be banned until the except has been "
-"removed."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s matches auto kick entry %s on %s (%s)."
-msgstr "Запись вида %s успешно добавлена в список автокиков канала %s."
-
-#, fuzzy, c-format
-msgid "%s not found on %s %s list."
-msgstr "Ник %s в списке AOP'ов канала %s не обнаружен."
-
-#, c-format
-msgid "%s not found on %s access list."
-msgstr "Ник %s в списке доступа канала %s не обнаружен."
-
-#, c-format
-msgid "%s not found on %s autokick list."
-msgstr "Запись вида %s в списке автокиков канала %s не обнаружена."
-
-#, c-format
-msgid "%s not found on %s bad words list."
-msgstr "Запись вида %s в списке плохих слов канала %s не обнаружена."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's access list."
-msgstr "Ник %s в списке доступа канала %s не обнаружен."
-
-#, fuzzy, c-format
-msgid "%s not found on %s's certificate list."
-msgstr "Маска вида %s не найдена в вашем списке доступа."
-
-#, fuzzy, c-format
-msgid "%s not found on ignore list."
-msgstr "Ник %s в списке игнорируемых не обнаружен."
-
-#, c-format
-msgid ""
-"%s not found on session list, but has a limit of %d because it matches entry:"
-" %s."
-msgstr ""
-
-#, c-format
-msgid "%s not found on session-limit exception list."
-msgstr "Запись вида %s в списке исключений из лимита сессий не обнаружена."
-
-#, fuzzy, c-format
-msgid "%s not found on the %s list."
-msgstr "Ник %s в списке AOP'ов канала %s не обнаружен."
-
-#, c-format
-msgid "%s not found on the AKILL list."
-msgstr "Запись вида %s в списке AKILL'ов не обнаружена."
-
-#, fuzzy, c-format
-msgid "%s removed from the %s access list."
-msgstr "Ник %s успешно удален из списка доступа канала %s."
-
-#, fuzzy, c-format
-msgid "%s removed from the ignore list."
-msgstr "Маска вида %s успешно удалена из вашего списка доступа."
-
-#, fuzzy, c-format
-msgid "%s users list:"
-msgstr "Конец списка пользователей."
-
-#, c-format
-msgid "%s will no longer be ignored."
-msgstr "Ник %s успешно удален из списка игнорирования."
-
-#, c-format
-msgid "%s will now be ignored for %s."
-msgstr "Ник %s добавлен в список игнорирования, продолжительность игнора: %s."
-
-#, c-format
-msgid "%s will now permanently be ignored."
-msgstr ""
-"Ник %s добавлен в список игнорирования, продолжительность игнора: постоянно."
-
-#, fuzzy, c-format
-msgid "%s%s HELP %s for more information."
-msgstr ""
-"Для более подробной информации о какой-либо конкретной опции, см.\n"
-"справку по /msg %s HELP опция"
-
-msgid "ADD nick user host real"
-msgstr ""
-
-#, fuzzy
-msgid "CHANGE oldnick newnick [user [host [real]]]"
-msgstr ""
-"BOT ADD ник идент хост реальное_имя\n"
-"BOT CHANGE старый_ник новый_ник [идент [хост [реальное_имя]]]\n"
-"BOT DEL ник"
-
-#, fuzzy
-msgid "DEL nick"
-msgstr "DEL <ник>."
-
-#, fuzzy
-msgid ""
-"EXCEPTION ADD adds the given host mask to the exception list.\n"
-"Note that nick!user@host and user@host masks are invalid!\n"
-"Only real host masks, such as box.host.dom and *.host.dom,\n"
-"are allowed because sessions limiting does not take nick or\n"
-"user names into account. limit must be a number greater than\n"
-"or equal to zero. This determines how many sessions this host\n"
-"may carry at a time. A value of zero means the host has an\n"
-"unlimited session limit. See the AKILL help for details about\n"
-"the format of the optional expiry parameter.\n"
-" \n"
-"EXCEPTION DEL removes the given mask from the exception list.\n"
-" \n"
-"EXCEPTION LIST and EXCEPTION VIEW show all current\n"
-"sessions if the optional mask is given, the list is limited\n"
-"to those sessions matching the mask. The difference is that\n"
-"EXCEPTION VIEW is more verbose, displaying the name of the\n"
-"person who added the exception, its session limit, reason,\n"
-"host mask and the expiry date and time.\n"
-" \n"
-"Note that a connecting client will \"use\" the first exception\n"
-"their host matches."
-msgstr ""
-"Синтаксис: EXCEPTION ADD [+срок_истечения] маска лимит причина\n"
-" EXCEPTION DEL {маска | список_записей}\n"
-" EXCEPTION MOVE номер позиция\n"
-" EXCEPTION LIST [маска | список_записей]\n"
-" EXCEPTION VIEW [маска | список_записей]\n"
-"\n"
-"Позволяет Администраторам сервисов управлять списком хостов, которые\n"
-"будут иметь отдельно указанные ограничения на количество сессий.\n"
-"Возможности списка исключений позволяют разрешить определенным хостам\n"
-"(шеллов или BNC) иметь большее количество клиентов одновременно,\n"
-"нежели разрешено по-умолчанию. Как только количество сессий с хоста \n"
-"достигнет установленного лимита, все последующие клиенты, пытающиеся\n"
-"подключиться с данного хоста, будут автоматически отключаться.\n"
-"Перед отключением, пользователь получит уведомление от %s\n"
-"о том, что с его хоста превышен лимит подключений. Тект сообщения\n"
-"можно изменить в конфигурационном файле сервисов.\n"
-"\n"
-"Команда EXCEPTION ADD позволяет добавить указанную маску в список\n"
-"исключений. Учтите, что общие хостмастки вида ник!идент@хост или\n"
-"идент@хост недопустимы! Вы должны указывать только реальные хосты\n"
-"вида box.host.dom и *.host.dom, так как ограничение сессий не\n"
-"использует при проверке ники и/или иденты. Значение лимита должно\n"
-"быть целым числом, больше или равным нулю. Данный параметр определяет,\n"
-"как много сессий данный хост может использовать одновременно.\n"
-"Установка этого значения равным 0 позволит хосту иметь неограниченное\n"
-"число сессий. Для более подробной информации о сроке истечения см.\n"
-"справку по команде AKILL.\n"
-"\n"
-"Команда EXCEPTION DEL позволяет удалить указанную маску (или\n"
-"диапазон записей) из списка исключений.\n"
-"\n"
-"Команда EXCEPTION MOVE позволяет переместить указанное исключение\n"
-"под указанным номером на указанную позицию. Соответственно, n-ое\n"
-"количество записей списка исключений будет сдвинуто выше или ниже,\n"
-"чтобы заполнить образовавшийся промежуток.\n"
-"\n"
-"Команды EXCEPTION LIST и EXCEPTION VIEW позволяют получить текущий\n"
-"список исключений. Если в качестве параметра указана маска, будут\n"
-"отображены только совпадающие с ней записи.\n"
-"\n"
-"Команда EXCEPTION VIEW позволяет получить более подробную информацию\n"
-"об исключении: ник добавившего запись, установленный лимит, указанную\n"
-"при установке причину, сам хост, срок истечения записи и дату ее\n"
-"создания.\n"
-"\n"
-"Стоит заметить, что сервисы будут использовать значения первой же\n"
-"совпадающей записи из списка исключений для попадающего под условия\n"
-"хоста. Слишком большой список исключений с широкими масками в\n"
-"достаточной мере влияет на производительность сервисов."
-
-msgid ""
-"SET kills all operators from the given\n"
-"server and prevents operators from opering\n"
-"up on the given server. REVOKE removes this\n"
-"restriction."
-msgstr ""
-
-#, c-format
-msgid ""
-"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
-"information."
-msgstr ""
-
-#, c-format
-msgid "[auto-memo] The memo you sent to %s has been viewed."
-msgstr ""
-"[авто-сообщение] Мемо-сообщение, которые вы посылали %s, было прочитано."
-
-#, fuzzy
-msgid "[target] [password]"
-msgstr "GROUP главный_ник пароль"
-
-msgid "address"
-msgstr ""
-
-#, fuzzy
-msgid "botname {ON|OFF}"
-msgstr "SASET ник AUTOOP {ON | OFF}"
-
-#, fuzzy
-msgid "channel"
-msgstr "DROP #канал"
-
-#, fuzzy
-msgid "channel bantype"
-msgstr "ACT #канал текст"
-
-#, fuzzy
-msgid "channel channel"
-msgstr "TOPIC #канал [текст_топика]"
-
-#, fuzzy
-msgid "channel command method [status]"
-msgstr "KICK #канал опция {ON|OFF} [параметры]"
-
-#, fuzzy
-msgid "channel mask [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel modes"
-msgstr "MODE #канал режимы"
-
-#, fuzzy
-msgid "channel nick"
-msgstr "UNBAN #канал [nick]"
-
-#, fuzzy
-msgid "channel nick [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel target [what]"
-msgstr "CLEAR #канал что_именно"
-
-#, fuzzy
-msgid "channel text"
-msgstr "ACT #канал текст"
-
-#, fuzzy
-msgid "channel time"
-msgstr "ACT #канал текст"
-
-#, fuzzy
-msgid "channel user reason"
-msgstr "KICK #канал ник причина"
-
-#, fuzzy
-msgid "channel what"
-msgstr "TOPIC #канал [текст_топика]"
-
-#, fuzzy
-msgid "channel ADD mask"
-msgstr "MODE #канал режимы"
-
-msgid "channel ADD mask level"
-msgstr ""
-
-#, fuzzy
-msgid "channel ADD message"
-msgstr "MODE #канал режимы"
-
-msgid "channel ADD word [SINGLE | START | END]"
-msgstr ""
-
-#, fuzzy
-msgid "channel ADD {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel APPEND topic"
-msgstr "TOPIC #канал [текст_топика]"
-
-#, fuzzy
-msgid "channel CLEAR"
-msgstr "DROP #канал"
-
-#, fuzzy
-msgid "channel CLEAR [what]"
-msgstr "TOPIC #канал [текст_топика]"
-
-#, fuzzy
-msgid "channel CLEAR [ALL]"
-msgstr "DROP #канал"
-
-#, fuzzy
-msgid "channel DEL num"
-msgstr "MODE #канал режимы"
-
-#, fuzzy
-msgid "channel DEL {mask | entry-num | list}"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-#, fuzzy
-msgid "channel DEL {nick | mask | entry-num | list}"
-msgstr "AOP #канал {ADD|DEL|LIST|CLEAR} [ник | номер запис]"
-
-#, fuzzy
-msgid "channel DEL {word | entry-num | list}"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-msgid "channel ENFORCE"
-msgstr ""
-
-#, fuzzy
-msgid "channel LIST"
-msgstr "DROP #канал"
-
-#, fuzzy
-msgid "channel LIST [mask | entry-num | list]"
-msgstr "AOP #канал {ADD|DEL|LIST|CLEAR} [ник | номер запис]"
-
-#, fuzzy
-msgid "channel LIST [mask | list]"
-msgstr "AOP #канал {ADD|DEL|LIST|CLEAR} [ник | номер запис]"
-
-msgid "channel LIST [mask | +flags]"
-msgstr ""
-
-#, fuzzy
-msgid "channel LOCK {ADD|DEL|SET|LIST} [what]"
-msgstr "AOP #канал {ADD|DEL|LIST|CLEAR} [ник | номер запис]"
-
-#, fuzzy
-msgid "channel RESET"
-msgstr "SET #канал GREET {ON|OFF}"
-
-#, fuzzy
-msgid "channel SET modes"
-msgstr "MODE #канал режимы"
-
-msgid "channel SET type level"
-msgstr ""
-
-#, fuzzy
-msgid "channel VIEW [mask | entry-num | list]"
-msgstr "AOP #канал {ADD|DEL|LIST|CLEAR} [ник | номер запис]"
-
-#, fuzzy
-msgid "channel VIEW [mask | list]"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-#, fuzzy
-msgid "channel [description]"
-msgstr "REGISTER #канал описание"
-
-#, fuzzy
-msgid "channel [nick]"
-msgstr "UNBAN #канал [nick]"
-
-#, fuzzy
-msgid "channel [parameters]"
-msgstr "CLEAR #канал что_именно"
-
-#, fuzzy
-msgid "channel [user]"
-msgstr "UNBAN #канал [nick]"
-
-#, fuzzy
-msgid "channel [+expiry] [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [+expiry] {nick | mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [MODIFY] mask changes"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "channel [SET] [topic]"
-msgstr "TOPIC #канал [текст_топика]"
-
-#, fuzzy
-msgid "channel [UNLOCK|LOCK]"
-msgstr "DROP #канал"
-
-#, fuzzy
-msgid "channel {ON|OFF}"
-msgstr "SET #канал XOP {ON | OFF}"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [ln [secs]]]"
-msgstr "KICK #канал опция {ON|OFF} [параметры]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [min [percent]]]"
-msgstr "KICK #канал опция {ON|OFF} [параметры]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb [num]]"
-msgstr "KICK #канал опция {ON|OFF} [параметры]"
-
-#, fuzzy
-msgid "channel {ON|OFF} [ttb]"
-msgstr "SET #канал XOP {ON | OFF}"
-
-msgid "channel {DIS | DISABLE} type"
-msgstr ""
-
-#, fuzzy
-msgid "channel {ON | LEVEL | OFF}"
-msgstr "SET #канал SIGNKICK {ON | LEVEL | OFF}"
-
-#, fuzzy
-msgid "channel {ON | OFF}"
-msgstr "SET #канал XOP {ON | OFF}"
-
-msgid "email"
-msgstr ""
-
-#, fuzzy
-msgid "language"
-msgstr "SET LANGUAGE номер"
-
-#, fuzzy
-msgid "memo-text"
-msgstr "STAFF memo-text"
-
-#, fuzzy
-msgid "message"
-msgstr "GLOBAL сообщение"
-
-msgid "modname"
-msgstr ""
-
-msgid "new-display"
-msgstr ""
-
-#, fuzzy
-msgid "new-password"
-msgstr "GROUP главный_ник пароль"
-
-#, fuzzy
-msgid "nick"
-msgstr "INFO ник"
-
-#, fuzzy
-msgid "nick channel"
-msgstr "CANCEL {ник | #канал}"
-
-#, fuzzy
-msgid "nick channel [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "nick flags"
-msgstr "OLINE ник +флаги"
-
-#, fuzzy
-msgid "nick hostmask"
-msgstr "SET <ник> <хостмаска>."
-
-#, fuzzy
-msgid "nick newnick"
-msgstr "SVSNICK ник новый_ник "
-
-#, fuzzy
-msgid "nick [reason]"
-msgstr "BAN #channel nick [reason]"
-
-#, fuzzy
-msgid "nickname"
-msgstr "CHECK ник"
-
-#, fuzzy
-msgid "nickname address"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "nickname email"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "nickname language"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "nickname message"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "nickname new-display"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "nickname new-password"
-msgstr "GHOST ник [пароль]"
-
-#, fuzzy
-msgid "nickname [parameter]"
-msgstr "GHOST ник [пароль]"
-
-#, fuzzy
-msgid "nickname [password]"
-msgstr "GHOST ник [пароль]"
-
-#, fuzzy
-msgid "nickname [+expiry] [reason]"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-msgstr "SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
-
-#, fuzzy
-msgid "nickname {ON | OFF}"
-msgstr "SASET ник AUTOOP {ON | OFF}"
-
-#, fuzzy
-msgid "nickname {ON | QUICK | IMMED | OFF}"
-msgstr "SASET ник KILL {ON | QUICK | IMMED | OFF}"
-
-#, fuzzy
-msgid "option (channel | bot) settings"
-msgstr "SET (#канал | бот) опция параметр"
-
-#, fuzzy
-msgid "option channel parameters"
-msgstr "SEND {ник | #канал} текст_сообщения"
-
-#, fuzzy
-msgid "option channel {ON|OFF} [settings]"
-msgstr "KICK #канал опция {ON|OFF} [параметры]"
-
-msgid "option nickname parameters"
-msgstr ""
-
-#, fuzzy
-msgid "option parameters"
-msgstr "SET опция параметры"
-
-#, fuzzy
-msgid "option setting"
-msgstr "SET опция параметры"
-
-#, fuzzy
-msgid "passcode"
-msgstr "REGISTER пароль email"
-
-#, fuzzy
-msgid "password"
-msgstr "GROUP главный_ник пароль"
-
-#, fuzzy
-msgid "password [email]"
-msgstr "REGISTER пароль email"
-
-#, fuzzy
-msgid "password email"
-msgstr "REGISTER пароль email"
-
-#, fuzzy
-msgid "pattern [SUSPENDED] [NOEXPIRE]"
-msgstr "LIST маска [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-
-#, fuzzy
-msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-msgstr "LIST маска [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
-
-#, fuzzy
-msgid "server [reason]"
-msgstr "JUPE имя_сервера [причина]"
-
-#, fuzzy
-msgid "user modes"
-msgstr "MODE #канал режимы"
-
-#, fuzzy
-msgid "user [reason]"
-msgstr "JUPE имя_сервера [причина]"
-
-#, fuzzy
-msgid ""
-" \n"
-"SNLINE ADD adds the given realname mask to the SNLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SNLINE which does not expire, use +0. If the\n"
-"realname mask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current SNLINE default expiry time can be found with the\n"
-"STATS AKILL command.\n"
-" \n"
-"Note: because the realname mask may contain spaces, the\n"
-"separator between it and the reason is a colon."
-msgstr ""
-"Синтаксис: AKILL ADD [+срок_истечения] маска причина\n"
-" AKILL DEL {маска | номер_записи | список_записей}\n"
-" AKILL LIST [маска | список_записей]\n"
-" AKILL VIEW [маска | список_записей]\n"
-" AKILL CLEAR\n"
-"\n"
-"Позволяет Операторам сервисов управлять списком сервисных AKILL'ов.\n"
-"Любой пользователь, подпадающий под маску AKILL'а, будет немедленно\n"
-"отключен от сети посредством сервисного KILL'а с указанной причиной,\n"
-"и не важно, на каком сервере он сидит или к какому подключается.\n"
-"Помимо этого, если IRCd вашей сети это поддерживает, сервисы \n"
-"установят KLINE/GLINE на всех серверах вашей сети, в качестве маски\n"
-"бана будет использована соответствующая запись AKILL'а.\n"
-"\n"
-"Команда AKILL ADD добавляет маску вида идент@хост/ip с указанной\n"
-"причиной в список AKILL'ов (наличие причины - обязательно).\n"
-"Значение срока истечения - это целое число, которое может быть\n"
-"одним из: d (дней), h (часов), или m (минут). Такие сочетания\n"
-"как 1h30m - недопустимы. Если единица измерения не указана, то\n"
-"по-умолчанию, она будет принята за \"d\" - \"дни\" (таким образом,\n"
-"+30 будет означать 30 дней). Чтобы добавить постоянный AKILL,\n"
-"используйте время истечения равным +0. Помните, что если в качестве\n"
-"первого символа второго параметра указан знак \"+\" - вы должны\n"
-"обозначить сроки истечения записи, даже если это будет значение\n"
-"по-умочанию.\n"
-"Текущее время истечения AKILL'а по-умолчанию, можно узнать с помощью\n"
-"команды STATS AKILL.\n"
-"\n"
-"Команда AKILL DEL удаляет указанную маску из списка AKILL'ов.\n"
-"В качестве параметра вы можете указать не только маску AKILL'а, но\n"
-"и конкретный номер записи или список записей (см. примеры\n"
-"использования команды LIST ниже).\n"
-"\n"
-"Команда AKILL LIST показывает текущий список AKILL'ов.\n"
-"В качестве дополнительного параметра, вы можете указать символьную\n"
-"маску, что позволит вам получить список с конкретными записями,\n"
-"попадающими под эту маску, или же, вы можете указать список записей.\n"
-"Например:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" отобразит все записи с 2-ой по 5-ю и с 7-ой по 9-ю.\n"
-"\n"
-"AKILL VIEW более подробная версия AKILL LIST, она покажет вам\n"
-"кто добавил AKILL, время установки AKILL'а, когда он истекает, ну\n"
-"и, конечно же, маску вида идент@хост/ip и причину AKILL'а.\n"
-"\n"
-"AKILL CLEAR позволяет полностью очистить список AKILL'ов."
-
-#, fuzzy
-msgid ""
-" \n"
-"SQLINE ADD adds the given (nick's) mask to the SQLINE\n"
-"list for the given reason (which must be given).\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an SQLINE which does not expire, use +0.\n"
-"If the mask to be added starts with a +, an expiry time\n"
-"must be given, even if it is the same as the default. The\n"
-"current SQLINE default expiry time can be found with the\n"
-"STATS AKILL command."
-msgstr ""
-"Синтаксис: AKILL ADD [+срок_истечения] маска причина\n"
-" AKILL DEL {маска | номер_записи | список_записей}\n"
-" AKILL LIST [маска | список_записей]\n"
-" AKILL VIEW [маска | список_записей]\n"
-" AKILL CLEAR\n"
-"\n"
-"Позволяет Операторам сервисов управлять списком сервисных AKILL'ов.\n"
-"Любой пользователь, подпадающий под маску AKILL'а, будет немедленно\n"
-"отключен от сети посредством сервисного KILL'а с указанной причиной,\n"
-"и не важно, на каком сервере он сидит или к какому подключается.\n"
-"Помимо этого, если IRCd вашей сети это поддерживает, сервисы \n"
-"установят KLINE/GLINE на всех серверах вашей сети, в качестве маски\n"
-"бана будет использована соответствующая запись AKILL'а.\n"
-"\n"
-"Команда AKILL ADD добавляет маску вида идент@хост/ip с указанной\n"
-"причиной в список AKILL'ов (наличие причины - обязательно).\n"
-"Значение срока истечения - это целое число, которое может быть\n"
-"одним из: d (дней), h (часов), или m (минут). Такие сочетания\n"
-"как 1h30m - недопустимы. Если единица измерения не указана, то\n"
-"по-умолчанию, она будет принята за \"d\" - \"дни\" (таким образом,\n"
-"+30 будет означать 30 дней). Чтобы добавить постоянный AKILL,\n"
-"используйте время истечения равным +0. Помните, что если в качестве\n"
-"первого символа второго параметра указан знак \"+\" - вы должны\n"
-"обозначить сроки истечения записи, даже если это будет значение\n"
-"по-умочанию.\n"
-"Текущее время истечения AKILL'а по-умолчанию, можно узнать с помощью\n"
-"команды STATS AKILL.\n"
-"\n"
-"Команда AKILL DEL удаляет указанную маску из списка AKILL'ов.\n"
-"В качестве параметра вы можете указать не только маску AKILL'а, но\n"
-"и конкретный номер записи или список записей (см. примеры\n"
-"использования команды LIST ниже).\n"
-"\n"
-"Команда AKILL LIST показывает текущий список AKILL'ов.\n"
-"В качестве дополнительного параметра, вы можете указать символьную\n"
-"маску, что позволит вам получить список с конкретными записями,\n"
-"попадающими под эту маску, или же, вы можете указать список записей.\n"
-"Например:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" отобразит все записи с 2-ой по 5-ю и с 7-ой по 9-ю.\n"
-"\n"
-"AKILL VIEW более подробная версия AKILL LIST, она покажет вам\n"
-"кто добавил AKILL, время установки AKILL'а, когда он истекает, ну\n"
-"и, конечно же, маску вида идент@хост/ip и причину AKILL'а.\n"
-"\n"
-"AKILL CLEAR позволяет полностью очистить список AKILL'ов."
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Accounts that are not used anymore are subject to\n"
-"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
-msgstr ""
-"Помните, что неиспользуемые в течение длительного периода ники\n"
-"автоматически удаляются из базы данных. Срок существования неактивных\n"
-"ников: %d дней."
-
-#, fuzzy
-msgid ""
-" \n"
-"Available commands are:"
-msgstr "Справочная информация по %s отсутствует."
-
-#, c-format
-msgid ""
-" \n"
-"Bot will join a channel whenever there is at least\n"
-"%d user(s) on it."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Enables or disables fantasy mode on a channel.\n"
-"When it is enabled, users will be able to use\n"
-"fantasy commands on a channel when prefixed\n"
-"with one of the following fantasy characters: %s\n"
-" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
-msgstr ""
-"Синтаксис: SET #канал FANTASY {ON|OFF}\n"
-"\n"
-"Активирует/деактивирует FANTASY-режим бота для указанного канала.\n"
-"Он позволяет посетителям канала использовать удобные аналоги аналоги\n"
-"стандартных команд прямо на канале, например:\n"
-"\n"
-"!protect, !deprotect - установка статуса защиты (администратора)\n"
-" на себя (без парамеров) или указанному нику.\n"
-" !halfop, !dehalfop - запрос статуса полуоператора канала, в\n"
-" качестве параметра вы можете указать ник\n"
-" посетителя канала.\n"
-" !owner, !deowner - запрос статуса владельца канала (команда\n"
-" доступна лишь владельцу канала).\n"
-" !voice, !devoice - запрос статуса войса канала, в качестве\n"
-" параметра вы можете указать ник посетителя\n"
-" канала.\n"
-" !op, !deop - запрос статуса оператора канала, в качестве\n"
-" параметра вы можете указать ник посетителя\n"
-" канала.\n"
-" !kick, !kb - кикнуть или кикнуть и забанить указанного\n"
-" посетителя канала с указанной причиной\n"
-" (например: !kick Vasya пшел вон отсюда!).\n"
-" !seen - запрос информации о том, когда указанный\n"
-" ник последний раз был в сети.\n"
-"\n"
-"Примечание: для использования команд FANTASY-режима, вы должны\n"
-"иметь соответствующий уровень доступа на канале (он определяется\n"
-"значением настройки FANTASIA, по-умолчанию это 3 или VOP).\n"
-"Помимо этого, ваш уровень доступа должен соответсвовать требованиям\n"
-"команды, например, вы не сможете использовать команду !op, если\n"
-"ваш уровень доступа не соответствует значению для OP/DEOP (или вы\n"
-"не AOP/SOP канала).\n"
-"\n"
-"Примечание 2: такие команды, как: !halfop, !dehalfop, !protect,\n"
-"!deprotect, !owner и !deowner - могут быть недоступны в вашей\n"
-"сети."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables greet mode on a channel.\n"
-"When it is enabled, the bot will display greet\n"
-"messages of users joining the channel, provided\n"
-"they have enough access to the channel."
-msgstr ""
-"Синтаксис: SET #канал GREET {ON|OFF}\n"
-"\n"
-"Включает или выключает режим показа приветствий на канале. Если\n"
-"опция включена, бот будет показывать приветственные сообщения для\n"
-"всех тех пользователей, которые имеют достаточный уровень доступа\n"
-"на канале и установили себе текст приветствия (см. настройки ника)."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables ops protection mode on a channel.\n"
-"When it is enabled, ops won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
-msgstr ""
-"Синтаксис: SET #канал DONTKICKOPS {ON|OFF}\n"
-"\n"
-"Позволяет включить или выключить режим исключения операторов канала\n"
-"из условий киков за нарушения. Данное действие распространится на\n"
-"всех операторов канала, не важно, соответствует их уровень доступа\n"
-"значению установки NOKICK или нет."
-
-#, fuzzy
-msgid ""
-" \n"
-"Enables or disables voices protection mode on a channel.\n"
-"When it is enabled, voices won't be kicked by the bot\n"
-"even if they don't match the NOKICK level."
-msgstr ""
-"Синтаксис: SET #канал DONTKICKVOICES {ON|OFF}\n"
-"\n"
-"Позволяет включить или выключить режим исключения войсов канала\n"
-"из условий киков за нарушения. Данное действие распространится на\n"
-"всех войсов канала, не важно, соответствует их уровень доступа\n"
-"значению установки NOKICK или нет."
-
-#, c-format
-msgid ""
-" \n"
-"Fantasy commands may be prefixed with one of the following characters: %s\n"
-msgstr ""
-
-msgid ""
-" \n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"Note that any channel which is not used for %d days\n"
-"(i.e. which no user on the channel's access list enters\n"
-"for that period of time) will be automatically dropped."
-msgstr ""
-"Помните, что любой канал, не использующийся в течение %d дней\n"
-"(т.е. ни один пользователь, прописанный в списке доступа канала,\n"
-"не посетит канал в течении данного времени), будет автоматически\n"
-"удален из базы данных сервисов."
-
-#, c-format
-msgid ""
-" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-msgstr ""
-
-#, fuzzy
-msgid ""
-" \n"
-"Services Operators can also drop any nickname without needing\n"
-"to identify for the nick, and may view the access list for\n"
-"any nickname."
-msgstr ""
-" \n"
-"Администраторы сервисов могут удалить любой ник без идентификации\n"
-"к нему, а так же, могут смотреть список доступа любого ника\n"
-"(более подробно см. /msg %s ACCESS LIST ник)."
-
-#, fuzzy
-msgid ""
-" \n"
-"Services Operators can also, depending on their access drop\n"
-"any channel, view (and modify) the access, levels and akick\n"
-"lists and settings for any channel."
-msgstr ""
-" \n"
-"Администраторы сервисов могут удалить любой канал без идентификации\n"
-"к нему в качестве владельца, могут просматривать списки доступа\n"
-"каналов, а так же, списки акиков и установки уровней доступа каналов."
-
-msgid ""
-" \n"
-"Sets the time bot bans expire in. If enabled, any bans placed by\n"
-"bots, such as flood kicker, badwords kicker, etc. will automatically\n"
-"be removed after the given time. Set to 0 to disable bans from\n"
-"automatically expiring."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-" \n"
-"The %s ADD command adds the given nickname to the\n"
-"%s list.\n"
-" \n"
-"The %s DEL command removes the given nick from the\n"
-"%s list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The %s LIST command displays the %s list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" %s #channel LIST 2-5,7-9\n"
-" Lists %s entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The %s CLEAR command clears all entries of the\n"
-"%s list."
-msgstr ""
-"Синтаксис: HOP #канал ADD ник\n"
-" HOP #канал DEL {ник | номер_записи | список_записей}\n"
-" HOP #канал LIST [маска | список_записей]\n"
-" HOP #канал CLEAR\n"
-"\n"
-"Позволяет управлять списком HOP'ов (полуоператоров) вашего канала.\n"
-"Привилегии HOP'а дают пользователю возможность получить статус хопа\n"
-"сразу при входе на канал, или запросить его вручную, через сервисы.\n"
-"\n"
-"Команда HOP ADD добавляет указанный ник в список HOP'ов.\n"
-"\n"
-"Команда HOP DEL удаляет указанный ник из списка HOP'ов. В качестве\n"
-"параметра вы можете указать не только ник, но и конкретный номер\n"
-"записи или список записей (см. примеры использования LIST ниже).\n"
-"\n"
-"Команда HOP LIST выводит текущий список HOP'ов канала. В качестве\n"
-"дополнительного параметра, вы можете указать символьную маску, что\n"
-"позволит вам получить список с конкретными никами, попадающими под\n"
-"эту маску, или же, вы можете указать список записей.\n"
-"\n"
-"Например:\n"
-"\n"
-" HOP #канал LIST 2-5,7-9\n"
-" отобразит все записи со 2-ой по 5-ую, и с 7-ой по 9-ю.\n"
-" HOP #канал LIST *vas*\n"
-" отобразит все записи, которые содержат подстроку \"vas\"\n"
-"\n"
-"Команда HOP CLEAR позволяет полностью очистить список HOP'ов.\n"
-"\n"
-"Команды HOP ADD, HOP DEL и HOP LIST могут использовать AOP'ы\n"
-"канала или выше, команду HOP CLEAR может использовать только\n"
-"владелец канала.\n"
-"\n"
-"Помните, что данная команда работает только в случае использования\n"
-"системы привилегий xOP. Если вы используете систему LEVELS, все\n"
-"изменения списка доступа канала должны производится посредством\n"
-"команды ACCESS. Для более подробной информации по использованию\n"
-"команды ACCESS и системы привилегий xOP см. справочную информацию\n"
-"по /msg %s HELP ACCESS и /msg %s HELP SET XOP."
-
-#, c-format
-msgid ""
-" \n"
-"The AKICK DEL command removes the given nick or mask\n"
-"from the AutoKick list. It does not, however, remove any\n"
-"bans placed by an AutoKick; those must be removed\n"
-"manually.\n"
-" \n"
-"The AKICK LIST command displays the AutoKick list, or\n"
-"optionally only those AutoKick entries which match the\n"
-"given mask.\n"
-" \n"
-"The AKICK VIEW command is a more verbose version of the\n"
-"AKICK LIST command.\n"
-" \n"
-"The AKICK ENFORCE command causes %s to enforce the\n"
-"current AKICK list by removing those users who match an\n"
-"AKICK mask.\n"
-" \n"
-"The AKICK CLEAR command clears all entries of the\n"
-"akick list."
-msgstr ""
-
-#, fuzzy
-msgid ""
-" \n"
-"The AKILL DEL command removes the given mask from the\n"
-"AKILL list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The AKILL LIST command displays the AKILL list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" AKILL LIST 2-5,7-9\n"
-" Lists AKILL entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"AKILL VIEW is a more verbose version of AKILL LIST, and\n"
-"will show who added an AKILL, the date it was added, and when\n"
-"it expires, as well as the user@host/ip mask and reason.\n"
-" \n"
-"AKILL CLEAR clears all entries of the AKILL list."
-msgstr ""
-"Синтаксис: HOP #канал ADD ник\n"
-" HOP #канал DEL {ник | номер_записи | список_записей}\n"
-" HOP #канал LIST [маска | список_записей]\n"
-" HOP #канал CLEAR\n"
-"\n"
-"Позволяет управлять списком HOP'ов (полуоператоров) вашего канала.\n"
-"Привилегии HOP'а дают пользователю возможность получить статус хопа\n"
-"сразу при входе на канал, или запросить его вручную, через сервисы.\n"
-"\n"
-"Команда HOP ADD добавляет указанный ник в список HOP'ов.\n"
-"\n"
-"Команда HOP DEL удаляет указанный ник из списка HOP'ов. В качестве\n"
-"параметра вы можете указать не только ник, но и конкретный номер\n"
-"записи или список записей (см. примеры использования LIST ниже).\n"
-"\n"
-"Команда HOP LIST выводит текущий список HOP'ов канала. В качестве\n"
-"дополнительного параметра, вы можете указать символьную маску, что\n"
-"позволит вам получить список с конкретными никами, попадающими под\n"
-"эту маску, или же, вы можете указать список записей.\n"
-"\n"
-"Например:\n"
-"\n"
-" HOP #канал LIST 2-5,7-9\n"
-" отобразит все записи со 2-ой по 5-ую, и с 7-ой по 9-ю.\n"
-" HOP #канал LIST *vas*\n"
-" отобразит все записи, которые содержат подстроку \"vas\"\n"
-"\n"
-"Команда HOP CLEAR позволяет полностью очистить список HOP'ов.\n"
-"\n"
-"Команды HOP ADD, HOP DEL и HOP LIST могут использовать AOP'ы\n"
-"канала или выше, команду HOP CLEAR может использовать только\n"
-"владелец канала.\n"
-"\n"
-"Помните, что данная команда работает только в случае использования\n"
-"системы привилегий xOP. Если вы используете систему LEVELS, все\n"
-"изменения списка доступа канала должны производится посредством\n"
-"команды ACCESS. Для более подробной информации по использованию\n"
-"команды ACCESS и системы привилегий xOP см. справочную информацию\n"
-"по /msg %s HELP ACCESS и /msg %s HELP SET XOP."
-
-#, fuzzy
-msgid ""
-" \n"
-"The SNLINE DEL command removes the given mask from the\n"
-"SNLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SNLINE LIST command displays the SNLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SNLINE LIST 2-5,7-9\n"
-" Lists SNLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SNLINE VIEW is a more verbose version of SNLINE LIST, and\n"
-"will show who added an SNLINE, the date it was added, and when\n"
-"it expires, as well as the realname mask and reason.\n"
-" \n"
-"SNLINE CLEAR clears all entries of the SNLINE list."
-msgstr ""
-"Синтаксис: HOP #канал ADD ник\n"
-" HOP #канал DEL {ник | номер_записи | список_записей}\n"
-" HOP #канал LIST [маска | список_записей]\n"
-" HOP #канал CLEAR\n"
-"\n"
-"Позволяет управлять списком HOP'ов (полуоператоров) вашего канала.\n"
-"Привилегии HOP'а дают пользователю возможность получить статус хопа\n"
-"сразу при входе на канал, или запросить его вручную, через сервисы.\n"
-"\n"
-"Команда HOP ADD добавляет указанный ник в список HOP'ов.\n"
-"\n"
-"Команда HOP DEL удаляет указанный ник из списка HOP'ов. В качестве\n"
-"параметра вы можете указать не только ник, но и конкретный номер\n"
-"записи или список записей (см. примеры использования LIST ниже).\n"
-"\n"
-"Команда HOP LIST выводит текущий список HOP'ов канала. В качестве\n"
-"дополнительного параметра, вы можете указать символьную маску, что\n"
-"позволит вам получить список с конкретными никами, попадающими под\n"
-"эту маску, или же, вы можете указать список записей.\n"
-"\n"
-"Например:\n"
-"\n"
-" HOP #канал LIST 2-5,7-9\n"
-" отобразит все записи со 2-ой по 5-ую, и с 7-ой по 9-ю.\n"
-" HOP #канал LIST *vas*\n"
-" отобразит все записи, которые содержат подстроку \"vas\"\n"
-"\n"
-"Команда HOP CLEAR позволяет полностью очистить список HOP'ов.\n"
-"\n"
-"Команды HOP ADD, HOP DEL и HOP LIST могут использовать AOP'ы\n"
-"канала или выше, команду HOP CLEAR может использовать только\n"
-"владелец канала.\n"
-"\n"
-"Помните, что данная команда работает только в случае использования\n"
-"системы привилегий xOP. Если вы используете систему LEVELS, все\n"
-"изменения списка доступа канала должны производится посредством\n"
-"команды ACCESS. Для более подробной информации по использованию\n"
-"команды ACCESS и системы привилегий xOP см. справочную информацию\n"
-"по /msg %s HELP ACCESS и /msg %s HELP SET XOP."
-
-#, fuzzy
-msgid ""
-" \n"
-"The SQLINE DEL command removes the given mask from the\n"
-"SQLINE list if it is present. If a list of entry numbers is\n"
-"given, those entries are deleted. (See the example for LIST\n"
-"below.)\n"
-" \n"
-"The SQLINE LIST command displays the SQLINE list.\n"
-"If a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" SQLINE LIST 2-5,7-9\n"
-" Lists SQLINE entries numbered 2 through 5 and 7\n"
-" through 9.\n"
-" \n"
-"SQLINE VIEW is a more verbose version of SQLINE LIST, and\n"
-"will show who added an SQLINE, the date it was added, and when\n"
-"it expires, as well as the mask and reason.\n"
-" \n"
-"SQLINE CLEAR clears all entries of the SQLINE list."
-msgstr ""
-"Синтаксис: HOP #канал ADD ник\n"
-" HOP #канал DEL {ник | номер_записи | список_записей}\n"
-" HOP #канал LIST [маска | список_записей]\n"
-" HOP #канал CLEAR\n"
-"\n"
-"Позволяет управлять списком HOP'ов (полуоператоров) вашего канала.\n"
-"Привилегии HOP'а дают пользователю возможность получить статус хопа\n"
-"сразу при входе на канал, или запросить его вручную, через сервисы.\n"
-"\n"
-"Команда HOP ADD добавляет указанный ник в список HOP'ов.\n"
-"\n"
-"Команда HOP DEL удаляет указанный ник из списка HOP'ов. В качестве\n"
-"параметра вы можете указать не только ник, но и конкретный номер\n"
-"записи или список записей (см. примеры использования LIST ниже).\n"
-"\n"
-"Команда HOP LIST выводит текущий список HOP'ов канала. В качестве\n"
-"дополнительного параметра, вы можете указать символьную маску, что\n"
-"позволит вам получить список с конкретными никами, попадающими под\n"
-"эту маску, или же, вы можете указать список записей.\n"
-"\n"
-"Например:\n"
-"\n"
-" HOP #канал LIST 2-5,7-9\n"
-" отобразит все записи со 2-ой по 5-ую, и с 7-ой по 9-ю.\n"
-" HOP #канал LIST *vas*\n"
-" отобразит все записи, которые содержат подстроку \"vas\"\n"
-"\n"
-"Команда HOP CLEAR позволяет полностью очистить список HOP'ов.\n"
-"\n"
-"Команды HOP ADD, HOP DEL и HOP LIST могут использовать AOP'ы\n"
-"канала или выше, команду HOP CLEAR может использовать только\n"
-"владелец канала.\n"
-"\n"
-"Помните, что данная команда работает только в случае использования\n"
-"системы привилегий xOP. Если вы используете систему LEVELS, все\n"
-"изменения списка доступа канала должны производится посредством\n"
-"команды ACCESS. Для более подробной информации по использованию\n"
-"команды ACCESS и системы привилегий xOP см. справочную информацию\n"
-"по /msg %s HELP ACCESS и /msg %s HELP SET XOP."
-
-#, fuzzy
-msgid ""
-" \n"
-"This option makes a channel unassignable. If a bot\n"
-"is already assigned to the channel, it is unassigned\n"
-"automatically when you enable it."
-msgstr ""
-"Синтаксис: SET #канал NOBOT {ON|OFF}\n"
-"\n"
-"Активирует/деактивирует режим NOBOT для указанного канала. Включение\n"
-"данного режима запретит администарции канала использовать бота на\n"
-"своем канале.\n"
-"Если бот уже установлен на канале, он будет автоматически удален с\n"
-"него сразу же после включения данной опции."
-
-#, fuzzy
-msgid ""
-" \n"
-"This option prevents a bot from being assigned to a\n"
-"channel by users that aren't IRC Operators."
-msgstr ""
-"Синтаксис: SET ник_бота PRIVATE {ON|OFF}\n"
-"\n"
-"Установите данную опцию на указанного бота, если хотите запретить\n"
-"обычным пользователям использовать его. Доступ к нему будет только\n"
-"у администрации сети."
-
-#, c-format
-msgid ""
-" \n"
-"Type %s%s HELP command for help on any of the\n"
-"above commands."
-msgstr ""
-
-#, c-format
-msgid " %s is online using this oper block."
-msgstr ""
-
-#, c-format
-msgid " Command %s on %s is linked to %s"
-msgstr ""
-
-#, fuzzy, c-format
-msgid " Providing service: %s"
-msgstr "Предоставляемая команда: /msg %s %s"
-
-msgid " This oper is configured in the configuration file."
-msgstr ""
-
-#, c-format
-msgid " Loaded at: %p"
-msgstr ""
-
-#, c-format
-msgid " but %s mysteriously dematerialized."
-msgstr ""
-
-#, c-format
-msgid ""
-"\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr ""
-"Адресация вида \"/msg %s\" больше не поддерживается. Используйте \"/msg %s@%s"
-"\" или \"/%s\"."
-
-#, fuzzy
-msgid "\"Jupiter\" a server"
-msgstr " JUPE \"Джуп\" указанного сервера сети"
-
-#, fuzzy, c-format
-msgid "%-8s %s"
-msgstr "%-20s %s@%s"
-
-#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
-
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr ""
-
-#, c-format
-msgid "%c is an unknown status mode."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%c%c is not locked on %s."
-msgstr "%s не уведомляется о новых собщениях."
-
-#, fuzzy, c-format
-msgid "%c%c%s has been unlocked from %s."
-msgstr "Nick %s has been ungrouped from %s."
-
-#, fuzzy, c-format
-msgid "%d access entries from %s have been cloned to %s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s"
-
-#, c-format
-msgid "%d bots available."
-msgstr "Количество доступных ботов: %d"
-
-#, fuzzy, c-format
-msgid "%d modules loaded."
-msgstr "Количество загруженных модулей: %d"
-
-#, fuzzy, c-format
-msgid "%d nickname(s) in the group."
-msgstr "Количество ников в группе: %d"
-
-#, c-format
-msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s %s list is empty."
-msgstr "Список AOP'ов канала %s пуст."
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban)"
-msgstr "Цензор жирных букв...: %s (%d киков до бана)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; %d lines in %ds)"
-msgstr "Цензор флуда.........: %s (%d киков до бана; %d линий из %ds)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; %d times)"
-msgstr "Цензор повторов......: %s (%d киков до бана; %d раз)"
-
-#, fuzzy, c-format
-msgid "%s (%d kick(s) to ban; minimum %d/%d%%)"
-msgstr "Цензор CapsLOCK......: %s (%d киков до бана; минимум %d/%d%%)"
-
-#, fuzzy, c-format
-msgid "%s (%d lines in %ds)"
-msgstr " %s (истекает %s)"
-
-#, c-format
-msgid "%s (%d times)"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was kicked from %s (\"%s\") %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was kicked from a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen changing nick from %s to %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen changing nick to %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen connecting %s ago (%s)%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen joining %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen joining a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen parting %s %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen parting a secret channel %s ago%s"
-msgstr ""
-
-#, c-format
-msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s (minimum %d/%d%%)"
-msgstr "Цензор CapsLOCK......: %s (минимум %d/%d%%)"
-
-#, c-format
-msgid "%s access list is empty."
-msgstr "Список доступа канала %s пуст."
-
-#, fuzzy, c-format
-msgid "%s added to %s's auto join list."
-msgstr "Запись вида %s успешно добавлена в список автокиков канала %s."
-
-#, fuzzy, c-format
-msgid "%s already exists."
-msgstr "Бот с ником %s уже существует."
-
-#, c-format
-msgid "%s autokick list is empty."
-msgstr "Список автокиков канала %s пуст."
-
-#, c-format
-msgid "%s bad words list is empty."
-msgstr "Список плохих слов канала %s пуст."
-
-#, fuzzy, c-format
-msgid "%s cannot be the successor on channel %s as they are the founder."
-msgstr "%s не может быть наследником канала %s так как он его владелец."
-
-#, c-format
-msgid "%s commands:"
-msgstr "Список команд %s:"
-
-#, c-format
-msgid "%s coverage is too wide; Please use a more specific mask."
-msgstr ""
-
-#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s сейчас имеет %d сообщений, %d из них все еще не прочитаны."
-
-#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s сейчас имеет %d сообщений, 1 из них все еще не прочитано."
-
-#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s сейчас имеет %d сообщений."
-
-#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s сейчас имеет %d сообщений, ни одно из них не прочитано."
-
-#, c-format
-msgid "%s currently has 1 memo, and it has not yet been read."
-msgstr "%s сейчас имеет 1 новое, непрочитанное сообщение."
-
-#, c-format
-msgid "%s currently has 1 memo."
-msgstr "%s сейчас имеет 1 сообщение."
-
-#, c-format
-msgid "%s currently has no memos."
-msgstr "Список сообщений для %s на данный момент пуст."
-
-#, fuzzy, c-format
-msgid "%s deleted from the %s forbid list."
-msgstr "Запись вида %s успешно удалена из списка плохих слов канала %s."
-
-#, fuzzy, c-format
-msgid "%s for %s set to %s."
-msgstr "Виртуальный хост для %s установлен на %s."
-
-#, fuzzy, c-format
-msgid "%s for %s unset."
-msgstr "Наследник канал %s удален."
-
-#, c-format
-msgid "%s had an invalid key specified, and was thus ignored."
-msgstr ""
-
-#, c-format
-msgid "%s has no memo limit."
-msgstr "Лимит сообщений для %s отключен."
-
-#, fuzzy, c-format
-msgid "%s has no memos."
-msgstr "Лимит сообщений для %s отключен."
-
-#, fuzzy, c-format
-msgid "%s has no new memos."
-msgstr "Лимит сообщений для %s отключен."
-
-#, c-format
-msgid "%s is %s"
-msgstr "%s это %s"
-
-#, fuzzy, c-format
-msgid "%s is a Services Operator of type %s."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy, c-format
-msgid "%s is a client on services."
-msgstr "%s сейчас в сети."
-
-#, fuzzy, c-format
-msgid "%s is a network service."
-msgstr "%s сейчас в сети."
-
-#, fuzzy, c-format
-msgid "%s is already covered by %s."
-msgstr ""
-"Указанная маска вида %s совпадает с одной из масок в списке AKILL'ов: %s."
-
-#, fuzzy, c-format
-msgid "%s is already on %s's auto join list."
-msgstr "Маска вида %s успешно добавлена в ваш список доступа."
-
-#, fuzzy, c-format
-msgid "%s is an unconfirmed nickname."
-msgstr "Дополнительно: регистрация этого ника никогда не истечет."
-
-#, c-format
-msgid ""
-"%s is another way to modify the channel access list, similar to\n"
-"the XOP and ACCESS methods."
-msgstr ""
-
-#, c-format
-msgid "%s is currently online."
-msgstr "%s сейчас в сети."
-
-#, c-format
-msgid "%s is disabled"
-msgstr "Режим %s: отключен."
-
-#, c-format
-msgid "%s is enabled"
-msgstr "Режим %s: включен."
-
-#, fuzzy, c-format
-msgid "%s is not a valid IP address."
-msgstr "Число %s не является валидным номером шаблона банмаски."
-
-#, fuzzy, c-format
-msgid "%s is not a valid command."
-msgstr "Число %s не является валидным номером шаблона банмаски."
-
-#, fuzzy, c-format
-msgid "%s is not a valid logging method."
-msgstr "Число %s не является валидным номером шаблона банмаски."
-
-#, c-format
-msgid "%s is not notified of new memos."
-msgstr "%s не уведомляется о новых собщениях."
-
-#, c-format
-msgid "%s is notified of new memos at logon and when they arrive."
-msgstr ""
-"%s уведомляется о новых сообщениях сразу после идентификации или по мере "
-"прихода новых собщений."
-
-#, c-format
-msgid "%s is notified of new memos at logon."
-msgstr "%s уведомляется о новых сообщениях сразу после идентификации к нику."
-
-#, c-format
-msgid "%s is notified when new memos arrive."
-msgstr "%s уведомляется о новых сообщениях сразу при поступлении оных."
-
-#, c-format
-msgid "%s is on the channel right now (as %s)!"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s is on the channel right now!"
-msgstr "Уровень доступа к %s на канале %s отключен."
-
-#, fuzzy, c-format
-msgid "%s list for %s"
-msgstr "Список доступа для %s:"
-
-#, fuzzy, c-format
-msgid "%s list is empty."
-msgstr "Список AOP'ов канала %s пуст."
-
-#, fuzzy, c-format
-msgid "%s locked on %s."
-msgstr "%s не уведомляется о новых собщениях."
-
-#, fuzzy, c-format
-msgid "%s not found."
-msgstr "Ник %s в списке AOP'ов канала %s не обнаружен."
-
-#, c-format
-msgid "%s settings:"
-msgstr ""
-
-#, c-format
-msgid "%s was last seen here %s ago."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "%s was not found on %s's auto join list."
-msgstr "Запись вида %s в списке автокиков канала %s не обнаружена."
-
-#, fuzzy, c-format
-msgid "%s was removed from %s's auto join list."
-msgstr "Запись вида %s удалена из списка автокиков канала %s."
-
-#, c-format
-msgid "%s will not send you any notification of memos."
-msgstr "С этого момента, %s не будет уведомлять вас о новых сообщениях."
-
-#, c-format
-msgid "%s will now notify you of memos when they are sent to you."
-msgstr ""
-"С этого момента, %s будет уведомлять вас о новых сообщениях сразу по "
-"поступлении оных."
-
-#, c-format
-msgid ""
-"%s will now notify you of memos when you log on and when they are sent to "
-"you."
-msgstr ""
-"С этого момента, %s будет уведомлять вас о новых сообщениях сразу после "
-"идентификации к нику или при поступлении новых сообщений."
-
-#, c-format
-msgid "%s will now notify you of memos when you log on or unset /AWAY."
-msgstr ""
-"С этого момента, %s будет уведомлять вас о новых сообщениях сразу после "
-"идентификации к нику или по возвращению из режима /AWAY."
-
-#, c-format
-msgid "%s!%s@%s (%s) added to the bot list."
-msgstr "%s!%s@%s (%s) добавлен в список ботов."
-
-#, fuzzy, c-format
-msgid "%s's access list is empty."
-msgstr "Список доступа канала %s пуст."
-
-#, fuzzy, c-format
-msgid "%s's auto join list is empty."
-msgstr "Список автокиков канала %s пуст."
-
-#, fuzzy, c-format
-msgid "%s's auto join list:"
-msgstr " AKICK Управление списком автокиков канала"
-
-#, fuzzy, c-format
-msgid "%s's certificate list is empty."
-msgstr "Ваш список доступа пуст."
-
-#, c-format
-msgid "%s's memo limit is %d, and may not be changed."
-msgstr "Лимит собщений для %s равен %d и не может быть изменен."
-
-#, c-format
-msgid "%s's memo limit is %d."
-msgstr "Лимит сообщений для %s равен %d."
-
-#, c-format
-msgid "(%s ago)"
-msgstr ""
-
-#, c-format
-msgid "(%s from now)"
-msgstr ""
-
-msgid "(Split)"
-msgstr ""
-
-#, c-format
-msgid "(by %s on %s) %s"
-msgstr ""
-
-#, fuzzy
-msgid "(disabled)"
-msgstr "Режим %s: включен."
-
-msgid "(founder only)"
-msgstr ""
-
-msgid "(now)"
-msgstr ""
-
-msgid "* AKILL any new clients connecting"
-msgstr "* Автоматическая установка AKILL'ов на всех новых клиентов."
-
-#, fuzzy, c-format
-msgid "* Force channel modes (%s) to be set on all channels"
-msgstr "* Принудительная установка режимов %s на все каналы сети."
-
-#, fuzzy
-msgid "* Ignore non-opers with a message"
-msgstr "* Игнорирование простых пользователей с оповещением их об этом."
-
-#, fuzzy
-msgid "* Kill any new clients connecting"
-msgstr "* Автоматическое отключение от сети всех новых клиентов."
-
-#, fuzzy
-msgid "* No mode lock changes"
-msgstr "* Запрет на изменение параметров MLOCK."
-
-msgid "* No new channel registrations"
-msgstr "* Запрет на регистрацию каналов."
-
-msgid "* No new memos sent"
-msgstr "* Запрет на отправку мемо-сообщений."
-
-msgid "* No new nick registrations"
-msgstr "* Запрет на регистрацию ников."
-
-msgid "* Silently ignore non-opers"
-msgstr "* Игнорирование простых пользователей без уведомления их об этом."
-
-#, c-format
-msgid "* Use the reduced session limit of %d"
-msgstr "* Уменьшение лимита сессий с одного хоста до %d."
-
-#, c-format
-msgid ", but %s mysteriously dematerialized."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ". %s is still online."
-msgstr "%s сейчас в сети."
-
-msgid "<unknown>"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"A confirmation e-mail has been sent to %s. Follow the instructions in it to "
-"change your e-mail address."
-msgstr ""
-"Auth-код был выслан на %s, для завершения регистрации используйте команду /"
-"msg %s confirm auth-код"
-
-msgid "A massmemo has been sent to all registered users."
-msgstr ""
-"Массовое сообщение успешно отправлено всем зарегистрированным пользователям."
-
-msgid ""
-"A memo informing the user will also be sent, which includes the reason for "
-"the rejection if supplied."
-msgstr ""
-
-msgid "A memo informing the user will also be sent."
-msgstr ""
-
-#, c-format
-msgid ""
-"A notification memo has been sent to %s informing him/her you have\n"
-"read his/her memo."
-msgstr ""
-"Мемо-извещение было автоматически послано для %s, информирующее отправителя "
-"о том, что вы прочитали его/ее сообщение."
-
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr ""
-
-msgid "A vHost must be in the format of a valid hostname."
-msgstr ""
-
-#, fuzzy
-msgid "ADD expiry {nick|mask} [reason]"
-msgstr "BAN #channel nick [reason]"
-
-msgid "ADD oper type"
-msgstr ""
-
-#, fuzzy
-msgid "ADD target info"
-msgstr "GROUP главный_ник пароль"
-
-msgid "ADD text"
-msgstr ""
-
-#, fuzzy
-msgid "ADD [+expiry] mask limit reason"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-#, fuzzy
-msgid "ADD [nickname] channel [key]"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-#, fuzzy
-msgid "ADD [nickname] mask"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-#, fuzzy
-msgid "ADD [nickname] [fingerprint]"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "ADD [+expiry] mask reason"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-#, fuzzy
-msgid "ADD [+expiry] mask:reason"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-#, fuzzy
-msgid "ADD {NICK|CHAN|EMAIL|REGISTER} [+expiry] entry reason"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-msgid "ADDIP server.name ip"
-msgstr ""
-
-msgid "ADDSERVER server.name [zone.name]"
-msgstr ""
-
-msgid "ADDZONE zone.name"
-msgstr ""
-
-#, c-format
-msgid "AKICK ENFORCE for %s complete; %d users were affected."
-msgstr "AKICK ENFORCE на канале %s завершен, пользователей забанено: %d "
-
-#, fuzzy
-msgid "AKILL all users on a specific channel"
-msgstr " CHANKILL \"Прибить\" всех пользователей на указанном канале"
-
-msgid "AKILL list is empty."
-msgstr "Список AKILL'ов пуст."
-
-#, fuzzy
-msgid "AMSG kicker"
-msgstr "Цензор CapsLOCK......: %s"
-
-#, fuzzy
-msgid "Access"
-msgstr "Ваш текущий список доступа:"
-
-#, fuzzy
-msgid "Access denied."
-msgstr "Ваш текущий список доступа:"
-
-#, fuzzy, c-format
-msgid "Access for %s on %s:"
-msgstr "Уровень доступа для %s на канале %s изменен на %d."
-
-#, fuzzy, c-format
-msgid "Access level must be between %d and %d inclusive."
-msgstr "Уровень должен быть числом между %d и %d включительно."
-
-msgid "Access level must be non-zero."
-msgstr "Уровень доступа должен быть отличен от нуля."
-
-#, c-format
-msgid "Access level settings for channel %s:"
-msgstr "Установки списка доступа для канала %s:"
-
-#, c-format
-msgid "Access levels for %s reset to defaults."
-msgstr "Уровни доступа для канала %s сброшены на значения по-умолчанию."
-
-#, fuzzy, c-format
-msgid "Access list for %s:"
-msgstr "Список доступа для %s:"
-
-#, c-format
-msgid ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-msgstr ""
-"Access to this command requires the permission %s to be present in your "
-"opertype."
-
-#, c-format
-msgid ""
-"Account %s has already reached the maximum number of simultaneous logins "
-"(%u)."
-msgstr ""
-
-#, fuzzy
-msgid "Activate security features"
-msgstr " SECURE дополнительные возможности %s'а по безопасности"
-
-msgid "Activate the requested vHost for the given nick."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Activates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see the vhost instead of your real host/IP address."
-msgstr ""
-"Синтаксис: ON\n"
-"\n"
-"Активирует ваш виртуальный хост, при условии, конечно, что он у вас\n"
-"установлен. Сразу после активации, ваш реальный хост/IP-адрес будет\n"
-"заменен на виртуальный, и, соответственно, он и будет показан в\n"
-"/WHOIS-информации вашего ника."
-
-#, fuzzy
-msgid "Activates your assigned vhost"
-msgstr " ON Активирует назначенный вам виртуальный хост"
-
-msgid ""
-"Add or delete oper information for a given nick or channel.\n"
-"This will show to opers in the respective info command for\n"
-"the nick or channel."
-msgstr ""
-
-#, c-format
-msgid "Added IP %s to %s."
-msgstr ""
-
-#, c-format
-msgid "Added a forbid on %s of type %s to expire on %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Added info to %s."
-msgstr "Мемо-сообщение для %s успешно отправлено."
-
-#, fuzzy
-msgid "Added new logon news item."
-msgstr "Новость успешно добавлена, ее номер: #%d"
-
-#, fuzzy
-msgid "Added new oper news item."
-msgstr "Новость успешно добавлена, ее номер: #%d"
-
-#, fuzzy
-msgid "Added new random news item."
-msgstr "Новость успешно добавлена, ее номер: #%d"
-
-#, fuzzy, c-format
-msgid "Added server %s."
-msgstr "Uplink-сервер: %s"
-
-#, c-format
-msgid "Added zone %s."
-msgstr ""
-
-msgid ""
-"Adding, deleting, or clearing entry messages requires the\n"
-"SET permission."
-msgstr ""
-
-msgid ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
-msgstr ""
-"Additionally, Services Operators with the nickserv/confirm permission can\n"
-"replace passcode with a users nick to force validate them."
-
-#, c-format
-msgid ""
-"Additionally, if fantasy is enabled fantasy commands\n"
-"can be executed by prefixing the command name with\n"
-"one of the following characters: %s"
-msgstr ""
-
-#, c-format
-msgid "All O:lines of %s have been reset."
-msgstr "Все OLINE-записи на сервере %s восстановлены."
-
-#, fuzzy, c-format
-msgid "All akick entries from %s have been cloned to %s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s"
-
-#, fuzzy, c-format
-msgid "All available commands for %s:"
-msgstr "Справочная информация по %s отсутствует."
-
-#, fuzzy, c-format
-msgid "All badword entries from %s have been cloned to %s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s"
-
-#, fuzzy, c-format
-msgid "All level entries from %s have been cloned into %s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s"
-
-msgid "All logon news items deleted."
-msgstr "Список новостей полностью очищен."
-
-#, c-format
-msgid "All memos for channel %s have been deleted."
-msgstr "Все сообщения канала %s были удалены."
-
-#, c-format
-msgid "All modes cleared on %s."
-msgstr ""
-
-msgid ""
-"All new accounts must be validated by an administrator. Please wait for your "
-"registration to be confirmed."
-msgstr ""
-
-msgid "All of your memos have been deleted."
-msgstr "Все ваши вообщения были удалены."
-
-msgid "All oper news items deleted."
-msgstr "Список новостей для операторов полностью очищен."
-
-#, fuzzy, c-format
-msgid "All operators from %s have been removed."
-msgstr "Все OLINE-записи на сервере %s были удалены."
-
-msgid "All random news items deleted."
-msgstr "Список случайных новостей полностью очищен."
-
-#, fuzzy, c-format
-msgid "All settings from %s have been cloned to %s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s"
-
-#, fuzzy, c-format
-msgid "All user modes on %s have been synced."
-msgstr "Все OLINE-записи на сервере %s восстановлены."
-
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s"
-
-#, fuzzy, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "Все виртуальные хосты для ников группы %s установлены на %s@%s"
-
-msgid "Allowed to (de)halfop him/herself"
-msgstr ""
-
-msgid "Allowed to (de)halfop users"
-msgstr ""
-
-msgid "Allowed to (de)op him/herself"
-msgstr ""
-
-msgid "Allowed to (de)op users"
-msgstr ""
-
-msgid "Allowed to (de)owner him/herself"
-msgstr ""
-
-msgid "Allowed to (de)owner users"
-msgstr ""
-
-msgid "Allowed to (de)protect him/herself"
-msgstr ""
-
-msgid "Allowed to (de)protect users"
-msgstr ""
-
-msgid "Allowed to (de)voice him/herself"
-msgstr ""
-
-msgid "Allowed to (de)voice users"
-msgstr ""
-
-msgid "Allowed to assign/unassign a bot"
-msgstr ""
-
-msgid "Allowed to ban users"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to change channel topics"
-msgstr "%s принудительно изменил ваши пользовательские режимы."
-
-msgid "Allowed to get full INFO output"
-msgstr ""
-
-msgid "Allowed to issue commands restricted to channel founders"
-msgstr ""
-
-msgid "Allowed to modify channel badwords list"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to modify the access list"
-msgstr "Ник %s успешно удален из списка доступа канала %s."
-
-msgid "Allowed to read channel memos"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to set channel settings"
-msgstr "* Запрет на регистрацию каналов."
-
-msgid "Allowed to unban users"
-msgstr ""
-
-msgid "Allowed to use GETKEY command"
-msgstr ""
-
-msgid "Allowed to use SAY and ACT commands"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to use fantasy commands"
-msgstr " PEACE активирование режима \"спокойствия\" на канале"
-
-#, fuzzy
-msgid "Allowed to use the AKICK command"
-msgstr "You cannot use this command."
-
-msgid "Allowed to use the INVITE command"
-msgstr ""
-
-#, fuzzy
-msgid "Allowed to use the KICK command"
-msgstr "You cannot use this command."
-
-#, fuzzy
-msgid "Allowed to use the MODE command"
-msgstr "You cannot use this command."
-
-#, fuzzy
-msgid "Allowed to view the access list"
-msgstr "Ник %s успешно удален из списка доступа канала %s."
-
-#, fuzzy, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
-msgstr ""
-"Синтаксис: GLOBAL сообщение\n"
-"\n"
-"Позволяет Администраторам сервисов отправлять глобальные сообщения\n"
-"всем пользователям сети. В качестве ника отправителя будет указан\n"
-"%s."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to change modes for any channel.\n"
-"Parameters are the same as for the standard /MODE command.\n"
-"Alternatively, CLEAR may be given to clear all modes on the channel.\n"
-"If CLEAR ALL is given then all modes, including user status, is removed."
-msgstr ""
-"Синтаксис: MODE #канал режимы\n"
-"\n"
-"Позволяет Операторам сервисов изменять режимы на каком-либо канале.\n"
-"В качестве второго параметра команды, вы должны указать режимы в\n"
-"том же формате, в котором указываете при ручной установке, с помощью\n"
-"команды /MODE."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to change modes for any user.\n"
-"Parameters are the same as for the standard /MODE command."
-msgstr ""
-"Синтаксис: MODE #канал режимы\n"
-"\n"
-"Позволяет Операторам сервисов изменять режимы на каком-либо канале.\n"
-"В качестве второго параметра команды, вы должны указать режимы в\n"
-"том же формате, в котором указываете при ручной установке, с помощью\n"
-"команды /MODE."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to create, modify, and delete\n"
-"bots that users will be able to use on their own\n"
-"channels.\n"
-" \n"
-"BOT ADD adds a bot with the given nickname, username,\n"
-"hostname and realname. Since no integrity checks are done\n"
-"for these settings, be really careful.\n"
-" \n"
-"BOT CHANGE allows you to change the nickname, username, hostname\n"
-"or realname of a bot without deleting it (and\n"
-"all the data associated with it).\n"
-" \n"
-"BOT DEL removes the given bot from the bot list.\n"
-" \n"
-"Note: You cannot create a bot with a nick that is\n"
-"currently registered. If an unregistered user is currently\n"
-"using the nick, they will be killed."
-msgstr ""
-"Синтаксис: BOT ADD ник идент хост реальное_имя\n"
-" BOT CHANGE старый ник новый_ник [идент [хост [реальное_имя]]]\n"
-" BOT DEL ник\n"
-"\n"
-"Позволяет Администраторам сервисов создавать, изменять или удалять\n"
-"ботов, которые в дальнейшем могут быть использованы пользователями\n"
-"сети на своих каналах.\n"
-"\n"
-"Команда BOT ADD добавляет бота с указанным ником, идентом, хостом\n"
-"и реальным именем. Так как корректность этих значений не проверяется,\n"
-"будьте крайне внимательны при добавлении/изменении хаарктеристик бота.\n"
-"\n"
-"Команда BOT CHANGE позволяет изменить ник, идент, хост или реальное\n"
-"имя бота без необходимости его удаления.\n"
-"\n"
-"Команда BOT DEL удаляет указанного бота из списка ботов.\n"
-"\n"
-"Примечание: вы не можете создать бота с ником, который уже кем-то\n"
-"зарегистрирован. Если же вы создаете бота с незарегистрированным ником,\n"
-"любой, кто использует этот ник на момент создания бота - будет тут\n"
-"же отключен от сети."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Синтаксис: OLINE ник оперфлаги\n"
-"\n"
-"Позволяет Администраторам сервисов установить флаги IRC-Оператора\n"
-"любому посетителю сети. Перед флагами должен присутствовать префикс\n"
-"\"+\" - для установки, или \"-\" - соответственно для снятия.\n"
-"Чтобы удалить все флаги, используйте \"-\" вместо какого-либо флага.\n"
-"\n"
-"Для использования этой команды необходимы права Супер-Администратора."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
-"for a certain time or until the next restart. The default\n"
-"time format is seconds. You can specify it by using units.\n"
-"Valid units are: s for seconds, m for minutes,\n"
-"h for hours and d for days.\n"
-"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
-"When adding a mask, it should be in the format nick!user@host,\n"
-"everything else will be considered a nick. Wildcards are permitted.\n"
-" \n"
-"Ignores will not be enforced on IRC Operators."
-msgstr ""
-"Синтаксис: IGNORE {ADD|DEL|LIST|CLEAR} [время] [ник|маска]\n"
-"\n"
-"Позволяет Администраторам сервисов управлять списком игнорируемых\n"
-"сервисами пользователей.\n"
-"По-умолчанию, параметр [время] является секундами. Однако, вы можете\n"
-"указать и иные единицы измерения, используя: s для секунд, m для\n"
-"минут, h для часов и d для дней. Комбинации этих единиц измерения\n"
-"недопустимы. Установка времени игнора в 0 сделает его постоянным.\n"
-"В качестве последнего значения вы должны указать валидный ник или\n"
-"маску вида ник!идент@хост или идент@хост. Любые другие значения будут\n"
-"расцениваться в качестве ника.\n"
-"Пользователи со статусом IRC-оператора игнорироваться сервисами не\n"
-"будут, даже если они присутствуют в списке игнора."
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
-"will issue a KILL for that user and, on supported server\n"
-"types, will instruct all servers to add a ban for the mask\n"
-"which the user matched.\n"
-" \n"
-"AKILL ADD adds the given mask to the AKILL\n"
-"list for the given reason, which must be given.\n"
-"Mask should be in the format of nick!user@host#real name,\n"
-"though all that is required is user@host. If a real name is specified,\n"
-"the reason must be prepended with a :.\n"
-"expiry is specified as an integer followed by one of d\n"
-"(days), h (hours), or m (minutes). Combinations (such as\n"
-"1h30m) are not permitted. If a unit specifier is not\n"
-"included, the default is days (so +30 by itself means 30\n"
-"days). To add an AKILL which does not expire, use +0. If the\n"
-"usermask to be added starts with a +, an expiry time must\n"
-"be given, even if it is the same as the default. The\n"
-"current AKILL default expiry time can be found with the\n"
-"STATS AKILL command."
-msgstr ""
-"Синтаксис: AKILL ADD [+срок_истечения] маска причина\n"
-" AKILL DEL {маска | номер_записи | список_записей}\n"
-" AKILL LIST [маска | список_записей]\n"
-" AKILL VIEW [маска | список_записей]\n"
-" AKILL CLEAR\n"
-"\n"
-"Позволяет Операторам сервисов управлять списком сервисных AKILL'ов.\n"
-"Любой пользователь, подпадающий под маску AKILL'а, будет немедленно\n"
-"отключен от сети посредством сервисного KILL'а с указанной причиной,\n"
-"и не важно, на каком сервере он сидит или к какому подключается.\n"
-"Помимо этого, если IRCd вашей сети это поддерживает, сервисы \n"
-"установят KLINE/GLINE на всех серверах вашей сети, в качестве маски\n"
-"бана будет использована соответствующая запись AKILL'а.\n"
-"\n"
-"Команда AKILL ADD добавляет маску вида идент@хост/ip с указанной\n"
-"причиной в список AKILL'ов (наличие причины - обязательно).\n"
-"Значение срока истечения - это целое число, которое может быть\n"
-"одним из: d (дней), h (часов), или m (минут). Такие сочетания\n"
-"как 1h30m - недопустимы. Если единица измерения не указана, то\n"
-"по-умолчанию, она будет принята за \"d\" - \"дни\" (таким образом,\n"
-"+30 будет означать 30 дней). Чтобы добавить постоянный AKILL,\n"
-"используйте время истечения равным +0. Помните, что если в качестве\n"
-"первого символа второго параметра указан знак \"+\" - вы должны\n"
-"обозначить сроки истечения записи, даже если это будет значение\n"
-"по-умочанию.\n"
-"Текущее время истечения AKILL'а по-умолчанию, можно узнать с помощью\n"
-"команды STATS AKILL.\n"
-"\n"
-"Команда AKILL DEL удаляет указанную маску из списка AKILL'ов.\n"
-"В качестве параметра вы можете указать не только маску AKILL'а, но\n"
-"и конкретный номер записи или список записей (см. примеры\n"
-"использования команды LIST ниже).\n"
-"\n"
-"Команда AKILL LIST показывает текущий список AKILL'ов.\n"
-"В качестве дополнительного параметра, вы можете указать символьную\n"
-"маску, что позволит вам получить список с конкретными записями,\n"
-"попадающими под эту маску, или же, вы можете указать список записей.\n"
-"Например:\n"
-"\n"
-" AKILL LIST 2-5,7-9\n"
-" отобразит все записи с 2-ой по 5-ю и с 7-ой по 9-ю.\n"
-"\n"
-"AKILL VIEW более подробная версия AKILL LIST, она покажет вам\n"
-"кто добавил AKILL, время установки AKILL'а, когда он истекает, ну\n"
-"и, конечно же, маску вида идент@хост/ip и причину AKILL'а.\n"
-"\n"
-"AKILL CLEAR позволяет полностью очистить список AKILL'ов."
-
-msgid ""
-"Allows Services Operators to manipulate the SNLINE list. If\n"
-"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
-"session."
-msgstr ""
-
-msgid ""
-"Allows Services Operators to manipulate the SQLINE list. If\n"
-"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow it to pursue his IRC\n"
-"session.\n"
-"If the first character of the mask is #, services will\n"
-"prevent the use of matching channels. If the mask is a\n"
-"regular expression, the expression will be matched against\n"
-"channels too."
-msgstr ""
-
-msgid ""
-"Allows Services Operators to manipulate the list of hosts that\n"
-"have specific session limits - allowing certain machines,\n"
-"such as shell servers, to carry more than the default number\n"
-"of clients at a time. Once a host reaches its session limit,\n"
-"all clients attempting to connect from that host will be\n"
-"killed. Before the user is killed, they are notified, of a\n"
-"source of help regarding session limiting. The content of\n"
-"this notice is a config setting."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Allows Services Operators to view the session list.\n"
-" \n"
-"SESSION LIST lists hosts with at least threshold sessions.\n"
-"The threshold must be a number greater than 1. This is to\n"
-"prevent accidental listing of the large number of single\n"
-"session hosts.\n"
-" \n"
-"SESSION VIEW displays detailed information about a specific\n"
-"host - including the current session count and session limit.\n"
-"The host value may not include wildcards.\n"
-" \n"
-"See the EXCEPTION help for more information about session\n"
-"limiting and how to set session limits specific to certain\n"
-"hosts and groups thereof."
-msgstr ""
-"Синтаксис: SESSION LIST порог\n"
-" SESSION VIEW хост\n"
-"\n"
-"Позволяет Администраторам сервисов просматривать список сессий.\n"
-"\n"
-"Команда SESSION LIST позволяет получить список хостов с количеством\n"
-"сессий большим или равным порогу. Значение порога должно быть\n"
-"целым числом и больше 1. Это позволит избежать слишком большого списка\n"
-"хостов с единичным количеством сессий.\n"
-"\n"
-"Команда SESSION VIEW покажет детальную информацию об указанном\n"
-"хосте - текущее количестов сессий и ограничение для указанного хоста.\n"
-"Помните, что указанный хост не должен включать в себя подстановочные\n"
-"символы вида '*' и '?'.\n"
-"\n"
-"См. EXCEPTION HELP для более подробной информации о лимитировании\n"
-"сессий и как установить отдельный лимит сессий для определенного\n"
-"хоста или группы хостов."
-
-msgid ""
-"Allows manipulating the topic of the specified channel.\n"
-"The SET command changes the topic of the channel to the given topic\n"
-"or unsets the topic if no topic is given. The APPEND command appends\n"
-"the given topic to the existing topic.\n"
-" \n"
-"LOCK and UNLOCK may be used to enable and disable topic lock. When\n"
-"topic lock is set, the channel topic will be unchangeable by users who do "
-"not have\n"
-"the TOPIC privilege."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Allows staff to kick a user from any channel.\n"
-"Parameters are the same as for the standard /KICK\n"
-"command. The kick message will have the nickname of the\n"
-"IRCop sending the KICK command prepended; for example:\n"
-" \n"
-"*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"
-msgstr ""
-"Синтаксис: KICK #канал ник причина\n"
-"\n"
-"Позволяет Операторам сервисов выкинуть какого-либо пользователя с\n"
-"указанного канала сети.\n"
-"Параметры данной команды аналогичны параметрам стандартной команды\n"
-"/KICK. Причина кика будет включать в себя ник Оператора сервисов,\n"
-"который использовал данную команду, например:\n"
-"\n"
-"*** SpamMan was kicked by %s (Alcan (Flood))"
-
-#, fuzzy
-msgid ""
-"Allows the channel founder to set various channel options\n"
-"and other information.\n"
-" \n"
-"Available options:"
-msgstr ""
-"Синтаксис: SET #канал опция параметр\n"
-"\n"
-"Позволяет владельцу канала менять различные настройки канала.\n"
-"Доступные опции:"
-
-msgid ""
-"Allows you to change and view Services Operators.\n"
-"Note that operators removed by this command but are still set in\n"
-"the configuration file are not permanently affected by this."
-msgstr ""
-
-msgid ""
-"Allows you to change and view configuration settings.\n"
-"Settings changed by this command are temporary and will not be reflected\n"
-"back into the configuration file, and will be lost if Anope is shut down,\n"
-"restarted, or the configuration is reloaded.\n"
-" \n"
-"Example:\n"
-" MODIFY nickserv forcemail no"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
-"else they'll use notices."
-msgstr ""
-"Синтаксис: SASET ник MSG {ON | OFF}\n"
-"\n"
-"Позволяет вам выбрать способ общения сервисов с указанным ником.\n"
-"Укажите ON, что бы активировать режим приватных сообщений - в\n"
-"этом случае все сообщения от сервисов будут приходить владельцу в\n"
-"приват. Параметр OFF заставит сервисы использовать режим\n"
-"уведомлений (notice, нотисы).\n"
-"Примечание: настройка данной опции может быть заблокирована."
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
-"use notices."
-msgstr ""
-"Синтаксис: SET MSG {ON | OFF}\n"
-"\n"
-"Позволяет вам выбрать способ общения сервисов с вами. Укажите ON,\n"
-"что бы активировать режим приватных сообщений - в этом случае все\n"
-"сообщения от сервисов будут приходить вам в приват. Параметр OFF\n"
-"заставит сервисы использовать режим уведомлений (notice, нотисы).\n"
-"Примечание: настройка данной опции может быть заблокирована."
-
-msgid ""
-"Allows you to ignore users by nick or host from memoing\n"
-"you or a channel. If someone on the memo ignore list tries\n"
-"to memo you or a channel, they will not be told that you have\n"
-"them ignored."
-msgstr ""
-
-msgid ""
-"Allows you to kill a user from the network.\n"
-"Parameters are the same as for the standard /KILL\n"
-"command."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), the services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-msgstr ""
-"Синтаксис: SASET ник HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Данная опция позволяет вам скрыть часть информации об указанном\n"
-"нике, которая может запрошена у %s с помощью команды INFO\n"
-"\n"
-"В качестве второго параметра вы должны указать что именно будет\n"
-"скрыто:\n"
-"QUIT - для скрытия последнего quit-сообщения владельца\n"
-"EMAIL - для скрытия ассоциированного email-адреса владельца\n"
-"STATUS - для скрытия уровня доступа к сервисам\n"
-"USERMASK - для скрытия последней хостмаски владельца (идент@хост)\n"
-"\n"
-"В качестве третьего параметра вы должны указать либо ON либо OFF.\n"
-"Первый активирует скрытие, второй, соответственно, деактивирует."
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to prevent certain pieces of information from\n"
-"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
-"user@host mask (USERMASK), your services access status\n"
-"(STATUS) and last quit message (QUIT).\n"
-"The second parameter specifies whether the information should\n"
-"be displayed (OFF) or hidden (ON)."
-msgstr ""
-"Синтаксис: SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\n"
-"\n"
-"Данная опция позволяет вам скрыть часть информации о вашем нике,\n"
-"которая может запрошена у %s с помощью команды INFO\n"
-"\n"
-"В качестве второго параметра вы должны указать что именно будет\n"
-"скрыто:\n"
-"USERMASK - для скрытия вашей последней хостмаски вида идент@хост\n"
-" STATUS - для скрытия вашего уровня доступа к сервисам\n"
-" EMAIL - для скрытия ассоциированного email-адреса.\n"
-" QUIT - для скрытия вашего последнего quit-сообщения\n"
-"\n"
-"В качестве третьего параметра вы должны указать либо ON либо OFF.\n"
-"Первый активирует скрытие, второй, соответственно, деактивирует."
-
-#, fuzzy, c-format
-msgid "Allows you to see %s information about a channel or a bot"
-msgstr "INFO Запрос информации о боте и его настройках на канале"
-
-#, fuzzy, c-format
-msgid ""
-"Allows you to see %s information about a channel or a bot.\n"
-"If the parameter is a channel, then you'll get information\n"
-"such as enabled kickers. If the parameter is a nick,\n"
-"you'll get information about a bot, such as creation\n"
-"time or number of channels it is on."
-msgstr ""
-"Синтаксис: INFO {#канал | ник}\n"
-"\n"
-"Позволяет просмотреть различную информацию о самом боте (ник, идент,\n"
-"хост, дату создания, количество обслуживаемых каналов), или о его\n"
-"настройках на конкретном #канале (условия киков и установленные\n"
-"опции).\n"
-"Примечание: данные будут посланы от лица %s"
-
-msgid ""
-"Alternative methods of modifying channel access lists are\n"
-"available."
-msgstr ""
-
-#, fuzzy
-msgid "Approve the requested vHost of a user"
-msgstr " DEL Удаление виртуального хоста"
-
-#, fuzzy
-msgid "As a Services Operator, you may drop any nick."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "Assigns a bot to a channel"
-msgstr "ASSIGN Установка бота на указанный канал"
-
-#, fuzzy
-msgid ""
-"Assigns the specified bot to a channel. You\n"
-"can then configure the bot for the channel so it fits\n"
-"your needs."
-msgstr ""
-"Синтаксис: ASSIGN #канал ник\n"
-"\n"
-"Позволяет установить указанного бота (ник) на указанный канал. Сразу\n"
-"же после установки, вы сможете сконфигурировать опции бота по своему\n"
-"усмотрению."
-
-#, fuzzy
-msgid "Associate a URL with the channel"
-msgstr "ASSIGN Установка бота на указанный канал"
-
-msgid "Associate a URL with this account"
-msgstr ""
-
-#, fuzzy
-msgid "Associate a URL with your account"
-msgstr " GREET установка приветственного сообщения"
-
-#, fuzzy
-msgid "Associate a greet message with your nickname"
-msgstr " GREET установка приветственного сообщения"
-
-#, fuzzy
-msgid "Associate an E-mail address with the channel"
-msgstr " EMAIL установка email-адреса на ник"
-
-#, fuzzy
-msgid "Associate an E-mail address with your nickname"
-msgstr " EMAIL установка email-адреса на ник"
-
-#, fuzzy
-msgid "Associate oper info with a nick or channel"
-msgstr "ASSIGN Установка бота на указанный канал"
-
-#, fuzzy
-msgid "Associates the given E-mail address with the nickname."
-msgstr " EMAIL установка email-адреса на ник"
-
-#, fuzzy
-msgid ""
-"Associates the given E-mail address with your nickname.\n"
-"This address will be displayed whenever someone requests\n"
-"information on the nickname with the INFO command."
-msgstr ""
-"Синтаксис: SET EMAIL адрес@email\n"
-"\n"
-"Ассоциирует email-адрес с вашим ником. Данный email будет показан\n"
-"в информации о вашем нике, предоставляемой по команде INFO."
-
-msgid "Auto-op"
-msgstr "Автостатус"
-
-#, c-format
-msgid "Autokick list for %s:"
-msgstr "Список автокиков канала %s:"
-
-msgid "Automatic channel operator status upon join"
-msgstr ""
-
-msgid "Automatic halfop upon join"
-msgstr ""
-
-msgid "Automatic owner upon join"
-msgstr ""
-
-msgid "Automatic protect upon join"
-msgstr ""
-
-msgid "Automatic voice on join"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Available commands for %s:"
-msgstr "Справочная информация по %s отсутствует."
-
-#, fuzzy
-msgid "Available opertypes:"
-msgstr "Справочная информация по %s отсутствует."
-
-#, c-format
-msgid "Available privileges for %s:"
-msgstr ""
-
-msgid "BANS enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "Bad words kicker"
-msgstr "Цензор плохих слов...: %s"
-
-#, fuzzy, c-format
-msgid "Bad words list for %s:"
-msgstr "Список доступа для %s:"
-
-msgid "Bad words list is now empty."
-msgstr "Список \"плохих\" слов полностью очищен."
-
-msgid "Ban expiry may not be longer than 1 day."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Ban on %s expires in %s."
-msgstr "Бот с ником %s уже существует."
-
-msgid "Ban type"
-msgstr ""
-
-#, c-format
-msgid "Ban type for channel %s is now #%d."
-msgstr "Шаблон банмаски на канале %s изменен на #%d."
-
-#, fuzzy
-msgid "Bans a given nick or mask on a channel"
-msgstr " BAN Установка бана на канале"
-
-#, fuzzy
-msgid ""
-"Bans a given nick or mask on a channel. An optional expiry may\n"
-"be given to cause services to remove the ban after a set amount\n"
-"of time.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders may ban masks."
-msgstr ""
-"Синтаксис: BAN #канал ник [причина]\n"
-"\n"
-"Банит указанного пользователя на указанном канале.\n"
-"\n"
-"По-умолчанию, данная команда может быть использована AOP'ами или\n"
-"лицами с уровнем доступа 5 и выше."
-
-#, fuzzy, c-format
-msgid "Bans enforced on %s."
-msgstr "%s не уведомляется о новых собщениях."
-
-#, fuzzy
-msgid "Bolds kicker"
-msgstr "Цензор жирных букв...: %s"
-
-#, c-format
-msgid "Bot %s already exists."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy, c-format
-msgid "Bot %s does not exist."
-msgstr "Бот с ником %s уже существует."
-
-#, c-format
-msgid "Bot %s has been assigned to %s."
-msgstr "Бот %s успешно назначен на канал %s."
-
-#, fuzzy, c-format
-msgid "Bot %s has been changed to %s!%s@%s (%s)."
-msgstr "Данные о боте %s были изменены на %s!%s@%s (%s)"
-
-#, c-format
-msgid "Bot %s has been deleted."
-msgstr "Бот под ником %s успешно удален."
-
-#, c-format
-msgid "Bot %s is already assigned to channel %s."
-msgstr "Бот %s уже назначен на канал %s."
-
-#, c-format
-msgid "Bot will kick ops on channel %s."
-msgstr "С этого момента, бот будет кикать операторов канала %s за нарушения."
-
-#, c-format
-msgid "Bot will kick voices on channel %s."
-msgstr "С этого момента бот будет кикать войсов канала %s за нарушения."
-
-#, c-format
-msgid "Bot won't kick ops on channel %s."
-msgstr ""
-"Теперь, операторы канала %s будут исключены из условий кика за нарушения."
-
-#, c-format
-msgid "Bot won't kick voices on channel %s."
-msgstr "Теперь, войсы канала %s будут исключены из условий кика за нарушения."
-
-#, fuzzy, c-format
-msgid "Bot %s is not changeable."
-msgstr "Режим без-бота для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Bot %s is not deletable."
-msgstr "Бот под ником %s успешно удален."
-
-#, c-format
-msgid "Bot bans will automatically expire after %s."
-msgstr ""
-
-#, fuzzy
-msgid "Bot bans will no longer automatically expire."
-msgstr "Режим автостатуса для %s отключен"
-
-#, fuzzy, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Хост бота не должен превышать %d символов."
-
-#, fuzzy
-msgid "Bot hosts may only contain valid host characters."
-msgstr "Указанный для бота хост содержит недопустимые символы."
-
-#, fuzzy, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Идент бота не должен превышать %d символов."
-
-#, fuzzy
-msgid "Bot idents may only contain valid ident characters."
-msgstr "Указанный для бота идент содержит недопустимые символы."
-
-#, fuzzy, c-format
-msgid "Bot is not on channel %s."
-msgstr "С этого момента, бот будет кикать операторов канала %s за нарушения."
-
-msgid "Bot list:"
-msgstr "Список ботов:"
-
-msgid "Bot nick"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Идент бота не должен превышать %d символов."
-
-#, fuzzy
-msgid "Bot nicks may only contain valid nick characters."
-msgstr "Указанный для бота ник содержит недопустимые символы."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for %s, and will place a ban\n"
-"after %d kicks for the same user."
-msgstr ""
-"Bot will now kick italics, and will place a ban after %d\n"
-"kicks for the same user."
-
-#, fuzzy, c-format
-msgid "Bot will now kick for %s."
-msgstr "Режим кика за использование жирного шрифта активирован."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message), and will\n"
-"place a ban after %d kicks for the same user."
-msgstr ""
-"Режим кика за чрезмерное использование CapsLOCK активирован. Бот\n"
-"будет кикать посетителя, если его фраза содержит не менее %d больших\n"
-"символов и они составляют не менее %d%% от общего кол-ва символов.\n"
-"Дополнительно, после %d предупреждающих киков, бот забанит нарушителя."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for caps (they must constitute at least\n"
-"%d characters and %d%% of the entire message)."
-msgstr ""
-"Режим кика за чрезмерное использование CapsLOCK активирован. Бот\n"
-"будет кикать посетителя, если его фраза содержит не менее %d больших\n"
-"символов и они составляют не менее %d%% от общего кол-ва символов."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for flood (%d lines in %d seconds\n"
-"and will place a ban after %d kicks for the same user."
-msgstr ""
-"Режим кика за флуд активирован (условие: %d линий за %d секунд).\n"
-"Дополнительно, после %d предупреждающих киков, бот забанит нарушителя."
-
-#, fuzzy, c-format
-msgid "Bot will now kick for flood (%d lines in %d seconds)."
-msgstr "Режим кика за флуд активирован (условие: %d линий за %d секунд)."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time), and will place a ban after %d\n"
-"kicks for the same user."
-msgstr ""
-"Режим кика за чрезмерные повторы активирован.\n"
-"Бот будет кикать пользователя после %d повторов подряд и ставить\n"
-"бан после %d предупреждающих киков."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d time)."
-msgstr ""
-"Режим кика за чрезмерные повторы активирован. Бот будет кикать\n"
-"посетителя если он повторит одну и ту же фразу %d раз подряд."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times), and will place a ban after %d\n"
-"kicks for the same user."
-msgstr ""
-"Режим кика за чрезмерные повторы активирован.\n"
-"Бот будет кикать пользователя после %d повторов подряд и ставить\n"
-"бан после %d предупреждающих киков."
-
-#, fuzzy, c-format
-msgid ""
-"Bot will now kick for repeats (users that repeat the\n"
-"same message %d times)."
-msgstr ""
-"Режим кика за чрезмерные повторы активирован. Бот будет кикать\n"
-"посетителя если он повторит одну и ту же фразу %d раз подряд."
-
-#, fuzzy, c-format
-msgid "Bot won't kick for %s anymore."
-msgstr "Режим кика за чрезмерное использование CapsLOCK отключен."
-
-#, fuzzy
-msgid "Bot won't kick for caps anymore."
-msgstr "Режим кика за чрезмерное использование CapsLOCK отключен."
-
-#, fuzzy
-msgid "Bot won't kick for flood anymore."
-msgstr "Режим кика за флуд отключен."
-
-#, fuzzy
-msgid "Bot won't kick for repeats anymore."
-msgstr "Режим кика за чрезмерные повторы отключен."
-
-msgid "By"
-msgstr ""
-
-msgid "CLEAR target"
-msgstr ""
-
-msgid "CLEAR time"
-msgstr ""
-
-#, fuzzy
-msgid "Cancel the last memo you sent"
-msgstr " CANCEL Отмена последнего отправленного вами мемо-сообщения"
-
-#, fuzzy
-msgid "Cancel the registration of a channel"
-msgstr " DROP Удаление канала из базы данных сервисов"
-
-#, fuzzy
-msgid "Cancel the registration of a nickname"
-msgstr " DROP Отмена регистрации ника (удаление)"
-
-#, fuzzy
-msgid ""
-"Cancels the last memo you sent to the given nick or channel,\n"
-"provided it has not been read at the time you use the command."
-msgstr ""
-"Синтаксис: CANCEL {ник | #канал}\n"
-"\n"
-"Отменяет последнее сообщение, отправленное вами указанному нику\n"
-"или каналу, тем самым предохраняя его от прочтения адресатом."
-
-#, fuzzy, c-format
-msgid "Cannot clone channel %s to itself!"
-msgstr "С этого момента, бот будет кикать операторов канала %s за нарушения."
-
-msgid "Cannot send mail now; please retry a little later."
-msgstr "На данный момент отправка email невозможна, попробуйте позже."
-
-#, fuzzy
-msgid "Caps kicker"
-msgstr "Цензор CapsLOCK......: %s"
-
-#, fuzzy
-msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
-"not saved. This command should not be used unless\n"
-"damage to the in-memory copies of the databases is feared\n"
-"and they should not be saved."
-msgstr ""
-"Синтаксис: QUIT\n"
-"\n"
-"Заставляет сервисы немедленно завершить свою работу. Все данные,\n"
-"накопленные с момента последнего обновления баз данных, сохранены\n"
-"не будут! Эта команда должна использоваться только в тех случаях,\n"
-"когда текущая загруженная в память база данных содержит какие-либо\n"
-"ошибки, сохранения которых нужно избежать.\n"
-"Для нормального завершения работы сервисов используйте команду SHUTDOWN."
-
-#, fuzzy
-msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
-"session limitation, etc.)."
-msgstr ""
-"Синтаксис: RELOAD\n"
-"\n"
-"Заставляет сервисы перечитать конфигурационный файл services.conf.\n"
-"Примечание: активация некоторых новых/измененных директив конфига\n"
-"требует полного перезапуска сервисов (например: изменение ников\n"
-"сервисов, активация лимитирования сессий, и т.д.)"
-
-#, fuzzy
-msgid ""
-"Causes Services to save all databases and then restart\n"
-"(i.e. exit and immediately re-run the executable)."
-msgstr ""
-"Синтаксис: RESTART\n"
-"\n"
-"Заставляет сервисы сохранить все базы данных и тут же перезапуститься."
-
-#, fuzzy
-msgid "Causes Services to save all databases and then shut down."
-msgstr ""
-"Синтаксис: SHUTDOWN\n"
-"\n"
-"Заставляет сервисы сохранить все базы данных и завершить свою работу."
-
-#, fuzzy
-msgid ""
-"Causes Services to update all database files as soon as you\n"
-"send the command."
-msgstr ""
-"Синтаксис: UPDATE\n"
-"\n"
-"Заставляет сервисы немедленно сохранить все базы данных на диск."
-
-#, fuzzy, c-format
-msgid "Certificate list for %s:"
-msgstr "Список доступа для %s:"
-
-msgid "ChanServ is required to enable persist on this network."
-msgstr ""
-
-#, fuzzy
-msgid "Change channel modes"
-msgstr "%s принудительно изменил ваши пользовательские режимы."
-
-#, fuzzy
-msgid "Change the communication method of Services"
-msgstr " MSG выбор метода общения сервисов с вами"
-
-#, fuzzy
-msgid "Change user modes"
-msgstr "%s принудительно изменил ваши пользовательские режимы."
-
-#, fuzzy, c-format
-msgid "Changed usermodes of %s to %s."
-msgstr "Режимы пользователя %s изменены."
-
-#, fuzzy
-msgid ""
-"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
-msgstr ""
-"Синтаксис: SET DISPLAY новый_ник\n"
-"\n"
-"Позволяет переназначить главный ник группы. Именно этот ник будет\n"
-"отображаться в списке доступа каналов, где вы прописаны.\n"
-"Примечание: новый главный ник должен состоять в вашей группе ников."
-
-#, fuzzy
-msgid ""
-"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
-msgstr ""
-"Синтаксис: SET DISPLAY новый_ник\n"
-"\n"
-"Позволяет переназначить главный ник группы. Именно этот ник будет\n"
-"отображаться в списке доступа каналов, где вы прописаны.\n"
-"Примечание: новый главный ник должен состоять в вашей группе ников."
-
-#, fuzzy
-msgid ""
-"Changes the founder of a channel. The new nickname must\n"
-"be a registered one."
-msgstr ""
-"Синтаксис: %s #канал FOUNDER ник\n"
-"\n"
-"Позволяет передать права на владение каналом другому пользователю.\n"
-"Ник нового владельца канала должен быть зарегистрированным."
-
-#, fuzzy
-msgid ""
-"Changes the language Services uses when sending messages to\n"
-"the given user (for example, when responding to a command they send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
-msgstr ""
-"Синтаксис: SET LANGUAGE номер\n"
-"\n"
-"Позволяет выбрать язык, на котором сервисы будут посылать вам\n"
-"различные сообщения. Например, текст справочной системы, который вы\n"
-"сейчас и читаете.\n"
-"В качестве номера, вы должны указать конкретный номер языка из\n"
-"списка поддерживаемых языков:"
-
-#, fuzzy
-msgid ""
-"Changes the language Services uses when sending messages to\n"
-"you (for example, when responding to a command you send).\n"
-"language should be chosen from the following list of\n"
-"supported languages:"
-msgstr ""
-"Синтаксис: SET LANGUAGE номер\n"
-"\n"
-"Позволяет выбрать язык, на котором сервисы будут посылать вам\n"
-"различные сообщения. Например, текст справочной системы, который вы\n"
-"сейчас и читаете.\n"
-"В качестве номера, вы должны указать конкретный номер языка из\n"
-"списка поддерживаемых языков:"
-
-#, fuzzy
-msgid "Changes the password used to identify as the nick's owner."
-msgstr ""
-"Синтаксис: SET PASSWORD новый_пароль\n"
-"\n"
-"Позволяет изменить пароль ника, используемый для идентификации к\n"
-"нему в качестве полноправного владельца."
-
-#, fuzzy
-msgid ""
-"Changes the password used to identify you as the nick's\n"
-"owner."
-msgstr ""
-"Синтаксис: SET PASSWORD новый_пароль\n"
-"\n"
-"Позволяет изменить пароль ника, используемый для идентификации к\n"
-"нему в качестве полноправного владельца."
-
-#, fuzzy
-msgid ""
-"Changes the successor of a channel. If the founder's\n"
-"nickname expires or is dropped while the channel is still\n"
-"registered, the successor will become the new founder of the\n"
-"channel. The successor's nickname must be a registered one.\n"
-"If there's no successor set, then the first nickname on the\n"
-"access list (with the highest access, if applicable) will\n"
-"become the new founder, but if the access list is empty, the\n"
-"channel will be dropped."
-msgstr ""
-"Синтаксис: %s #канал SUCCESSOR ник\n"
-"\n"
-"Позволяет назначить наследника канала. Если ник текущего владельца\n"
-"канала будет удален ввиду истечения срока регистрации или по каким\n"
-"иным причинам, назначенный наследник станет новым владельцем канала.\n"
-"Так же, стоит заметить, что если наследник уже зарегистрировал\n"
-"чересчур много каналов (более %d), он не получит прав на владение\n"
-"каналом и тот будет удален. Ко всему прочему, ник наследника канала\n"
-"должен быть зарегистрированным ником."
-
-#, fuzzy
-msgid "Channel"
-msgstr "DROP #канал"
-
-#, fuzzy, c-format
-msgid "Channel %s doesn't exist."
-msgstr "Channel %s is now persistant."
-
-#, c-format
-msgid "Channel %s has been dropped."
-msgstr "Канал %s удален из базы данных."
-
-#, fuzzy, c-format
-msgid "Channel %s has no key."
-msgstr "Канал %s не имеет ключа (no key)."
-
-#, c-format
-msgid "Channel %s is already registered!"
-msgstr "Канал %s уже зарегистрирован!"
-
-#, fuzzy, c-format
-msgid "Channel %s is forbidden by %s: %s"
-msgstr "Этот канал был зарегистрирован с помощью %s"
-
-#, fuzzy, c-format
-msgid "Channel %s is forbidden."
-msgstr "Channel %s is now persistant."
-
-#, fuzzy, c-format
-msgid "Channel %s is no longer persistent."
-msgstr "Channel %s is no longer persistant."
-
-#, fuzzy, c-format
-msgid "Channel %s is now persistent."
-msgstr "Channel %s is now persistant."
-
-#, c-format
-msgid "Channel %s is now released."
-msgstr "Канал %s успешно восстановлен из режима саспенда."
-
-#, c-format
-msgid "Channel %s is now suspended."
-msgstr "Активность канала %s приостановлена."
-
-#, fuzzy, c-format
-msgid "Channel %s isn't registered."
-msgstr "Канал %s не может быть зарегистрирован."
-
-#, fuzzy, c-format
-msgid "Channel %s isn't suspended."
-msgstr "Активность канала %s приостановлена."
-
-#, fuzzy, c-format
-msgid "Channel %s registered under your account: %s"
-msgstr ""
-"Ник %s успешно зарегистрирован, в ACCESS-список добавлена хостмаска: %s"
-
-#, c-format
-msgid "Channel %s will expire."
-msgstr "Режим истечения по времени для канала %s активирована."
-
-#, c-format
-msgid "Channel %s will not expire."
-msgstr "С этого момента, регистрация канала %s никогда не истечет."
-
-#, fuzzy, c-format
-msgid "Channel %s %s list has been cleared."
-msgstr "Список AOP'ов канала %s был полностью очищен."
-
-#, c-format
-msgid "Channel %s access list has been cleared."
-msgstr "Список доступа канала %s был полностью очищен."
-
-#, c-format
-msgid "Channel %s akick list has been cleared."
-msgstr "Список AKICK'ов на канале %s был полностью очищен."
-
-#, fuzzy, c-format
-msgid "Channel %s has no mode locks."
-msgstr "Канал %s успешно восстановлен из режима саспенда."
-
-#, fuzzy, c-format
-msgid "Channel %s is currently suspended."
-msgstr "Активность канала %s приостановлена."
-
-#, fuzzy, c-format
-msgid "Channel %s is not a valid channel."
-msgstr "Число %s не является валидным номером шаблона банмаски."
-
-#, fuzzy
-msgid "Channel list:"
-msgstr "Список ботов:"
-
-#, fuzzy, c-format
-msgid "Channel stats for %s on %s:"
-msgstr ""
-"Каналы, на которых у %s есть уровни доступа:\n"
-"Номер Канал Уровень Описание"
-
-#, fuzzy
-msgid "Channels may not be on access lists."
-msgstr "Ник %s в списке доступа канала %s не обнаружен."
-
-#, fuzzy, c-format
-msgid "Channels that %s has access on:"
-msgstr ""
-"Каналы, на которых у %s есть уровни доступа:\n"
-"Номер Канал Уровень Описание"
-
-#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-msgid "Chanstats"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Chanstats statistics are now disabled for %s"
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-msgid "Chanstats statistics are now disabled for this channel."
-msgstr ""
-
-#, fuzzy
-msgid "Chanstats statistics are now disabled for your nick."
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-#, fuzzy, c-format
-msgid "Chanstats statistics are now enabled for %s"
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-msgid "Chanstats statistics are now enabled for this channel."
-msgstr ""
-
-#, fuzzy
-msgid "Chanstats statistics are now enabled for your nick."
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-msgid ""
-"Checks for the last time nick was seen joining, leaving,\n"
-"or changing nick on the network and tells you when and, depending\n"
-"on channel or user settings, where it was."
-msgstr ""
-
-#, fuzzy
-msgid "Checks if last memo to a nick was read"
-msgstr ""
-" CHECK Проверка на то, было ли прочитано последнее посланное вами "
-"сообщение"
-
-#, fuzzy
-msgid ""
-"Checks whether the _last_ memo you sent to nick has been read\n"
-"or not. Note that this only works with nicks, not with channels."
-msgstr ""
-"Синтаксис: CHECK ник\n"
-"\n"
-"Проверяет, было ли прочитано последнее посланное вами сообщения\n"
-"указанным ником.\n"
-"Примечание: команда работает только для ников, не для каналов."
-
-#, c-format
-msgid "Cleared info from %s."
-msgstr ""
-
-#, fuzzy
-msgid "Colors kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Command"
-msgstr "Список команд %s:"
-
-#, fuzzy
-msgid "Configures AMSG kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures badwords kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures bolds kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures bot kickers. option can be one of:"
-msgstr ""
-"Синтаксис: SET опция параметры\n"
-"\n"
-"Команда SET позволяет вам настроить различные опции ника.\n"
-"Список опций:"
-
-#, fuzzy
-msgid "Configures bot options"
-msgstr "SET Настройка различных опций бота"
-
-#, fuzzy
-msgid ""
-"Configures bot options.\n"
-" \n"
-"Available options:"
-msgstr "SET Настройка различных опций бота"
-
-#, fuzzy
-msgid "Configures caps kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures channel logging settings"
-msgstr "* Запрет на регистрацию каналов."
-
-#, fuzzy
-msgid "Configures color kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures flood kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures italics kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures kickers"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures repeat kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures reverses kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Configures the time bot bans expire in"
-msgstr "SET Настройка различных опций бота"
-
-#, fuzzy
-msgid "Configures underlines kicker"
-msgstr "KICK Настройка условий KICK'а"
-
-#, fuzzy
-msgid "Confirm a passcode"
-msgstr " CONFIRM Подтверждение регистрации кодом аутенфикации"
-
-#, fuzzy
-msgid "Control modes and mode locks on a channel"
-msgstr " CLEARMODES Очистка всех режимов указанного канала"
-
-msgid ""
-"Controls what messages will be sent to users when they join the channel."
-msgstr ""
-
-msgid ""
-"Copies all settings, access, akicks, etc from channel to the\n"
-"target channel. If what is ACCESS, AKICK, BADWORDS,\n"
-"or LEVELS then only the respective settings are cloned.\n"
-"You must be the founder of channel and target."
-msgstr ""
-
-#, fuzzy
-msgid "Copy all settings from one channel to another"
-msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-
-#, fuzzy
-msgid "Created"
-msgstr "Создан..........: %s"
-
-#, fuzzy
-msgid "Creator"
-msgstr "Создан..........: %s"
-
-#, fuzzy, c-format
-msgid "Current %s list:"
-msgstr "Текущий список AKILL'ов:"
-
-#, fuzzy
-msgid "Current AKILL list:"
-msgstr "Текущий список AKILL'ов:"
-
-msgid "Current Session Limit Exception list:"
-msgstr "Текущий список исключений из лимита сессий:"
-
-#, fuzzy
-msgid "Current module list:"
-msgstr "Текущий список модулей:"
-
-#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Текущее количество AKILL'ов : %d"
-
-#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Текущее количество SNLINE'ов : %d"
-
-#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Текущее количество SQLINE'ов : %d"
-
-#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Текущее кол-во пользователей: %d, IRC-операторов: %d "
-
-#, fuzzy
-msgid "DEL oper"
-msgstr "DEL <ник>."
-
-#, fuzzy
-msgid "DEL target info"
-msgstr "GROUP главный_ник пароль"
-
-#, fuzzy
-msgid "DEL [nickname] channel"
-msgstr "MODE #канал режимы"
-
-#, fuzzy
-msgid "DEL [nickname] fingerprint"
-msgstr "FORBID ник причина"
-
-#, fuzzy
-msgid "DEL [nickname] mask"
-msgstr "MODE #канал режимы"
-
-#, fuzzy
-msgid "DEL {mask | entry-num | list | id}"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-#, fuzzy
-msgid "DEL {mask | entry-num | list}"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-#, fuzzy
-msgid "DEL {nick|mask}"
-msgstr "DEL <ник>."
-
-#, fuzzy
-msgid "DEL {num | ALL}"
-msgstr "Синтаксис: OPERNEWS DEL {номер | ALL}"
-
-msgid "DEL {NICK|CHAN|EMAIL|REGISTER} entry"
-msgstr ""
-
-msgid "DELIP server.name ip"
-msgstr ""
-
-msgid "DELSERVER server.name [zone.name]"
-msgstr ""
-
-msgid "DELZONE zone.name"
-msgstr ""
-
-#, fuzzy
-msgid "DEPOOL server.name"
-msgstr "NOOP {SET|REVOKE} сервер"
-
-#, c-format
-msgid "Database cleared, removed %lu nicks that were added after %s."
-msgstr ""
-
-msgid "Date/Time"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Deactivates the vhost currently assigned to the nick in use.\n"
-"When you use this command any user who performs a /whois\n"
-"on you will see your real host/IP address."
-msgstr ""
-"Синтаксис: OFF\n"
-"\n"
-"Деактивирует ваш текущий виртуальный хост, при условии, конечно,\n"
-"что таковой установлен на момент использования команды."
-
-#, fuzzy
-msgid "Deactivates your assigned vhost"
-msgstr " OFF Деактивирует ваш текущий виртуальный хост"
-
-#, c-format
-msgid "Default AKILL expiry time: %d days"
-msgstr "Время истечения AKILL'а по-умолчанию : %d дней"
-
-#, c-format
-msgid "Default AKILL expiry time: %d hours"
-msgstr "Время истечения AKILL'а по-умолчанию : %d часов"
-
-#, c-format
-msgid "Default AKILL expiry time: %d minutes"
-msgstr "Время истечения AKILL'а по-умолчанию : %d минут"
-
-msgid "Default AKILL expiry time: 1 day"
-msgstr "Время истечения AKILL'а по-умолчанию : 1 день"
-
-msgid "Default AKILL expiry time: 1 hour"
-msgstr "Время истечения AKILL'а по-умолчанию : 1 час"
-
-msgid "Default AKILL expiry time: 1 minute"
-msgstr "Время истечения AKILL'а по-умолчанию : 1 минута"
-
-msgid "Default AKILL expiry time: No expiration"
-msgstr "Время истечения AKILL'а по-умолчанию : никогда"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d days"
-msgstr "Время истечения SNLINE'а по-умолчанию : %d дней"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d hours"
-msgstr "Время истечения SNLINE'а по-умолчанию : %d часов"
-
-#, c-format
-msgid "Default SNLINE expiry time: %d minutes"
-msgstr "Время истечения SNLINE'а по-умолчанию : %d минут"
-
-msgid "Default SNLINE expiry time: 1 day"
-msgstr "Время истечения SNLINE'а по-умолчанию : 1 день"
-
-msgid "Default SNLINE expiry time: 1 hour"
-msgstr "Время истечения SNLINE'а по-умолчанию : 1 час"
-
-msgid "Default SNLINE expiry time: 1 minute"
-msgstr "Время истечения SNLINE'а по-умолчанию : 1 минута"
-
-msgid "Default SNLINE expiry time: No expiration"
-msgstr "Время истечения SNLINE'а по-умолчанию : никогда"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d days"
-msgstr "Время истечения SQGLINE'а по-умолчанию: %d дней"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d hours"
-msgstr "Время истечения SQGLINE'а по-умолчанию: %d часов"
-
-#, c-format
-msgid "Default SQLINE expiry time: %d minutes"
-msgstr "Время истечения SQGLINE'а по-умолчанию: %d минут"
-
-msgid "Default SQLINE expiry time: 1 day"
-msgstr "Время истечения SQGLINE'а по-умолчанию: 1 день"
-
-msgid "Default SQLINE expiry time: 1 hour"
-msgstr "Время истечения SQGLINE'а по-умолчанию: 1 час"
-
-msgid "Default SQLINE expiry time: 1 minute"
-msgstr "Время истечения SQGLINE'а по-умолчанию: 1 минута"
-
-msgid "Default SQLINE expiry time: No expiration"
-msgstr "Время истечения SQGLINE'а по-умолчанию: никогда"
-
-#, fuzzy
-msgid "Define messages to be randomly shown to users at logon"
-msgstr " LOGONNEWS Управление списком новостей при подключении"
-
-#, fuzzy
-msgid "Define messages to be shown to users at logon"
-msgstr " LOGONNEWS Управление списком новостей при подключении"
-
-#, fuzzy
-msgid "Define messages to be shown to users who oper"
-msgstr " OPERNEWS Управление списком опер-новостей"
-
-#, fuzzy
-msgid "Delete a memo or memos"
-msgstr " DEL Удаление мемо-сообщений"
-
-#, fuzzy
-msgid "Delete the vhost of another user"
-msgstr " DEL Удаление виртуального хоста"
-
-#, fuzzy, c-format
-msgid "Deleted %d entries from %s %s list."
-msgstr "Удалено %d записей из списка AOP'ов канала %s."
-
-#, c-format
-msgid "Deleted %d entries from %s access list."
-msgstr "Удалено %d записей из списка доступа канала %s."
-
-#, c-format
-msgid "Deleted %d entries from %s autokick list."
-msgstr "Удалено %d записей из списка актокиков канала %s."
-
-#, c-format
-msgid "Deleted %d entries from %s bad words list."
-msgstr "Удалено %d записей из списка плохих слов канала %s."
-
-#, c-format
-msgid "Deleted %d entries from session-limit exception list."
-msgstr "Удалено %d записей из списка исключений лимита сессий."
-
-#, fuzzy, c-format
-msgid "Deleted %d entries from the %s list."
-msgstr "Удалено %d записей из списка AOP'ов канала %s."
-
-#, c-format
-msgid "Deleted %d entries from the AKILL list."
-msgstr "Удалено %d записей из списка AKILL'ов."
-
-#, c-format
-msgid "Deleted 1 entry from %s access list."
-msgstr "Удалена 1 запись из списка доступа канала %s."
-
-#, c-format
-msgid "Deleted 1 entry from %s autokick list."
-msgstr "Удалена 1 запись из списка автокиков канала %s."
-
-#, c-format
-msgid "Deleted 1 entry from %s bad words list."
-msgstr "Удалена 1 запись из списка плохих слов канала %s."
-
-msgid "Deleted 1 entry from session-limit exception list."
-msgstr "Удалена 1 запись из списка исключений лимита сессий."
-
-#, fuzzy, c-format
-msgid "Deleted 1 entry from the %s list."
-msgstr "Удалена 1 запись из спика AKILL'ов."
-
-msgid "Deleted 1 entry from the AKILL list."
-msgstr "Удалена 1 запись из спика AKILL'ов."
-
-#, fuzzy, c-format
-msgid "Deleted info from %s."
-msgstr "Удалена 1 запись из спика AKILL'ов."
-
-#, fuzzy, c-format
-msgid "Deleted one entry from %s %s list."
-msgstr "Удалена 1 запись из списка AOP'ов канала %s."
-
-#, fuzzy
-msgid ""
-"Deletes the specified memo or memos. You can supply\n"
-"multiple memo numbers or ranges of numbers instead of a\n"
-"single number, as in the second example below.\n"
-" \n"
-"If LAST is given, the last memo will be deleted.\n"
-"If ALL is given, deletes all of your memos.\n"
-" \n"
-"Examples:\n"
-" \n"
-" DEL 1\n"
-" Deletes your first memo.\n"
-" \n"
-" DEL 2-5,7-9\n"
-" Deletes memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Синтаксис: DEL [#канал] {номер | список_записей | LAST | ALL}\n"
-"\n"
-"Позволяет удалить указанное сообщение. В зависимости от указанного\n"
-"параметра, вы можете удалить сразу несколько сообщений или целый\n"
-"диапазон сообщений (см. пример ниже).\n"
-"\n"
-"Параметр LAST позволяет удалить последнее полученное сообщение.\n"
-"Параметр ALL позволяет полностью очистить список сообщений.\n"
-"\n"
-"Примеры:\n"
-"\n"
-" DEL 1\n"
-" удалит сообщение под номером 1.\n"
-"\n"
-" DEL 2-5,7-9\n"
-" удалит все сообщения с 2-го по 5-ое и с 7-го по 9-ое."
-
-#, fuzzy
-msgid ""
-"Deletes the vhost assigned to the given nick from the\n"
-"database."
-msgstr ""
-"Синтаксис: DEL <ник>\n"
-"\n"
-"Удаляет виртуальный хост назначенный указанному нику."
-
-#, fuzzy
-msgid "Deletes the vhost for all nicks in a group"
-msgstr " DELALL Удаление вирт. хоста у всех ников указанной группы"
-
-#, fuzzy
-msgid ""
-"Deletes the vhost for all nicks in the same group as\n"
-"that of the given nick."
-msgstr ""
-"Синтаксис: DELALL <ник>.\n"
-"\n"
-"Удаляет виртуальные хосты у всех ников указанной группы."
-
-#, c-format
-msgid "Depooled %s."
-msgstr ""
-
-#, fuzzy
-msgid "Description"
-msgstr "Описание канала %s изменено на %s."
-
-#, c-format
-msgid "Description of %s changed to %s."
-msgstr "Описание канала %s изменено на %s."
-
-#, fuzzy, c-format
-msgid "Description of %s unset."
-msgstr "Описание канала %s изменено на %s."
-
-#, fuzzy
-msgid "Disabled"
-msgstr "Режим %s: включен."
-
-#, fuzzy
-msgid ""
-"Disallows anyone from using the given channel.\n"
-"May be cancelled by using the UNSUSPEND\n"
-"command to preserve all previous channel data/settings.\n"
-"If an expiry is given the channel will be unsuspended after\n"
-"that period of time, else the default expiry from the\n"
-"configuration is used.\n"
-" \n"
-"Reason may be required on certain networks."
-msgstr ""
-"Синтаксис: SUSPEND #канал [причина]\n"
-"\n"
-"Приостанавливает любую активность указанного канала (замораживает).\n"
-"В режиме саспенда, на канал не действуют условия истечения регистрации\n"
-"по времени, канал невозможно использовать или удалить. Единственное,\n"
-"что владелец все еще может - это изменять настройки своего канала.\n"
-"Эффект \"заморозки\" отменяется путем использования команды UNSUSPEND,\n"
-"которая полностью восстанавливает активность канала со всеми его\n"
-"настройками.\n"
-"\n"
-"Примечание: в зависимости от настроек сервисов, причина может\n"
-"быть параметром как опциональным, так и необходимым."
-
-#, fuzzy, c-format
-msgid "Displayed %d records (%d total)."
-msgstr "Конец списка хостов, записей насчитано: %d"
-
-#, fuzzy, c-format
-msgid "Displayed all records (count: %d)."
-msgstr "Конец списка хостов, записей насчитано: %d"
-
-#, fuzzy, c-format
-msgid "Displayed records from %d to %d."
-msgstr "Конец списка записей с %d по %d"
-
-#, fuzzy, c-format
-msgid "Displayed records matching key %s (count: %d)."
-msgstr "Конец списка хостов по маске %s, записей насчитано: %d"
-
-#, fuzzy
-msgid "Displays information about a given nickname"
-msgstr " INFO Информация о каком-либо нике"
-
-#, fuzzy
-msgid ""
-"Displays information about the given nickname, such as\n"
-"the nick's owner, last seen address and time, and nick\n"
-"options. If no nick is given, and you are identified,\n"
-"your account name is used, else your current nickname is\n"
-"used."
-msgstr ""
-"Синтаксис: INFO ник\n"
-"\n"
-"Запрашивает у сервисов информацию об указанном нике. В частности\n"
-"будут показаны: реальное имя владельца (realname), его последняя\n"
-"хостмаска, когда он последний раз был в IRC под этим ником. Если вы\n"
-"запрашиваете информацию относительно своего ника, вы можете указать\n"
-"параметр ALL, чтобы получить всю доступную информацию, в том числе\n"
-"и ту, которая скрыта."
-
-#, fuzzy
-msgid "Displays information about your memos"
-msgstr " INFO Информация о кол-ве сообщений и настройках оповещения"
-
-#, fuzzy
-msgid "Displays one or more vhost entries"
-msgstr " LIST Вывод списка всех виртуальных хостов"
-
-#, fuzzy
-msgid "Displays the top 10 users of a channel"
-msgstr " FOUNDER смена владельца канала"
-
-msgid "Displays the top 10 users of the network"
-msgstr ""
-
-#, fuzzy
-msgid "Displays the top 3 users of a channel"
-msgstr " FOUNDER смена владельца канала"
-
-msgid "Displays the top 3 users of the network"
-msgstr ""
-
-#, fuzzy
-msgid "Displays this list and give information about commands"
-msgstr " INFO Информация о кол-ве сообщений и настройках оповещения"
-
-msgid "Displays your Channel Stats"
-msgstr ""
-
-msgid "Displays your Global Stats"
-msgstr ""
-
-msgid "Don't use AMSGs!"
-msgstr ""
-
-msgid "Don't use bolds on this channel!"
-msgstr "Использование жирного шрифта у нас тут не приветствуется!"
-
-msgid "Don't use colors on this channel!"
-msgstr "Использование цветов у нас тут не приветствуется!"
-
-msgid "Don't use italics on this channel!"
-msgstr "Don't use italics on this channel!"
-
-msgid "Don't use reverses on this channel!"
-msgstr "Использование инверсии у нас тут не приветствуется!"
-
-#, c-format
-msgid "Don't use the word \"%s\" on this channel!"
-msgstr "Слово %s запрещено на этом канале!"
-
-msgid "Don't use underlines on this channel!"
-msgstr "Использование подчеркиваний у нас тут не приветствуется!"
-
-msgid ""
-"Drops the given nick from the database. Once your nickname\n"
-"is dropped you may lose all of your access and channels that\n"
-"you may own. Any other user will be able to gain control of\n"
-"this nick."
-msgstr ""
-
-#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "Email-адрес для %s изменен на %s."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "Email-адрес для %s удален."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "Email-адрес для %s некорректен."
-
-#, fuzzy, c-format
-msgid ""
-"Edits or displays the list of logon news messages. When a\n"
-"user connects to the network, these messages will be sent\n"
-"to them. However, no more than %d messages will be\n"
-"sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
-msgstr ""
-"Синтаксис: LOGONNEWS ADD текст\n"
-" LOGONNEWS DEL {номер | ALL}\n"
-" LOGONNEWS LIST\n"
-"\n"
-"Позволяет управлять списком новостей, которые будут автоматически\n"
-"выдаваться пользователю сразу же, как только он подключится к сети.\n"
-"Стоит заметить, что во избежание флуда пользователь получит только\n"
-"%d новость(и), так что если у вас в списке их больше - показаны\n"
-"будут только последние из них. Значение NewsCount, отвечающее за\n"
-"одновременно посылаемое кол-во новостей, указывается в services.conf\n"
-"\n"
-"Команда LOGONNEWS ADD позволяет добавить новость в список.\n"
-"\n"
-"Команда LOGONNEWS DEL позволяет удалить новость из списка. В\n"
-"качестве параметра вы можете указать номер новости - что бы удалить\n"
-"одну новость, или ALL - что бы очистить список новостей полностью.\n"
-"\n"
-"LOGONNEWS may only be used by Services Operators."
-
-#, fuzzy, c-format
-msgid ""
-"Edits or displays the list of oper news messages. When a\n"
-"user opers up (with the /OPER command), these messages will\n"
-"be sent to them. However, no more than %d messages will\n"
-"be sent in order to avoid flooding the user. If there are\n"
-"more news messages, only the most recent will be sent."
-msgstr ""
-"Синтаксис: OPERNEWS ADD текст\n"
-" OPERNEWS DEL {номер | ALL}\n"
-" OPERNEWS LIST\n"
-"\n"
-"Позволяет управлять списком новостей для IRC-Операторов. Как только\n"
-"пользователь получит статус IRC-оператора (использовав команду /OPER),\n"
-"данные сообщения будут ему отправлены автоматически.\n"
-"Стоит заметить, что во избежание флуда пользователь получит только\n"
-"%d новость(и), так что если у вас в списке их больше - показаны\n"
-"будут только последние из них. Значение NewsCount, отвечающее за\n"
-"одновременно посылаемое кол-во новостей, указывается в services.conf\n"
-"\n"
-"Команда OPERNEWS ADD позволяет добавить новость в список.\n"
-"\n"
-"Команда OPERNEWS DEL позволяет удалить новость из списка. В\n"
-"качестве параметра вы можете указать номер новости - что бы удалить\n"
-"одну новость, или ALL - что бы очистить список новостей полностью.\n"
-"\n"
-"OPERNEWS may only be used by Services Operators."
-
-#, fuzzy
-msgid ""
-"Edits or displays the list of random news messages. When a\n"
-"user connects to the network, one (and only one) of the\n"
-"random news will be randomly chosen and sent to them."
-msgstr ""
-"Синтаксис: RANDOMNEWS ADD текст\n"
-" RANDOMNEWS DEL {текст | ALL}\n"
-" RANDOMNEWS LIST\n"
-"\n"
-"Позволяет управлять списком случайных новостей.\n"
-"Как только пользователь успешно подключится к IRC-сети, одна (и\n"
-"только одна) из случайных новостей будет выбрана сервисами наугад и\n"
-"отправлена ему.\n"
-"\n"
-"Команда RANDOMNEWS ADD позволяет добавить новость в список.\n"
-"\n"
-"Команда RANDOMNEWS DEL позволяет удалить новость из списка. В\n"
-"качестве параметра вы можете указать номер новости - что бы удалить\n"
-"одну новость, или ALL - что бы очистить список новостей полностью.\n"
-"\n"
-"RANDOMNEWS may only be used by Services Operators."
-
-#, fuzzy
-msgid "Email address"
-msgstr "Email-адрес.............: %s"
-
-#, fuzzy, c-format
-msgid "Email matched: %s (%s) to %s."
-msgstr "Найдено соответствие для ника %s: %s."
-
-msgid "Enable fantaisist commands"
-msgstr ""
-
-msgid "Enable greet messages"
-msgstr ""
-
-msgid "Enable or disable keep modes"
-msgstr ""
-
-#, fuzzy
-msgid "Enabled"
-msgstr "Режим %s: включен."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables %s's autoop feature for a\n"
-"channel. When disabled, users who join the channel will\n"
-"not automatically gain any status from %s."
-msgstr ""
-"Синтаксис: %s #канал SECUREOPS {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим ограничения на получение статуса\n"
-"оператора канала. Данный режим позволяет запретить возможность\n"
-"получения статуса опа тем пользователям, которые не присутствуют\n"
-"в списке доступа канала или права которых не соответствуют\n"
-"получаемому статусу."
-
-#, fuzzy
-msgid ""
-"Enables or disables keepmodes for the given channel. If keep\n"
-"modes is enabled, services will remember modes set on the channel\n"
-"and attempt to re-set them the next time the channel is created."
-msgstr ""
-"Синтаксис: %s #канал KEEPTOPIC {ON | OFF}\n"
-"\n"
-"Позволяет активировать/деактивировать опцию хранения топика на\n"
-"канале. При включенном режиме хранения топика, текст топика канала\n"
-"будет сохраняться в базе данных %s после того, как последний\n"
-"пользователь покинет канал, и автоматически восстанавливаться сразу\n"
-"же, как только канал снова станет активным (то есть, на него опять\n"
-"кто-либо зайдет)."
-
-msgid ""
-"Enables or disables keepmodes for the given nick. If keep\n"
-"modes is enabled, services will remember users' usermodes\n"
-"and attempt to re-set them the next time they authenticate."
-msgstr ""
-
-msgid ""
-"Enables or disables keepmodes for your nick. If keep\n"
-"modes is enabled, services will remember your usermodes\n"
-"and attempt to re-set them the next time you authenticate."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Синтаксис: %s #канал SECURE {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим безопасности для канала.\n"
-"Когда SECURE включено, только пользователи с зарегистрированными\n"
-"никами, проидентифицировавшиеся к ним через пароль и включенные в\n"
-"список доступа канала, смогут запросить статус на канале с помощью\n"
-"%s.\n"
-"Если безопасность отключена, пользователи, прописанные на канале,\n"
-"смогут запросить статус даже если имеют авторизацию к своему нику\n"
-"всего лишь через список масок на %s."
-
-#, fuzzy
-msgid ""
-"Enables or disables signed kicks for a\n"
-"channel. When SIGNKICK is set, kicks issued with\n"
-"the KICK command will have the nick that used the\n"
-"command in their reason.\n"
-" \n"
-"If you use LEVEL, those who have a level that is superior\n"
-"or equal to the SIGNKICK level on the channel won't have their\n"
-"kicks signed."
-msgstr ""
-"Синтаксис: %s #канал SIGNKICK {ON | LEVEL | OFF}\n"
-"\n"
-"Включает или выключает опцию \"подписанных киков\" на канале.\n"
-"Активирование режима SIGNKICK заставит %s автоматически\n"
-"добавлять к причине кика ник того, кто использовал команду KICK.\n"
-"\n"
-"В качестве дополнительного параметра для опции SIGNKICK вы можете\n"
-"указать значение LEVEL. Это позволит более тонко лимитировать\n"
-"действие данного режима, при условии конечно, что вы используете\n"
-"систему LEVELS на канале (см. /msg %s HELP LEVELS для\n"
-"более подробной информации)."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the peace option for a channel.\n"
-"When peace is set, a user won't be able to kick,\n"
-"ban or remove a channel status of a user that has\n"
-"a level superior or equal to his via %s commands."
-msgstr ""
-"Синтаксис: %s #канал PEACE {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует опцию спокойствия на канале. Данный режим\n"
-"позволяет запретить использование таких команд %s'а как BAN,\n"
-"OP, DEOP, KICK и т. д. относительно тех, кто выше или равен по\n"
-"статусу относительно использующего.\n"
-"Примечание: тем не менее любой, имеющий доступ к этим командам,\n"
-"сможет использовать их относительно себя."
-
-msgid "Enables or disables the private option for a channel."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-msgstr ""
-"Синтаксис: %s #канал RESTRICTED {ON | OFF}\n"
-"\n"
-"Enables or disables the restricted access option for a\n"
-"channel. When restricted access is set, users not on the access list will\n"
-"instead be kicked and banned from the channel."
-
-#, fuzzy
-msgid ""
-"Enables or disables the secure founder option for a channel.\n"
-"When secure founder is set, only the real founder will be\n"
-"able to drop the channel, change its founder and its successor,\n"
-"and not those who have founder level access through\n"
-"the access/qop command."
-msgstr ""
-"Синтаксис: %s #канал SECUREFOUNDER {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим безопасности владельца на канале.\n"
-"Активирование SECUREFOUNDER позволяет вам ограничить возможность\n"
-"удаления канала, изменения его пароля, владельца или наследника до\n"
-"реального владельца, прописанного в графе Founder (Владелец канала).\n"
-"(и не важно, кто там идентифицировался к каналу через %s ID)."
-
-#, fuzzy
-msgid ""
-"Enables or disables the secure ops option for a channel.\n"
-"When secure ops is set, users who are not on the access list\n"
-"will not be allowed channel operator status."
-msgstr ""
-"Синтаксис: %s #канал SECUREOPS {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим ограничения на получение статуса\n"
-"оператора канала. Данный режим позволяет запретить возможность\n"
-"получения статуса опа тем пользователям, которые не присутствуют\n"
-"в списке доступа канала или права которых не соответствуют\n"
-"получаемому статусу."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the topic retention option for a\n"
-"channel. When %s is set, the topic for the\n"
-"channel will be remembered by %s even after the\n"
-"last user leaves the channel, and will be restored the\n"
-"next time the channel is created."
-msgstr ""
-"Синтаксис: %s #канал KEEPTOPIC {ON | OFF}\n"
-"\n"
-"Позволяет активировать/деактивировать опцию хранения топика на\n"
-"канале. При включенном режиме хранения топика, текст топика канала\n"
-"будет сохраняться в базе данных %s после того, как последний\n"
-"пользователь покинет канал, и автоматически восстанавливаться сразу\n"
-"же, как только канал снова станет активным (то есть, на него опять\n"
-"кто-либо зайдет)."
-
-#, fuzzy, c-format
-msgid ""
-"Enables or disables the persistent channel setting.\n"
-"When persistent is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-" \n"
-"If your IRCd does not have a permanent (persistent) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-" \n"
-"If this network does not have %s enabled and does\n"
-"not have a permanent channel mode, %s will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-" \n"
-"If your IRCd has a permanent (persistent) channel mode\n"
-"and it is set or unset (for any reason, including MODE LOCK),\n"
-"persist is automatically set and unset for the channel as well.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-msgstr ""
-"Syntax: %s channel PERSIST {ON | OFF}\n"
-"Enables or disables the persistant channel setting.\n"
-"When persistant is set, the service bot will remain\n"
-"in the channel when it has emptied of users.\n"
-"\n"
-"If your IRCd does not a permanent (persistant) channel\n"
-"mode you must have a service bot in your channel to\n"
-"set persist on, and it can not be unassigned while persist\n"
-"is on.\n"
-"\n"
-"If this network does not have BotServ enabled and does\n"
-"not have a permanent channel mode, ChanServ will\n"
-"join your channel when you set persist on (and leave when\n"
-"it has been set off).\n"
-"\n"
-"If your IRCd has a permanent (persistant) channel mode\n"
-"and is is set or unset (for any reason, including MLOCK),\n"
-"persist is automatically set and unset for the channel aswell.\n"
-"Additionally, services will set or unset this mode when you\n"
-"set persist on or off."
-
-#, fuzzy
-msgid "End of AKILL list."
-msgstr "Конец списка пользователей."
-
-#, fuzzy
-msgid "End of access list"
-msgstr "Конец списка доступа."
-
-#, fuzzy, c-format
-msgid "End of access list - %d/%d entries shown."
-msgstr "Конец списка - %d/%d записей показано."
-
-msgid "End of access list."
-msgstr "Конец списка доступа."
-
-#, fuzzy
-msgid "End of autokick list"
-msgstr "Конец списка доступа."
-
-#, fuzzy
-msgid "End of bad words list."
-msgstr "Конец списка пользователей."
-
-#, fuzzy, c-format
-msgid "End of channel list. %u channels shown."
-msgstr "Конец списка - %d/%d записей показано."
-
-msgid "End of configuration."
-msgstr ""
-
-#, fuzzy
-msgid "End of entry message list."
-msgstr "Конец списка пользователей."
-
-#, fuzzy, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Конец списка - %d/%d записей показано."
-
-#, fuzzy
-msgid "End of forbid list."
-msgstr "Конец списка пользователей."
-
-#, fuzzy, c-format
-msgid "End of list - %d channels shown."
-msgstr "Конец списка - %d/%d записей показано."
-
-#, c-format
-msgid "End of list - %d/%d matches shown."
-msgstr "Конец списка - %d/%d записей показано."
-
-#, fuzzy
-msgid "End of news list."
-msgstr "Конец списка пользователей."
-
-#, fuzzy, c-format
-msgid "End of users list. %u users shown."
-msgstr "Конец списка - %d/%d записей показано."
-
-msgid "Enforce various channel modes and set options"
-msgstr ""
-
-msgid ""
-"Enforce various channel modes and set options. The channel\n"
-"option indicates what channel to enforce the modes and options\n"
-"on. The what option indicates what modes and options to\n"
-"enforce, and can be any of SECUREOPS, RESTRICTED, REGONLY, SSLONLY,\n"
-"BANS, or LIMIT.\n"
-" \n"
-"Use SECUREOPS to enforce the SECUREOPS option, even if it is not\n"
-"enabled. Use RESTRICTED to enforce the RESTRICTED option, also\n"
-"if it's not enabled. Use REGONLY to kick all unregistered users\n"
-"from the channel. Use SSLONLY to kick all users not using a secure\n"
-"connection from the channel. BANS will enforce bans on the channel by\n"
-"kicking users affected by them, and LIMIT will kick users until the\n"
-"user count drops below the channel limit, if one is set."
-msgstr ""
-
-msgid "English"
-msgstr "Русский"
-
-#, fuzzy, c-format
-msgid "Entry message %i for %s deleted."
-msgstr "Приветствие для %s удалено."
-
-#, fuzzy, c-format
-msgid "Entry message %s not found on channel %s."
-msgstr "FANTASY-режим для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Entry message added to %s"
-msgstr "Приветствие для %s изменено на %s."
-
-#, fuzzy, c-format
-msgid "Entry message list for %s is empty."
-msgstr "Список доступа для %s пуст."
-
-#, fuzzy, c-format
-msgid "Entry message list for %s:"
-msgstr "Список доступа для %s:"
-
-#, fuzzy, c-format
-msgid "Entry messages for %s have been cleared."
-msgstr "Все сообщения канала %s были удалены."
-
-#, fuzzy, c-format
-msgid "Error reloading configuration file: %s"
-msgstr " RELOAD Перезагрузка конфигурационного файла сервисов"
-
-#, c-format
-msgid ""
-"Error! The vHost ident is too long, please use an ident shorter than %d "
-"characters."
-msgstr ""
-
-#, c-format
-msgid ""
-"Error! The vHost is too long, please use a hostname shorter than %d "
-"characters."
-msgstr ""
-
-msgid ""
-"Examples:\n"
-" \n"
-" CERT ADD\n"
-" Adds your current fingerprint to the certificate list and\n"
-" automatically identifies you when you connect to IRC\n"
-" using this fingerprint.\n"
-" \n"
-" CERT DEL <fingerprint>\n"
-" Removes the fingerprint <fingerprint> from your certificate list.\n"
-" \n"
-" CERT LIST\n"
-" Displays the current certificate list."
-msgstr ""
-
-#, c-format
-msgid "Exception for %s has been updated to %d."
-msgstr "Лимит сессий для записи вида %s был изменен на %d."
-
-#, fuzzy
-msgid "Expires"
-msgstr "Регистрация истекает....: %s"
-
-#, fuzzy, c-format
-msgid "Expiry and reason updated for %s."
-msgstr "Лимит сессий для записи вида %s был изменен на %d."
-
-#, fuzzy, c-format
-msgid "Expiry for %s updated."
-msgstr "Срок истечения записи %s успешно изменен."
-
-msgid "Fantasy"
-msgstr "FANTASY-режим"
-
-#, fuzzy, c-format
-msgid "Fantasy mode is now off on channel %s."
-msgstr "FANTASY-режим для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Fantasy mode is now on on channel %s."
-msgstr "FANTASY-режим для канала %s активирован."
-
-#, fuzzy
-msgid "Find a user's status on a channel"
-msgstr " DEOWNER Снимает с вас статус владельца канала"
-
-#, fuzzy, c-format
-msgid "Fingerprint %s already present on %s's certificate list."
-msgstr "Маска вида %s уже присутствует в вашем списке доступа."
-
-#, fuzzy, c-format
-msgid "Fingerprint %s is already in use."
-msgstr "You are already in %s! "
-
-msgid "Flags"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Flags for %s on %s set to +%s"
-msgstr "Уровень доступа для %s на канале %s изменен на %d."
-
-#, fuzzy, c-format
-msgid "Flags list for %s"
-msgstr "Список доступа для %s:"
-
-#, fuzzy
-msgid "Flood kicker"
-msgstr "Цензор флуда.........: %s"
-
-msgid ""
-"Forbid allows you to forbid usage of certain nicknames, channels,\n"
-"and email addresses. Wildcards are accepted for all entries."
-msgstr ""
-
-#, fuzzy
-msgid "Forbid list is empty."
-msgstr "Список игнорируемых ников пуст."
-
-#, fuzzy
-msgid "Forbid list:"
-msgstr "Список ботов:"
-
-#, c-format
-msgid "Forbid on %s was not found."
-msgstr ""
-
-msgid "Forbid usage of nicknames, channels, and emails"
-msgstr ""
-
-#, fuzzy
-msgid "Force the Services databases to be updated immediately"
-msgstr " UPDATE Обновление баз данных сервисов (сохранение на диск)"
-
-#, fuzzy
-msgid "Forcefully change a user's nickname"
-msgstr " SVSNICK Принудительное изменение ника пользователя сети"
-
-#, fuzzy
-msgid "Forcefully changes a user's nickname from nick to newnick."
-msgstr ""
-"Синтаксис: SVSNICK ник новый_ник\n"
-"\n"
-"Позволяет принудительно изменить указанный ник на новый_ник."
-
-#, fuzzy
-msgid "Forcefully join a user to a channel"
-msgstr " SVSNICK Принудительное изменение ника пользователя сети"
-
-#, fuzzy
-msgid "Forcefully join a user to a channel."
-msgstr " SVSNICK Принудительное изменение ника пользователя сети"
-
-#, fuzzy
-msgid "Forcefully part a user from a channel"
-msgstr " KICK Кикнуть пользователя с канала посредством сервисов"
-
-#, fuzzy
-msgid "Forcefully part a user from a channel."
-msgstr " KICK Кикнуть пользователя с канала посредством сервисов"
-
-#, fuzzy
-msgid "Founder"
-msgstr "Безопасность владельца"
-
-#, fuzzy, c-format
-msgid "Founder of %s changed to %s."
-msgstr "Все права на владение каналом %s успешно переданы пользователю %s."
-
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "Команда GETPASS недоступна, так как включено шифрование паролей."
-
-msgid "Ghost with your nick has been killed."
-msgstr "Сессия с вашим зависшим ником успешно закрыта."
-
-#, fuzzy
-msgid "Give Operflags to a certain user"
-msgstr " OLINE Установка оперфлагов указанному пользователю сети"
-
-#, c-format
-msgid ""
-"Gives %s status to the selected nick on a channel. If nick is\n"
-"not given, it will %s you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Gives you or the specified nick %s status on a channel"
-msgstr " OWNER Запрос статуса владельца на канале"
-
-msgid "Greet"
-msgstr "Приветствия"
-
-#, fuzzy
-msgid "Greet message displayed on join"
-msgstr "Приветствие для %s изменено на %s."
-
-#, c-format
-msgid "Greet message for %s changed to %s."
-msgstr "Приветствие для %s изменено на %s."
-
-#, c-format
-msgid "Greet message for %s unset."
-msgstr "Приветствие для %s удалено."
-
-#, fuzzy, c-format
-msgid "Greet mode is now off on channel %s."
-msgstr "Режим приветствий для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Greet mode is now on on channel %s."
-msgstr "Режим приветствий для канала %s активирован."
-
-#, fuzzy
-msgid "Helps you reset lost passwords"
-msgstr " RESETPASS Helps you reset lost passwords"
-
-#, fuzzy
-msgid "Hide certain pieces of nickname information"
-msgstr " HIDE скрытие различной информации о вашем нике"
-
-#, fuzzy
-msgid "Hide channel from the LIST command"
-msgstr " PRIVATE скрытие канала в списке каналов выводимых по LIST"
-
-msgid "Host"
-msgstr ""
-
-#, c-format
-msgid "Hosts with at least %d sessions:"
-msgstr "Список хостов с количеством сессий %d и более:"
-
-#, c-format
-msgid "I don't know who %s is."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "I've never seen %s on this channel."
-msgstr "Использование инверсии у нас тут не приветствуется!"
-
-msgid "ID"
-msgstr ""
-
-msgid "INFO [type]"
-msgstr ""
-
-msgid "IP"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "IP %s already exists for %s."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy, c-format
-msgid "IP %s does not exist for %s."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy
-msgid "Identify yourself with your password"
-msgstr " IDENTIFY Идентификация к нику в качестве владельца"
-
-#, fuzzy, c-format
-msgid "If you do not change within %s, I will change your nick."
-msgstr ""
-"Если вы не выполните указанные рекомендации, ваш ник будет принудительно "
-"изменен в течении 20 секунд."
-
-msgid "Ignore list has been cleared."
-msgstr "Список игнорируемых ников полностью очищен."
-
-msgid "Ignore list is empty."
-msgstr "Список игнорируемых ников пуст."
-
-#, fuzzy
-msgid "Ignore list:"
-msgstr "Список ботов:"
-
-#, fuzzy
-msgid "Immediate protection"
-msgstr "Не кикать войсов"
-
-#, fuzzy
-msgid "Incorrect email address."
-msgstr "Email-адрес.............: %s"
-
-msgid "Incorrect range specified. The correct syntax is #from-to."
-msgstr ""
-
-#, fuzzy
-msgid "Info about a loaded module"
-msgstr " MODINFO Информация о загруженном модуле"
-
-#, c-format
-msgid "Information for bot %s:"
-msgstr "Информация о боте %s:"
-
-#, fuzzy, c-format
-msgid "Information for channel %s:"
-msgstr "Информация о боте %s:"
-
-#, c-format
-msgid "Invalid duration %s, using %d days."
-msgstr ""
-
-msgid "Invalid expiry time."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Invalid hostmask. Only real hostmasks are valid, as exceptions are not "
-"matched against nicks or usernames."
-msgstr ""
-"Указана некорректная хостмаска. Только реальный хост, не содержащий ников и "
-"идентов пользователей, может быть добавлен в список исключения."
-
-#, c-format
-msgid "Invalid limit %s, using %d."
-msgstr ""
-
-msgid ""
-"Invalid passcode has been entered, please check the e-mail again, and retry."
-msgstr ""
-
-msgid "Invalid passcode."
-msgstr ""
-
-#, c-format
-msgid ""
-"Invalid session limit. It must be a valid integer greater than or equal to "
-"zero and less than %d."
-msgstr ""
-"Некорректное значение лимита. Оно должно быть целым числом, больше или "
-"равным нулю, и меньше %d."
-
-msgid "Invalid threshold value. It must be a valid integer greater than 1."
-msgstr ""
-"Некорректное значение для порога сессий. В качестве параметра должно быть "
-"целое число >1."
-
-msgid "Invalid value for LIMIT. Must be numerical."
-msgstr ""
-
-#, fuzzy
-msgid "Invites you or an optionally specified nick into a channel"
-msgstr ""
-" OP Установка статуса оператора (+o) указанному нику на канале"
-
-#, fuzzy
-msgid "Italics kicker"
-msgstr "Italics kicker : %s"
-
-#, fuzzy
-msgid "Join a group"
-msgstr " GROUP Объединение ников в группы"
-
-#, fuzzy
-msgid "Keep modes"
-msgstr "Режим приватных сообщений"
-
-#, fuzzy, c-format
-msgid "Keep modes for %s is now off."
-msgstr "Режим спокойствия для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Keep modes for %s is now on."
-msgstr "Режим спокойствия для канала %s активирован."
-
-msgid "Key"
-msgstr ""
-
-#, c-format
-msgid "Key for channel %s is %s."
-msgstr "Key for channel %s is %s."
-
-#, fuzzy
-msgid "Kick a user from a channel"
-msgstr " KICK Кикнуть пользователя с канала посредством сервисов"
-
-#, c-format
-msgid "Kicked %d/%d users matching %s from %s."
-msgstr ""
-
-#, fuzzy
-msgid "Kicks a specified nick from a channel"
-msgstr " KICK Выкидывает указанного пользователя с канала"
-
-#, fuzzy
-msgid ""
-"Kicks a specified nick from a channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access\n"
-"and above on the channel. Channel founders can also specify masks."
-msgstr ""
-"Синтаксис: KICK #канал ник [причина]\n"
-"\n"
-"Выкидывает указанного пользователя с указанного канала.\n"
-"\n"
-"По-умолчанию, данная команда может быть использована AOP'ами или\n"
-"лицами с уровнем доступа 5 и выше."
-
-msgid "Kill a user"
-msgstr ""
-
-msgid "LIMIT enforced by "
-msgstr ""
-
-#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr ""
-
-msgid "LIST threshold"
-msgstr ""
-
-#, fuzzy
-msgid "LIST [mask | list | id]"
-msgstr "LIST [#канал] [список_записей | NEW]"
-
-#, fuzzy
-msgid "LIST [mask | list]"
-msgstr "LIST [#канал] [список_записей | NEW]"
-
-#, fuzzy
-msgid "LIST [nickname]"
-msgstr "CHECK ник"
-
-msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "LOGONNEWS {ADD|DEL|LIST} [текст|номер]"
-
-msgid "Language changed to English."
-msgstr "Язык сервисов изменен на Русский."
-
-#, fuzzy, c-format
-msgid "Language for %s changed to %s."
-msgstr "Наследником канала %s назначен пользователь %s."
-
-#, c-format
-msgid "Last memo to %s has been cancelled."
-msgstr "Последнее ваше сообщение адресату %s успешно отменено."
-
-#, fuzzy
-msgid "Last quit message"
-msgstr "Последнее quit-сообщение: %s"
-
-#, fuzzy
-msgid "Last seen"
-msgstr "Последний раз замечен...: %s"
-
-#, fuzzy
-msgid "Last seen address"
-msgstr "Последняя маска.........: %s"
-
-msgid "Last topic"
-msgstr ""
-
-#, fuzzy
-msgid "Last used"
-msgstr "Последний раз замечен...: %s"
-
-#, fuzzy
-msgid "Last usermask"
-msgstr "Последний раз замечен...: %s"
-
-msgid "Level"
-msgstr ""
-
-#, c-format
-msgid "Level for %s on channel %s changed to %d."
-msgstr "Уровень доступа к %s на канале %s изменен на %d."
-
-#, c-format
-msgid "Level for %s on channel %s changed to founder only."
-msgstr "Level for %s on channel %s changed to founder only."
-
-#, c-format
-msgid "Level must be between %d and %d inclusive."
-msgstr "Уровень должен быть числом между %d и %d включительно."
-
-msgid "Limit"
-msgstr ""
-
-#, fuzzy
-msgid "List all registered nicknames that match a given pattern"
-msgstr " LIST Список всех зарегистрированных ников по маске"
-
-#, fuzzy
-msgid "List channels you have access on"
-msgstr " ALIST Вывод списка каналов, на которых у вас есть доступ"
-
-#, c-format
-msgid "List for mode %c is full."
-msgstr ""
-
-#, fuzzy
-msgid "List loaded modules"
-msgstr " MODLIST Список загруженных модулей"
-
-#, fuzzy, c-format
-msgid "List of entries matching %s:"
-msgstr "Список ников в группе %s:"
-
-#, c-format
-msgid "List of nicknames in the group of %s:"
-msgstr "Список ников в группе %s:"
-
-msgid "List of nicknames in your group:"
-msgstr "Список ников в вашей группе:"
-
-#, fuzzy
-msgid "List your memos"
-msgstr " LIST Список ваших мемо-сообщений"
-
-#, fuzzy
-msgid ""
-"Lists all available bots on this network.\n"
-"Bots prefixed by a * are reserved for IRC Operators."
-msgstr ""
-"Синтаксис: BOTLIST\n"
-"\n"
-"Выведет список всех доступных для установки ботов."
-
-#, fuzzy
-msgid "Lists all channel records"
-msgstr " CHANLIST Список текущих активных каналов сети"
-
-#, fuzzy
-msgid ""
-"Lists all channels currently in use on the IRC network, whether they\n"
-"are registered or not.\n"
-" \n"
-"If pattern is given, lists only channels that match it. If a nickname\n"
-"is given, lists only the channels the user using it is on. If SECRET is\n"
-"specified, lists only channels matching pattern that have the +s or\n"
-"+p mode."
-msgstr ""
-"Синтаксис: CHANLIST [{маска | ник} [SECRET]]\n"
-"\n"
-"Выводит список всех активных (на данный момент) каналов сети, вне\n"
-"зависимости от того, зарегистрированы они или нет.\n"
-"\n"
-"В качестве параметра вы можете указать маску имени канала, что бы\n"
-"получить только конкретные, совпадающие записи. Если же вы укажите\n"
-"ник, будет выведен список всех каналов, на которых находится этот\n"
-"пользователь.\n"
-"Дополнительный параметр SECRET позволяет получить список каналов\n"
-"с режимами +s/+p, совпадающих с указанной символьной маской."
-
-msgid ""
-"Lists all channels you have access on.\n"
-" \n"
-"Channels that have the NOEXPIRE option set will be\n"
-"prefixed by an exclamation mark. The nickname parameter is\n"
-"limited to Services Operators"
-msgstr ""
-
-#, fuzzy
-msgid "Lists all nicknames in your group"
-msgstr "Список ников в вашей группе:"
-
-#, fuzzy
-msgid "Lists all registered channels matching the given pattern"
-msgstr " LIST Запрос списка всех зарегистрированных каналов"
-
-#, fuzzy
-msgid ""
-"Lists all registered channels matching the given pattern.\n"
-"Channels with the PRIVATE option set will only be\n"
-"displayed to Services Operators with the proper access.\n"
-"Channels with the NOEXPIRE option set will have\n"
-"a ! prefixed to the channel for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range, channel names\n"
-"are to be written without '#'.\n"
-" \n"
-"If the SUSPENDED or NOEXPIRE options are given, only channels\n"
-"which, respectively, are SUSPENDED or have the NOEXPIRE\n"
-"flag set will be displayed. If multiple options are given,\n"
-"all channels matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *anope*\n"
-" Lists all registered channels with anope in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered channels which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered channels within the given range (51-100)."
-msgstr ""
-"Синтаксис: LIST маска [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\n"
-"\n"
-"Показывает список всех зарегистрированных ников, которые совпадают\n"
-"с указанной в качестве основного параметра маской. Формат маски:\n"
-"ник!идент@хост допустимо использование подстановочных символов.\n"
-"Ники, у которых включена опция PRIVATE, будут показаны только\n"
-"Администраторам сервисов. Ники с включенным параметром NOEXPIRE\n"
-"будут показаны с префиксом !.\n"
-"\n"
-"В качестве дополнительных опций команды LIST вы можете указать\n"
-"FORBIDDEN, SUSPENDED, NOEXPIRE или UNCONFIRMED. Это позволит вам\n"
-"получить список ников, отвечающих определенным критериям, таким как:\n"
-"FORBIDDEN - ники, запрещенные к использованию, SUSPENDED - ники,\n"
-"\"замороженные\" до поры до времени, UNCONFIRMED - ники, регистрация\n"
-"которых все еще не подтверждена, и NOEXPIRE - ники, находящиеся в\n"
-"режиме \"не-истечения\". Если указаны все четыре опции, то все 4 типа\n"
-"ников будут перечислены в списке.\n"
-"\n"
-"Примеры:\n"
-"\n"
-" LIST *!joeuser@foo.com\n"
-" покажет все ники, маска которых совпадает с joeuser@foo.com\n"
-" LIST *Bot*!*@*\n"
-" покажет все зарегистрированные ники, которые содержат слово\n"
-" Bot (вне зависимости от регистра).\n"
-" LIST * NOEXPIRE\n"
-" Покажет все зарегистрированные ники у которых включена опция\n"
-" NOEXPIRE."
-
-#, fuzzy
-msgid ""
-"Lists all registered nicknames which match the given\n"
-"pattern, in nick!user@host format. Nicks with the PRIVATE\n"
-"option set will only be displayed to Services Operators with the\n"
-"proper access. Nicks with the NOEXPIRE option set will have\n"
-"a ! prefixed to the nickname for Services Operators to see.\n"
-" \n"
-"Note that a preceding '#' specifies a range.\n"
-" \n"
-"If the SUSPENDED, UNCONFIRMED or NOEXPIRE options are given, only\n"
-"nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n"
-"NOEXPIRE flag set will be displayed. If multiple options are\n"
-"given, all nicks matching at least one option will be displayed.\n"
-"Note that these options are limited to Services Operators.\n"
-" \n"
-"Examples:\n"
-" \n"
-" LIST *!joeuser@foo.com\n"
-" Lists all registered nicks owned by joeuser@foo.com.\n"
-" \n"
-" LIST *Bot*!*@*\n"
-" Lists all registered nicks with Bot in their\n"
-" names (case insensitive).\n"
-" \n"
-" LIST * NOEXPIRE\n"
-" Lists all registered nicks which have been set to not expire.\n"
-" \n"
-" LIST #51-100\n"
-" Lists all registered nicks within the given range (51-100)."
-msgstr ""
-"Синтаксис: LIST маска [FORBIDDEN] [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\n"
-"\n"
-"Показывает список всех зарегистрированных ников, которые совпадают\n"
-"с указанной в качестве основного параметра маской. Формат маски:\n"
-"ник!идент@хост допустимо использование подстановочных символов.\n"
-"Ники, у которых включена опция PRIVATE, будут показаны только\n"
-"Администраторам сервисов. Ники с включенным параметром NOEXPIRE\n"
-"будут показаны с префиксом !.\n"
-"\n"
-"В качестве дополнительных опций команды LIST вы можете указать\n"
-"FORBIDDEN, SUSPENDED, NOEXPIRE или UNCONFIRMED. Это позволит вам\n"
-"получить список ников, отвечающих определенным критериям, таким как:\n"
-"FORBIDDEN - ники, запрещенные к использованию, SUSPENDED - ники,\n"
-"\"замороженные\" до поры до времени, UNCONFIRMED - ники, регистрация\n"
-"которых все еще не подтверждена, и NOEXPIRE - ники, находящиеся в\n"
-"режиме \"не-истечения\". Если указаны все четыре опции, то все 4 типа\n"
-"ников будут перечислены в списке.\n"
-"\n"
-"Примеры:\n"
-"\n"
-" LIST *!joeuser@foo.com\n"
-" покажет все ники, маска которых совпадает с joeuser@foo.com\n"
-" LIST *Bot*!*@*\n"
-" покажет все зарегистрированные ники, которые содержат слово\n"
-" Bot (вне зависимости от регистра).\n"
-" LIST * NOEXPIRE\n"
-" Покажет все зарегистрированные ники у которых включена опция\n"
-" NOEXPIRE."
-
-#, fuzzy
-msgid "Lists all user records"
-msgstr " USERLIST Список текущих пользователей сети"
-
-#, fuzzy
-msgid ""
-"Lists all users currently online on the IRC network, whether their\n"
-"nick is registered or not.\n"
-" \n"
-"If pattern is given, lists only users that match it (it must be in\n"
-"the format nick!user@host[#realname]). If channel is given, lists\n"
-"only users that are on the given channel. If INVISIBLE is specified, only "
-"users\n"
-"with the +i flag will be listed."
-msgstr ""
-"Синтаксис: USERLIST [{хостмаска | #канал} [INVISIBLE]]\n"
-"\n"
-"Выводит список всех пользователей, находящихся в данный момент в сети.\n"
-"Зарегистрирован их ник или нет - роли не играет.\n"
-"\n"
-"В качестве параметра, вы можете указать пользовательскую хостмаску\n"
-"вида ник!идент@хост - это позволит получить только конкретные,\n"
-"совпадающие с маской записи. Если же вы укажите #канал, будет\n"
-"выведен список всех посетителей указанного канала.\n"
-"Дополнительный параметр INVISIBLE позволяет получить список ников\n"
-"с режимом +i, данные которых совпадают с указанной в качестве второго\n"
-"параметра хостмаской."
-
-#, fuzzy
-msgid ""
-"Lists any memos you currently have. With NEW, lists only\n"
-"new (unread) memos. Unread memos are marked with a \"*\"\n"
-"to the left of the memo number. You can also specify a list\n"
-"of numbers, as in the example below:\n"
-" LIST 2-5,7-9\n"
-" Lists memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Синтаксис: LIST [#канал] [список_записей | NEW]\n"
-"\n"
-"Выводит текущий список сообщений. С параметром NEW, покажет только\n"
-"новые (непрочитанные) сообщения, они будут помечены значком \"*\"\n"
-"слева от номера сообщения.\n"
-"Помимо этого, вы можете указать список записей или номер записи,\n"
-"например:\n"
-"\n"
-" LIST 2-5,7-9\n"
-" покажет сообщения с 2-го по 5-ое и с 7-го по 9-ое."
-
-#, fuzzy
-msgid "Lists available bots"
-msgstr "BOTLIST Список доступных для установки ботов"
-
-#, fuzzy
-msgid "Lists currently loaded modules."
-msgstr " MODLIST Список загруженных модулей"
-
-#, fuzzy
-msgid "Lists information about the specified registered channel"
-msgstr " INFO Запрос информации об указанном канале"
-
-#, fuzzy
-msgid ""
-"Lists information about the specified registered channel,\n"
-"including its founder, time of registration, last\n"
-"time used, and description. If the user issuing the\n"
-"command has the appropriate access for it, then the\n"
-"successor, last topic set, settings and expiration\n"
-"time will also be displayed when applicable."
-msgstr ""
-"Синтаксис: INFO #канал\n"
-"\n"
-"Позволяет получить подробную информацию о зарегистрированом канале,\n"
-"в частности такую как: ник владельца, время регистрации канала, дату\n"
-"его последнего использования и описание. С параметром ALL будут\n"
-"так же показаны заблокированные режимы, опции канала и его наследник.\n"
-"Примечание: по-умолчанию, использовать команду с параметром ALL\n"
-"может только владелец канала."
-
-#, fuzzy
-msgid "Load a module"
-msgstr " MODLOAD Загрузить модуль"
-
-msgid "Local channels cannot be registered."
-msgstr "Локальные каналы не могут быть зарегистрированы."
-
-#, fuzzy, c-format
-msgid "Log list for %s:"
-msgstr "Список доступа для %s:"
-
-#, c-format
-msgid "Logging changed for command %s on %s, now using log method %s%s%s."
-msgstr ""
-
-#, c-format
-msgid "Logging for command %s on %s with log method %s%s%s has been removed."
-msgstr ""
-
-#, c-format
-msgid "Logging is now active for command %s on %s, using log method %s%s%s."
-msgstr ""
-
-#, c-format
-msgid "Login to %s"
-msgstr ""
-
-#, c-format
-msgid "Logon news item #%d deleted."
-msgstr "Новость под номером #%d удалена."
-
-#, fuzzy, c-format
-msgid "Logon news item #%s not found!"
-msgstr "Новость под номером #%d не обнаружена."
-
-msgid "Logon news items:"
-msgstr "Текущие список новостей:"
-
-#, fuzzy, c-format
-msgid "Logout from %s"
-msgstr "Список доступа для %s:"
-
-#, c-format
-msgid ""
-"Logs you in to %s so you gain Services Operator privileges.\n"
-"This command may be unnecessary if your oper block is\n"
-"configured without a password."
-msgstr ""
-
-#, c-format
-msgid ""
-"Logs you out from %s so you lose Services Operator privileges.\n"
-"This command is only useful if your oper block is configured\n"
-"with a password."
-msgstr ""
-
-#, c-format
-msgid "Looking for yourself, eh %s?"
-msgstr ""
-
-#, c-format
-msgid ""
-"Mainly controls mode locks and mode access (which is different from channel "
-"access)\n"
-"on a channel.\n"
-" \n"
-"The %s LOCK command allows you to add, delete, and view mode locks on a "
-"channel.\n"
-"If a mode is locked on or off, services will not allow that mode to be "
-"changed. The SET\n"
-"command will clear all existing mode locks and set the new one given, while "
-"ADD and DEL\n"
-"modify the existing mode lock.\n"
-"Example:\n"
-" MODE #channel LOCK ADD +bmnt *!*@*aol*\n"
-" \n"
-"The %s SET command allows you to set modes through services. Wildcards * "
-"and ? may\n"
-"be given as parameters for list and status modes.\n"
-"Example:\n"
-" MODE #channel SET +v *\n"
-" Sets voice status to all users in the channel.\n"
-" \n"
-" MODE #channel SET -b ~c:*\n"
-" Clears all extended bans that start with ~c:\n"
-" \n"
-"The %s CLEAR command is an easy way to clear modes on a channel. what may "
-"be\n"
-"any mode name. Examples include bans, excepts, inviteoverrides, ops, "
-"halfops, and voices. If what\n"
-"is not given then all basic modes are removed."
-msgstr ""
-
-#, fuzzy
-msgid "Maintain the AutoKick list"
-msgstr " AKICK Управление списком автокиков канала"
-
-#, fuzzy
-msgid "Maintains network bot list"
-msgstr "BOT Управление сервисными ботами"
-
-#, c-format
-msgid ""
-"Maintains the %s list for a channel. Users who match an access entry\n"
-"on the %s list receive the following privileges:\n"
-" "
-msgstr ""
-
-#, c-format
-msgid ""
-"Maintains the AutoKick list for a channel. If a user\n"
-"on the AutoKick list attempts to join the channel,\n"
-"%s will ban that user from the channel, then kick\n"
-"the user.\n"
-" \n"
-"The AKICK ADD command adds the given nick or usermask\n"
-"to the AutoKick list. If a reason is given with\n"
-"the command, that reason will be used when the user is\n"
-"kicked; if not, the default reason is \"User has been\n"
-"banned from the channel\".\n"
-"When akicking a registered nick the %s account\n"
-"will be added to the akick list instead of the mask.\n"
-"All users within that nickgroup will then be akicked.\n"
-msgstr ""
-
-#, c-format
-msgid ""
-"Maintains the access list for a channel. The access\n"
-"list specifies which users are allowed chanop status or\n"
-"access to %s commands on the channel. Different\n"
-"user levels allow for access to different subsets of\n"
-"privileges. Any registered user not on the access list has\n"
-"a user level of 0, and any unregistered user has a user level\n"
-"of -1."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Maintains the bad words list for a channel. The bad\n"
-"words list determines which words are to be kicked\n"
-"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
-" \n"
-"The ADD command adds the given word to the\n"
-"bad words list. If SINGLE is specified, a kick will be\n"
-"done only if a user says the entire word. If START is\n"
-"specified, a kick will be done if a user says a word\n"
-"that starts with word. If END is specified, a kick\n"
-"will be done if a user says a word that ends with\n"
-"word. If you don't specify anything, a kick will\n"
-"be issued every time word is said by a user.\n"
-" \n"
-msgstr ""
-"Синтаксис: BADWORDS #канал ADD слово [SINGLE | START | END]\n"
-" BADWORDS #канал DEL {слово | номер_записи | список_записей}\n"
-" BADWORDS #канал LIST [маска | список_записей]\n"
-" BADWORDS #канал CLEAR\n"
-"\n"
-"Данная команда позволяет модифицировать список \"плохих\" слов канала.\n"
-"Этот список определяет, за использование каких слов пользователь\n"
-"будет кикнут ботом, при условии, конечно, что данная возможность\n"
-"активирована.\n"
-"Для более подробной информации по активации данного режима смотрите\n"
-"%s%s HELP KICK BADWORDS.\n"
-"\n"
-"Команда BADWORDS ADD добавляет новое слово в список \"плохих\" слов.\n"
-"Вы можете указать дополнительные условия обработки для добавляемого\n"
-"слова, например: опциональный параметр SINGLE заставит бота\n"
-"учитывать только факт полного употребления данного слова, параметр\n"
-"START заставит бота учитывать факт совпадения по маске \"слово*\"\n"
-"(то есть, совпадение какой-либо START-записи из списка с началом\n"
-"сказанного слова), ну и последний параметр END будет срабатывать\n"
-"при употреблении \"*слова\". Если вы не укажете ни один из этих\n"
-"параметров для добавляемого слова, будет использоваться совпадение\n"
-"по \"*слову*\".\n"
-"Примеры:\n"
-"\n"
-"BADWORDS #chuvaki ADD пес\n"
-"-> добавит слово \"пес\" в список плохих слов и заставит бота кикать\n"
-" не только за употребление самого этого слова, но и любых его\n"
-" словоформ, содержащих в себе оригин (например: пес, песок и т.д.)\n"
-"\n"
-"BADWORDS #chuvaki ADD пес SINGLE\n"
-"-> добавит слово \"пес\" в список плохих слов и заставит бота кикать\n"
-" только за употребление самого этого слова, и никак иначе.\n"
-"\n"
-"Команда BADWORDS DEL удаляет указанное слово из списка плохих слов.\n"
-"В качестве параметра вы можете указать не только конкретную запись,\n"
-"но и номер записи или список записей (см. примеры использования\n"
-"команды LIST ниже).\n"
-"\n"
-"Команда BADWORDS LIST покажет текущий список плохих слов.\n"
-"В качестве дополнительного параметра, вы можете указать символьную\n"
-"маску, что позволит вам получить список с конкре"
-
-#, fuzzy
-msgid "Maintains the bad words list"
-msgstr "BADWORDS Управление списком \"плохих\" слов"
-
-#, fuzzy
-msgid "Makes the bot do the equivalent of a \"/me\" command"
-msgstr "ACT Выполнить действие от лица бота на указанном канале"
-
-#, fuzzy
-msgid ""
-"Makes the bot do the equivalent of a \"/me\" command\n"
-"on the specified channel using the specified text."
-msgstr ""
-"Синтаксис: ACT #канал текст\n"
-"\n"
-"Заставляет бота выполнить команду, эквивалентную команде \"/me\"\n"
-"в IRC-клиенте mIRC. Вы должны указать оба параметра: текст действия\n"
-"и #канал."
-
-#, fuzzy
-msgid "Makes the bot say the specified text on the specified channel"
-msgstr "SAY Послать на указанный канал текст от лица бота"
-
-#, fuzzy
-msgid "Makes the bot say the specified text on the specified channel."
-msgstr "SAY Послать на указанный канал текст от лица бота"
-
-#, fuzzy
-msgid ""
-"Makes the given message the greet of the nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that the user has the necessary\n"
-"access on it."
-msgstr ""
-"Синтаксис: SASET ник GREET текст\n"
-"\n"
-"Позволяет назначить приветственное сообщение, которое сервисный\n"
-"бот будет говорить каждый раз, когда ник зайдет на канал. Учтите,\n"
-"что для отображения приветсвия, на канале должна быть активирована\n"
-"опция GREET и ник должен иметь соответствующий уровень доступа."
-
-#, fuzzy
-msgid ""
-"Makes the given message the greet of your nickname, that\n"
-"will be displayed when joining a channel that has GREET\n"
-"option enabled, provided that you have the necessary\n"
-"access on it."
-msgstr ""
-"Синтаксис: SET GREET сообщение\n"
-"\n"
-"Позволяет назначить приветственное сообщение, которое сервисный\n"
-"бот будет говорить каждый раз, когда вы заходите на канал. Учтите,\n"
-"что для отображения приветствия, на канале должна быть активирована\n"
-"опция GREET и вы должны иметь соответствующий уровень доступа."
-
-#, fuzzy
-msgid "Manage DNS zones for this network"
-msgstr "Возможность удаления email-адреса в вашей IRC-сети недоступна."
-
-#, fuzzy
-msgid "Manage the channel's entry messages"
-msgstr " PERSIST Set the channel as permanent"
-
-#, fuzzy
-msgid "Manage the memo ignore list"
-msgstr " IGNORE Управление игнор-списком сервисов"
-
-#, fuzzy
-msgid "Manage your auto join list"
-msgstr " AKICK Управление списком автокиков канала"
-
-#, fuzzy, c-format
-msgid "Manipulate the %s list"
-msgstr " AKILL Управление списком AKILL'ов"
-
-#, fuzzy
-msgid "Manipulate the AKILL list"
-msgstr " AKILL Управление списком AKILL'ов"
-
-#, fuzzy
-msgid "Manipulate the DefCon system"
-msgstr " DEFCON Управление системой DefCon (защитных контрмер)"
-
-#, fuzzy
-msgid "Manipulate the topic of the specified channel"
-msgstr " TOPIC Установка топика на канале посредством сервисов"
-
-msgid "Mask"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "Маска вида %s уже присутствует в вашем списке доступа."
-
-msgid "Mask must be in the form user@host."
-msgstr ""
-
-#, fuzzy
-msgid "Masks and unregistered users may not be on access lists."
-msgstr "Маска вида %s уже присутствует в вашем списке доступа."
-
-#, fuzzy
-msgid "Matches and returns all users that registered using given email"
-msgstr " GETEMAIL Запрос списка всех ников с указанным email"
-
-#, fuzzy, c-format
-msgid "Matches for %s:"
-msgstr "Блокировка режимов........: %s"
-
-#, c-format
-msgid "Maximum users: %d (%s)"
-msgstr "Зафиксированный максимум пользователей: %d (на %s)"
-
-#, fuzzy, c-format
-msgid "Memo %d from %s (%s)."
-msgstr "Блокировка режимов........: %s"
-
-#, c-format
-msgid "Memo %d has been deleted."
-msgstr "Сообщение под номером %d было удалено."
-
-#, fuzzy
-msgid "Memo ignore list is empty."
-msgstr "Список игнорируемых ников пуст."
-
-#, c-format
-msgid "Memo limit disabled for %s."
-msgstr "Лимит сообщений для %s отключен."
-
-#, c-format
-msgid "Memo limit for %s set to %d."
-msgstr "Лимит собщений для %s установлен на %d."
-
-#, c-format
-msgid "Memo limit for %s set to 0."
-msgstr "Лимит сообщений для %s установлен на 0."
-
-#, c-format
-msgid "Memo sent to %s."
-msgstr "Мемо-сообщение для %s успешно отправлено."
-
-#, fuzzy, c-format
-msgid "Memos for %s:"
-msgstr "Блокировка режимов........: %s"
-
-#, fuzzy
-msgid "Message"
-msgstr "GLOBAL сообщение"
-
-msgid "Message mode"
-msgstr "Режим приватных сообщений"
-
-msgid "Method"
-msgstr ""
-
-#, c-format
-msgid "Missing parameter for mode %c."
-msgstr ""
-
-msgid "Mode"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Mode %s is a virtual mode and can't be cleared."
-msgstr "Указанный ник %s содержит недопустимые символы."
-
-#, fuzzy, c-format
-msgid "Mode %s is not a status or list mode."
-msgstr "Ник %s в списке игнорируемых не обнаружен."
-
-#, fuzzy
-msgid "Mode lock"
-msgstr "Блокировка режимов........: %s"
-
-#, fuzzy, c-format
-msgid "Mode locks for %s:"
-msgstr "Блокировка режимов........: %s"
-
-msgid "Modes"
-msgstr ""
-
-#, c-format
-msgid "Modes cleared on %s and the channel destroyed."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
-msgstr ""
-"Синтаксис: ACCESS ADD маска\n"
-" ACCESS DEL маска\n"
-" ACCESS LIST\n"
-"\n"
-"Позволяет просматривать/изменять список масок доступа на ваш ник.\n"
-"Имеется ввиду список хостмасок вида идент@хост, с которых %s\n"
-"позволит использовать ваш ник даже без и дентификации к нему.\n"
-"В противном случае, чтобы использовать ник с хостмаски которая не\n"
-"присутствует в списоке доступа, вам необходимо будет использовать\n"
-"команду IDENTIFY для идентификации на %s.\n"
-"\n"
-"Примеры:\n"
-"\n"
-" ACCESS ADD anyone@*.set.ru\n"
-" позволяет использовать ник всем, кто имеет идент anyone\n"
-" и чей хост попадает под маску *.set.ru.\n"
-" ACCESS DEL anyone@*.set.ru\n"
-" антоним предыдущей команды - удаляет маску из списка.\n"
-" ACCESS LIST\n"
-" выводит текущий список \"доверенных\" хостмасок."
-
-msgid ""
-"Modifies or displays the certificate list for your nick.\n"
-"If you connect to IRC and provide a client certificate with a\n"
-"matching fingerprint in the cert list, you will be\n"
-"automatically identified to services. Services Operators\n"
-"may provide a nick to modify other users' certificate lists.\n"
-" \n"
-msgstr ""
-
-#, fuzzy
-msgid "Modify the Services ignore list"
-msgstr " IGNORE Управление игнор-списком сервисов"
-
-#, fuzzy, c-format
-msgid "Modify the list of %s users"
-msgstr " AOP Управление списком AOP'ов канала"
-
-#, fuzzy
-msgid "Modify the list of authorized addresses"
-msgstr " ACCESS Управление ACCESS-списком ника (списком хостмасок)"
-
-#, fuzzy
-msgid "Modify the list of privileged users"
-msgstr " ACCESS Управление ACCESS-списком привилегий канала"
-
-#, fuzzy
-msgid "Modify the nickname client certificate list"
-msgstr " IGNORE Управление игнор-списком сервисов"
-
-#, fuzzy
-msgid "Modify the session-limit exception list"
-msgstr " EXCEPTION Управление списком исключений из лимита сессий"
-
-#, c-format
-msgid "Module %s is already loaded."
-msgstr "Module %s is already loaded."
-
-#, c-format
-msgid "Module %s isn't loaded."
-msgstr "Module %s isn't loaded."
-
-#, fuzzy, c-format
-msgid "Module %s loaded."
-msgstr "Модуль %s успешно загружен."
-
-#, fuzzy, c-format
-msgid "Module %s reloaded."
-msgstr "Модуль %s успешно загружен."
-
-#, fuzzy, c-format
-msgid "Module %s unloaded."
-msgstr "Модуль %s успешно выгружен."
-
-#, fuzzy
-msgid "Module Name"
-msgstr "Модуль %s успешно загружен."
-
-msgid "Module settings:"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Module: %s Version: %s Author: %s Loaded: %s"
-msgstr "Модуль: %s Версия: %s Автор: %s Загружен: %s"
-
-#, c-format
-msgid "Module: %s [%s] [%s]"
-msgstr "Модуль: %s [%s] [%s]"
-
-msgid "Name"
-msgstr ""
-
-msgid "Name Type"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Network stats for %s:"
-msgstr "Список доступа для %s:"
-
-msgid "Never"
-msgstr ""
-
-#, fuzzy
-msgid "Nick"
-msgstr "INFO ник"
-
-#, fuzzy, c-format
-msgid "Nick %s has been confirmed."
-msgstr "Ник %s успешно удален из базы данных сервисов."
-
-#, fuzzy, c-format
-msgid "Nick %s is already an operator."
-msgstr "Ник %s уже зарегистрирован!"
-
-#, fuzzy, c-format
-msgid "Nick %s is already confirmed."
-msgstr "Ник %s уже зарегистрирован!"
-
-#, c-format
-msgid "Nick %s is an illegal nickname and cannot be used."
-msgstr "Указанный ник %s содержит недопустимые символы."
-
-#, c-format
-msgid "Nick %s is currently in use."
-msgstr "Ник %s на данный момент используется кем-то другим."
-
-#, fuzzy, c-format
-msgid "Nick %s is forbidden by %s: %s"
-msgstr "Ник %s на данный момент используется кем-то другим."
-
-#, fuzzy, c-format
-msgid "Nick %s is forbidden."
-msgstr "На данный момент, ник %s сервисами не удерживается."
-
-#, fuzzy, c-format
-msgid "Nick %s is not a Services Operator."
-msgstr "%s is a services operator of type %s."
-
-#, c-format
-msgid "Nick %s is part of this Network's Services."
-msgstr "Ник %s является ником одного из сервисных псевдоклиентов данной сети."
-
-#, fuzzy, c-format
-msgid "Nick %s isn't currently in use."
-msgstr "Ник %s на данный момент используется кем-то другим."
-
-#, fuzzy, c-format
-msgid "Nick %s isn't registered."
-msgstr "Ник %s успешно зарегистрирован."
-
-#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "Ник %s был усечен до %d символов."
-
-#, c-format
-msgid "Nick %s will expire."
-msgstr "C этого момента ник %s снова в режиме истечения."
-
-#, c-format
-msgid "Nick %s will not expire."
-msgstr "С этого момента регистрация ника %s никогда не истечет."
-
-#, c-format
-msgid "Nick %s doesn't have a memo from you."
-msgstr "Ник %s не получал от вас никаких сообщений."
-
-#, c-format
-msgid "Nick %s has been logged out."
-msgstr "Ник %s успешно деидентифицирован."
-
-#, c-format
-msgid "Nick %s has been ungrouped from %s."
-msgstr "Nick %s has been ungrouped from %s."
-
-#, fuzzy, c-format
-msgid "Nick %s is currently suspended."
-msgstr "С этого момента ник %s находится режиме саспенда."
-
-#, fuzzy, c-format
-msgid "Nick %s is not in your group."
-msgstr "The nick %s is not in your group."
-
-#, fuzzy, c-format
-msgid "Nick %s is not suspended."
-msgstr "С этого момента ник %s находится режиме саспенда."
-
-#, c-format
-msgid "Nick %s is now released."
-msgstr "Режим саспенда с ника %s успешно снят."
-
-#, c-format
-msgid "Nick %s is now suspended."
-msgstr "С этого момента ник %s находится режиме саспенда."
-
-#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr ""
-
-#, c-format
-msgid "Nickname %s has been dropped."
-msgstr "Ник %s успешно удален из базы данных сервисов."
-
-#, fuzzy, c-format
-msgid "Nickname %s is already registered!"
-msgstr "Канал %s уже зарегистрирован!"
-
-#, fuzzy, c-format
-msgid "Nickname %s may not be registered."
-msgstr "Канал %s не может быть зарегистрирован."
-
-#, fuzzy, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr ""
-"Ник %s успешно зарегистрирован, в ACCESS-список добавлена хостмаска: %s"
-
-#, fuzzy, c-format
-msgid "Nickname %s registered."
-msgstr "Ник %s успешно зарегистрирован."
-
-#, fuzzy
-msgid "No auto-op"
-msgstr "Автостатус"
-
-msgid "No bot"
-msgstr "Без ботов"
-
-#, fuzzy
-msgid "No expire"
-msgstr "никогда не истечет"
-
-#, c-format
-msgid "No help available for %s."
-msgstr "Справочная информация по %s отсутствует."
-
-#, fuzzy, c-format
-msgid "No information about module %s is available."
-msgstr "Информация о модуле %s недоступна. "
-
-#, fuzzy, c-format
-msgid "No limit is set on %s."
-msgstr "Лимит собщений для %s установлен на %d."
-
-msgid "No logon news items to delete!"
-msgstr "Список новостей пуст, удалять нечего."
-
-#, fuzzy, c-format
-msgid "No matches for %s found."
-msgstr "Ники с email-адресом %s не обнаружены."
-
-#, fuzzy, c-format
-msgid "No matching entries on %s %s list."
-msgstr "Совпадающих записей в списке AOP'ов канала %s не обнаружено."
-
-#, c-format
-msgid "No matching entries on %s access list."
-msgstr "Совпадающих записей в списке доступа канала %s не обнаружено."
-
-#, c-format
-msgid "No matching entries on %s autokick list."
-msgstr "Совпадающих значений в списке автокиков канала %s не обнаружено."
-
-#, c-format
-msgid "No matching entries on %s bad words list."
-msgstr "В списке плохих слов канала %s совпадающих записей не обнаружено."
-
-msgid "No matching entries on session-limit exception list."
-msgstr ""
-"Совпадающих значений в списке исключений из лимита сессий не обнаружено."
-
-#, fuzzy, c-format
-msgid "No matching entries on the %s list."
-msgstr "Совпадающих записей в списке AOP'ов канала %s не обнаружено."
-
-msgid "No matching entries on the AKILL list."
-msgstr "Совпадающих записей не обнаружено."
-
-msgid "No memo was cancelable."
-msgstr "Нет сообщений доступных для отмены."
-
-msgid "No memos to display."
-msgstr ""
-
-#, fuzzy
-msgid "No modules currently loaded matching that criteria."
-msgstr "Список модулей пуст."
-
-msgid "No one is using your nick, and services are not holding it."
-msgstr ""
-
-msgid "No oper block for your nick."
-msgstr ""
-
-msgid "No oper news items to delete!"
-msgstr "Список опер-новостей пуст, удалять нечего."
-
-msgid "No random news items to delete!"
-msgstr "Список случайных новостей пуст, удалять нечего."
-
-msgid "No records to display."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "No registrations matching %s were found."
-msgstr "* Запрет на регистрацию ников."
-
-#, c-format
-msgid "No request for nick %s found."
-msgstr ""
-
-msgid "No signed kick when SIGNKICK LEVEL is used"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "No stats for %s."
-msgstr "Список доступа для %s:"
-
-#, fuzzy, c-format
-msgid "No such info \"%s\" on %s."
-msgstr "%s has been invited to %s."
-
-#, fuzzy, c-format
-msgid "No users on %s match %s."
-msgstr "Режимы пользователя %s изменены."
-
-#, fuzzy, c-format
-msgid "No-bot mode is now off on channel %s."
-msgstr "Режим без-бота для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "No-bot mode is now on on channel %s."
-msgstr "Режим без-бота для канала %s активирован."
-
-#, c-format
-msgid "Non-status modes cleared on %s."
-msgstr ""
-
-msgid "None"
-msgstr "отсутствуют"
-
-#, c-format
-msgid ""
-"Note, however, if the successor already has too many\n"
-"channels registered (%d), they will not be able to\n"
-"become the new founder and it will be as if the\n"
-"channel had no successor set."
-msgstr ""
-
-msgid "Nothing to do."
-msgstr ""
-
-msgid "Number"
-msgstr ""
-
-msgid "OPERNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "OPERNEWS {ADD|DEL|LIST} [текст|номер]"
-
-#, fuzzy
-msgid "Online from"
-msgstr "Сейчас онлайн, c маской.: %s"
-
-#, c-format
-msgid ""
-"Oper %s is configured in the configuration file(s) and can not be removed by "
-"this command."
-msgstr ""
-
-msgid "Oper Info"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Oper info list for %s is empty."
-msgstr "Список доступа для %s пуст."
-
-#, c-format
-msgid "Oper news item #%d deleted."
-msgstr "Новость под номером #%d удалена."
-
-#, fuzzy, c-format
-msgid "Oper news item #%s not found!"
-msgstr "Новость под номером #%d не обнаружена."
-
-msgid "Oper news items:"
-msgstr "Список новостей для IRC-операторов:"
-
-#, c-format
-msgid "Oper privileges removed from %s (%s)."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Oper type %s has not been configured."
-msgstr "Ник %s успешно удален из базы данных сервисов."
-
-#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "OLINE-флаги %s успешно установлены для сессий пользователя %s"
-
-#, fuzzy, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "OLINE-флаги %s успешно установлены для сессий пользователя %s"
-
-#, c-format
-msgid "Opertype %s has no allowed commands."
-msgstr ""
-
-#, c-format
-msgid "Opertype %s has no allowed privileges."
-msgstr ""
-
-#, c-format
-msgid "Opertype %s receives modes %s once identified."
-msgstr ""
-
-msgid "Ops protection"
-msgstr "Не кикать операторов"
-
-#, fuzzy
-msgid "Options"
-msgstr "Опции...........: %s"
-
-#, fuzzy
-msgid "POOL server.name"
-msgstr "NOOP {SET|REVOKE} сервер"
-
-msgid "Param"
-msgstr ""
-
-msgid "Password accepted - you are now recognized."
-msgstr "Пароль принят - вы признаны как владелец ника."
-
-#, fuzzy
-msgid "Password accepted."
-msgstr "Вы указали неверный пароль."
-
-msgid "Password authentication required for that command."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Password for %s changed to %s."
-msgstr "Наследником канала %s назначен пользователь %s."
-
-#, fuzzy, c-format
-msgid "Password for %s changed."
-msgstr "Пароль для ника %s был выслан на его email-адрес."
-
-#, c-format
-msgid "Password for %s is %s."
-msgstr "Пароль для ника %s - %s"
-
-#, fuzzy
-msgid "Password incorrect."
-msgstr "Вы указали неверный пароль."
-
-#, c-format
-msgid "Password reset email for %s has been sent."
-msgstr "Password reset email for %s has been sent."
-
-msgid "Peace"
-msgstr "Спокойствие"
-
-#, fuzzy, c-format
-msgid "Peace option for %s is now off."
-msgstr "Режим спокойствия для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Peace option for %s is now on."
-msgstr "Режим спокойствия для канала %s активирован."
-
-#, fuzzy
-msgid "Persistent"
-msgstr "Persistant"
-
-msgid "Please contact an Operator to get a vHost assigned to this nick."
-msgstr ""
-
-msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab "
-"characters."
-msgstr ""
-
-#, fuzzy
-msgid "Please use a valid server name when juping."
-msgstr ""
-"В качестве основного параметра вы должны указать реальное имя серевера "
-
-msgid "Please use the symbol of # when attempting to register."
-msgstr ""
-
-#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Пожалуйста, подождите %d секунд и повторите запрос."
-
-#, fuzzy, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr ""
-"Пожалуйста, подождите %d секунд перед повторным использованием команды SEND."
-
-#, fuzzy, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr ""
-"Пожалуйста, подождите %d секунд перед повторным использованием команды SEND."
-
-#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "Подождите %d секунд перед повторным использованием команды GROUP."
-
-#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "Подождите %d секунд перед повторным использованием команды REGISTER."
-
-#, c-format
-msgid "Pooled %s."
-msgstr ""
-
-msgid "Pooled/Active"
-msgstr ""
-
-msgid "Pooled/Not Active"
-msgstr ""
-
-msgid "Prevent a bot from being assigned by non IRC operators"
-msgstr ""
-
-#, fuzzy
-msgid "Prevent a bot from being assigned to a channel"
-msgstr ""
-" SUSPEND Приостановка работы канала, с сохранением всех данных\n"
-" и настроек канала"
-
-#, fuzzy
-msgid "Prevent a channel from being used preserving channel data and settings"
-msgstr ""
-" SUSPEND Приостановка работы канала, с сохранением всех данных\n"
-" и настроек канала"
-
-#, fuzzy
-msgid "Prevent the channel from expiring"
-msgstr " NOEXPIRE Prevent the channel from expiring"
-
-#, fuzzy
-msgid "Prevent the nickname from appearing in the LIST command"
-msgstr " PRIVATE скрытие ника в списке ников по /msg %s LIST"
-
-#, fuzzy
-msgid "Prevent the nickname from expiring"
-msgstr " NOEXPIRE установка на ник т.н. режима 'не-истечения'"
-
-msgid "Prevents users being kicked by Services"
-msgstr ""
-
-msgid "Private"
-msgstr "Приватность"
-
-#, fuzzy, c-format
-msgid "Private mode of bot %s is now off."
-msgstr "Бот под ником %s успешно помечен как приватный."
-
-#, fuzzy, c-format
-msgid "Private mode of bot %s is now on."
-msgstr "Бот под ником %s успешно помечен как приватный."
-
-#, fuzzy, c-format
-msgid "Private option for %s is now off."
-msgstr "Режим приватности канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Private option for %s is now on."
-msgstr "Режим приватности канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Private option is now off for %s."
-msgstr "Режим приватности для %s активирован."
-
-#, fuzzy, c-format
-msgid "Private option is now on for %s."
-msgstr "Режим приватности для %s активирован."
-
-#, c-format
-msgid "Privilege %s added to %s on %s, new flags are +%s"
-msgstr ""
-
-#, c-format
-msgid "Privilege %s removed from %s on %s, new flags are +%s"
-msgstr ""
-
-msgid "Protection"
-msgstr "Защита"
-
-#, fuzzy, c-format
-msgid "Protection is now off for %s."
-msgstr "Защита ника %s активирована, лимит времени на ввод пароля: 60 секунд."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s, with a reduced delay."
-msgstr "Защита ника %s активирована,лимит времени на ввод пароля: 20 секунд."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s, with no delay."
-msgstr "Защита ника %s активирована, лимит времени на ввод пароля: 0 секунд."
-
-#, fuzzy, c-format
-msgid "Protection is now on for %s."
-msgstr "Защита ника %s активирована, лимит времени на ввод пароля: 60 секунд."
-
-#, fuzzy
-msgid ""
-"Puts an AKILL for every nick on the specified channel. It\n"
-"uses the entire real ident@host for every nick, and\n"
-"then enforces the AKILL."
-msgstr ""
-"Синтаксис: CHANKILL [+срок_истечения] #канал причина\n"
-"Добавляет в AKILL-список всех пользователей указанного канала с\n"
-"указанной причиной на указанный промежуток времени. В качестве маски\n"
-"AKILL'ов будут использованы маски посетителей канала вида идент@хост."
-
-#, fuzzy
-msgid "Quick protection"
-msgstr "Не кикать войсов"
-
-msgid "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
-msgstr "RANDOMNEWS {ADD|DEL|LIST} [текст|номер]"
-
-msgid "REGONLY enforced by "
-msgstr ""
-
-msgid "RESTRICTED enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "REVOKE server"
-msgstr "NOOP {SET|REVOKE} сервер"
-
-#, c-format
-msgid "Random news item #%d deleted."
-msgstr "Новость под номером #%d удалена."
-
-#, fuzzy, c-format
-msgid "Random news item #%s not found!"
-msgstr "Новость под номером #%d не обнаружена."
-
-msgid "Random news items:"
-msgstr "Список случайных новостей:"
-
-#, fuzzy
-msgid "Read a memo or memos"
-msgstr " READ Чтение какого-либо сообщения, группы сообщений"
-
-#, fuzzy
-msgid "Real name"
-msgstr "Реальное имя....: %s"
-
-#, fuzzy
-msgid "Realname"
-msgstr "Реальное имя....: %s"
-
-msgid "Reason"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Reason for %s updated."
-msgstr "Наследник канал %s удален."
-
-msgid ""
-"Recovers your nick from another user or from services.\n"
-"If services are currently holding your nick, the hold\n"
-"will be released. If another user is holding your nick\n"
-"and is identified they will be killed (similar to the old\n"
-"GHOST command). If they are not identified they will be\n"
-"forced off of the nick."
-msgstr ""
-
-#, fuzzy
-msgid "Redefine the meanings of access levels"
-msgstr " LEVELS Переустановка значения уровней доступа канала"
-
-#, fuzzy
-msgid "Regains control of your nick"
-msgstr ""
-" RELEASE Снятие защиты сервисов с вашего ника после команды RECOVER"
-
-#, fuzzy
-msgid "Regex is disabled."
-msgstr "Режим %s: включен."
-
-#, c-format
-msgid ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your mask in // if this is desired."
-msgstr ""
-
-#, c-format
-msgid ""
-"Regex matches are also supported using the %s engine.\n"
-"Enclose your pattern in // if this is desired."
-msgstr ""
-
-#, fuzzy
-msgid "Register a channel"
-msgstr " REGISTER Регистрация ника"
-
-#, fuzzy
-msgid "Register a nickname"
-msgstr " REGISTER Регистрация ника"
-
-#, fuzzy
-msgid "Registered"
-msgstr "Зарегистрирован.........: %s"
-
-#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Registered only enforced on %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which is optional, is a\n"
-"general description of the channel's purpose.\n"
-" \n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel."
-msgstr ""
-"Синтаксис: REGISTER #канал описание\n"
-"\n"
-"Registers a channel in the %s database. In order\n"
-"to use this command, you must first be a channel operator\n"
-"on the channel you're trying to register.\n"
-"The description, which must be included, is a\n"
-"general description of the channel's purpose.\n"
-"When you register a channel, you are recorded as the\n"
-"\"founder\" of the channel. The channel founder is allowed\n"
-"to change all of the channel settings for the channel;\n"
-"%s will also automatically give the founder\n"
-"channel-operator privileges when s/he enters the channel.\n"
-"See the ACCESS command (/msg %s HELP ACCESS) for\n"
-"information on giving a subset of these privileges to\n"
-"other channel users.\n"
-"NOTICE: In order to register a channel, you must have\n"
-"first registered your nickname. If you haven't,\n"
-"/msg %s HELP for information on how to do so."
-
-#, fuzzy, c-format
-msgid ""
-"Registers your nickname in the %s database. Once\n"
-"your nick is registered, you can use the SET and ACCESS\n"
-"commands to configure your nick's settings as you like\n"
-"them. Make sure you remember the password you use when\n"
-"registering - you'll need it to make changes to your nick\n"
-"later. (Note that case matters! ANOPE, Anope, and\n"
-"anope are all different passwords!)\n"
-" \n"
-"Guidelines on choosing passwords:\n"
-" \n"
-"Passwords should not be easily guessable. For example,\n"
-"using your real name as a password is a bad idea. Using\n"
-"your nickname as a password is a much worse idea ;) and,\n"
-"in fact, %s will not allow it. Also, short\n"
-"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
-"Finally, the space character cannot be used in passwords."
-msgstr ""
-"Синтаксис: REGISTER пароль [email]\n"
-"\n"
-"Позволяет зарегистрировать ваш текущий ник в базе данных %s.\n"
-"После успешной его регистрации, вы можете использовать команды\n"
-"SET и ACCESS что бы сконфигурировать параметры ника так, как\n"
-"вам будет угодно. Постарайтесь не забыть указанный при регистрации\n"
-"пароль - он понадобится вам для дальнейшего использования ника!\n"
-"\n"
-"Принципы выбора пароля:\n"
-"Пароли не должны быть легко угадываемы. Например, использование\n"
-"вашего реального имени в качестве пароля - плохая идея.\n"
-"Использование вашего ника в качестве пароля - совсем плохая идея,\n"
-"%s просто-напросто не допустит этого. Также, короткие пароли\n"
-"очень легко подбираются простым перебором, поэтому длина пароля\n"
-"должна быть больше 5 символов. Пробелы и знаки табуляции в пароле\n"
-"недопустимы, вы можете использовать только латинские буквы и цифры.\n"
-"Примечание: все пароли чувствительны к регистру! MYPASSWORD,\n"
-"MyPassword, и mypassword - это разные пароли!\n"
-"\n"
-"Указанный в качестве дополнительного параметра email будет\n"
-"автоматически ассоциирован с регистрируемым ником. Данный параметр\n"
-"может быть как опциональным, так и обязательным - это зависит от\n"
-"требований и настроек IRC-сети.\n"
-"Вы можете не беспокоиться о приватности вашего email-адреса - никто\n"
-"из посторонних лиц его не получит.\n"
-"\n"
-"Так же, регистрация нового ника автоматически создает для него новую\n"
-"группу. Возможности групп ников позволяют вам иметь несколько ников\n"
-"с общей для них информацией, настройками, списком доступа. Для более\n"
-"подробной информации см. /msg %s HELP GROUP"
-
-#, fuzzy
-msgid "Registration is currently disabled."
-msgstr "Извините, регистрация каналов временно приостановлена."
-
-#, fuzzy
-msgid "Regulate the use of critical commands"
-msgstr " PEACE активирование режима \"спокойствия\" на канале"
-
-#, fuzzy
-msgid "Reject the requested vHost for the given nick."
-msgstr ""
-" STATUS Запрос статуса идентификации указанного ника на сервисах"
-
-#, fuzzy
-msgid "Reject the requested vHost of a user"
-msgstr " DEL Удаление виртуального хоста"
-
-#, fuzzy
-msgid "Releases a suspended channel"
-msgstr " UNSUSPEND Снятие режима саспенда с канала (восстановление)"
-
-#, fuzzy
-msgid ""
-"Releases a suspended channel. All data and settings\n"
-"are preserved from before the suspension."
-msgstr ""
-"Синтаксис: UNSUSPEND #канал\n"
-"\n"
-"Полностью восстанавливает активность приостановленного канала."
-
-#, fuzzy
-msgid "Reload a module"
-msgstr " MODLOAD Загрузить модуль"
-
-#, fuzzy
-msgid "Reload services' configuration file"
-msgstr " RELOAD Перезагрузка конфигурационного файла сервисов"
-
-#, fuzzy
-msgid "Remove a nick from a group"
-msgstr " UNGROUP Remove a nick from a group"
-
-#, fuzzy
-msgid "Remove all bans preventing a user from entering a channel"
-msgstr ""
-" UNBAN Remove all bans preventing a user from entering a channel"
-
-#, fuzzy
-msgid "Remove all operators from a server remotely"
-msgstr ""
-" NOOP Временное удаление всех O:line'ов с указанного\n"
-" сервера сети"
-
-#, fuzzy, c-format
-msgid "Removed IP %s from %s."
-msgstr "Блокировка режимов........: %s"
-
-#, c-format
-msgid "Removed server %s from zone %s."
-msgstr ""
-
-#, c-format
-msgid "Removed server %s."
-msgstr ""
-
-#, c-format
-msgid ""
-"Removes %s status from the selected nick on a channel. If nick is\n"
-"not given, it will de%s you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Removes %s status from you or the specified nick on a channel"
-msgstr ""
-" OP Установка статуса оператора (+o) указанному нику на канале"
-
-#, fuzzy
-msgid "Removes a selected nicks status from a channel"
-msgstr " KICK Выкидывает указанного пользователя с канала"
-
-msgid ""
-"Removes a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is removed. If channel is omitted then\n"
-"your channel status is removed on every channel you are in."
-msgstr ""
-
-#, c-format
-msgid "Removing %s because %s covers it."
-msgstr ""
-
-#, fuzzy
-msgid "Repeat kicker"
-msgstr "Цензор повторов......: %s"
-
-#, fuzzy
-msgid "Request a vHost for your nick"
-msgstr "Для вашего ника не установлен email-адрес."
-
-msgid ""
-"Request the given vHost to be activated for your nick by the\n"
-"network administrators. Please be patient while your request\n"
-"is being considered."
-msgstr ""
-
-#, fuzzy
-msgid "Resend registration confirmation email"
-msgstr " RELOAD Перезагрузка конфигурационного файла сервисов"
-
-#, fuzzy
-msgid "Restrict access to the channel"
-msgstr " RESTRICTED ограничение уровня доступа на канал до прописанных"
-
-#, fuzzy
-msgid "Restricted access"
-msgstr "Ограниченный доступ"
-
-#, fuzzy, c-format
-msgid "Restricted access option for %s is now off."
-msgstr "Режим ограниченного доступа на канал %s активирован."
-
-#, fuzzy, c-format
-msgid "Restricted access option for %s is now on."
-msgstr "Режим ограниченного доступа на канал %s активирован."
-
-#, fuzzy, c-format
-msgid "Restricted enforced on %s."
-msgstr "Ограниченный доступ"
-
-#, fuzzy
-msgid "Retain modes when channel is not in use"
-msgstr " KEEPTOPIC активирование автосохранения топика канала"
-
-#, fuzzy
-msgid "Retain topic when channel is not in use"
-msgstr " KEEPTOPIC активирование автосохранения топика канала"
-
-#, fuzzy
-msgid "Retrieve the password for a nickname"
-msgstr " GETPASS Запрос пароля указанного ника"
-
-msgid "Retrieves the vhost requests"
-msgstr ""
-
-#, fuzzy
-msgid "Returns the key of the given channel"
-msgstr " GETKEY Запрос установленного на канале ключа (+k)"
-
-#, fuzzy
-msgid "Returns the key of the given channel."
-msgstr " GETKEY Запрос установленного на канале ключа (+k)"
-
-#, fuzzy
-msgid "Returns the matching accounts that used given email."
-msgstr " GETKEY Запрос установленного на канале ключа (+k)"
-
-#, fuzzy
-msgid "Returns the owner status of the given nickname"
-msgstr ""
-" STATUS Запрос статуса идентификации указанного ника на сервисах"
-
-#, fuzzy
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Синтаксис: GETPASS ник\n"
-"\n"
-"Позволяет получить пароль указанного ника.\n"
-"Примечание: сразу по использовании данной команды, сервисы пошлют\n"
-"по WALLOPS/GLOBOPS сообщение, содержащие ник использовавшего команду,\n"
-"и ник, относительно которого была использована данная команда.\n"
-"Одновременно с этим, событие будет записано в лог-файл.\n"
-"Примечание 2: команда недоступна, если включено шифрование паролей."
-
-#, fuzzy
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
-msgstr ""
-"Синтаксис: STATUS ник1 ник2 ник3...\n"
-"\n"
-"Запрашивает информацию о статусе ника на сервисах - идентифицировался\n"
-"ли использующий его как владелец. Ответ выводится в формате:\n"
-"\n"
-" ник код-статуса status account\n"
-"\n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-"\n"
-"0 - такого пользователя нет в онлайне или этот ник не зарегистрирован\n"
-"1 - пользователь не идентифицирован как владелец ника\n"
-"2 - пользователь идентифицирован как владелец ника через список хостмасок\n"
-"3 - пользователь идентифицирован как владелец ника через идентификацию "
-"паролем\n"
-"\n"
-"Вы можете запросить статус сразу у 16 ников (разделяя их пробелом),\n"
-"все лишние буду проигнорированы. Если параметр не указан - команда\n"
-"вернет ваш текущий статус на сервисах."
-
-#, fuzzy
-msgid "Reverses kicker"
-msgstr "Цензор инверсий......: %s"
-
-#, fuzzy
-msgid "Reverses the effect of the IDENTIFY command"
-msgstr " LOGOUT Деидентификация от используемого на данный момент ника"
-
-#, fuzzy
-msgid "SET server"
-msgstr "NOOP {SET|REVOKE} сервер"
-
-msgid "SET server.name option value"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "SSL certificate fingerprint accepted, you are now identified to %s."
-msgstr "Пароль принят - вы признаны как владелец ника."
-
-#, fuzzy
-msgid "SSL certificate fingerprint accepted, you are now identified."
-msgstr "Пароль принят - вы признаны как владелец ника."
-
-#, c-format
-msgid "SSL only enforced on %s."
-msgstr ""
-
-msgid "SSLONLY enforced by "
-msgstr ""
-
-#, fuzzy
-msgid "Save databases and restart Services"
-msgstr " RESTART Сохранить базы данных и перезапустить сервисы"
-
-msgid "Searches logs for a matching pattern"
-msgstr ""
-
-#, fuzzy
-msgid "Secure founder"
-msgstr "Безопасность владельца"
-
-#, fuzzy, c-format
-msgid "Secure founder option for %s is now off."
-msgstr "Режим безопасности владельца для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Secure founder option for %s is now on."
-msgstr "Режим безопасности владельца для канала %s активирован."
-
-#, fuzzy
-msgid "Secure ops"
-msgstr "Контроль статуса оператора"
-
-#, fuzzy, c-format
-msgid "Secure ops option for %s is now off."
-msgstr "Режим контроля за статусом оператора для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Secure ops option for %s is now on."
-msgstr "Режим контроля за статусом оператора для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now off."
-msgstr "Режим безопасности для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Secure option for %s is now on."
-msgstr "Режим безопасности для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Secure option is now off for %s."
-msgstr "Режим безопасности для %s активирован."
-
-#, fuzzy, c-format
-msgid "Secure option is now on for %s."
-msgstr "Режим безопасности для %s активирован."
-
-#, fuzzy, c-format
-msgid "Secureops enforced on %s."
-msgstr "Режим безопасности для %s активирован."
-
-msgid "Security"
-msgstr "Безопасность"
-
-#, fuzzy, c-format
-msgid ""
-"See %s%s HELP %s for more information\n"
-"about the access list."
-msgstr ""
-"Для более подробной информации о какой-либо конкретной опции, см.\n"
-"справку по /msg %s HELP опция"
-
-#, fuzzy, c-format
-msgid ""
-"See %s%s HELP %s for more information\n"
-"about the flags system."
-msgstr ""
-"Для более подробной информации о какой-либо конкретной опции, см.\n"
-"справку по /msg %s HELP опция"
-
-#, fuzzy
-msgid "Send a memo to a nick or channel"
-msgstr " SEND Отправка мемо-сообщения указанному нику или каналу"
-
-#, fuzzy
-msgid "Send a memo to all opers/admins"
-msgstr ""
-" STAFF Отправка мемо-сообщения всем операторам/администраторам сети"
-
-#, fuzzy
-msgid "Send a memo to all registered users"
-msgstr " SENDALL Отправка массового мемо-сообщения всем пользователям сети"
-
-#, fuzzy
-msgid "Send a message to all users"
-msgstr " GLOBAL Отправка глобального сообщения всем пользователям сети"
-
-#, fuzzy
-msgid "Sender"
-msgstr "Безопасность владельца"
-
-#, fuzzy
-msgid "Sends a memo and requests a read receipt"
-msgstr ""
-" RSEND Отправка мемо-сообщения с условием подтверждения о прочтении"
-
-#, fuzzy
-msgid ""
-"Sends a passcode to the nickname with instructions on how to\n"
-"reset their password. Email must be the email address associated\n"
-"to the nickname."
-msgstr ""
-"Syntax: RESETPASS nickname\n"
-"\n"
-"Sends a code key to the nickname with the instructions on how to\n"
-"reset their password."
-
-#, fuzzy
-msgid "Sends all registered users a memo containing memo-text."
-msgstr ""
-"Синтаксис: SENDALL текст_сообщения\n"
-"\n"
-"Отправляет массовое мемо-сообщение всем зарегистрированным\n"
-"пользователям сети."
-
-#, fuzzy
-msgid "Sends all services staff a memo containing memo-text."
-msgstr ""
-"Синтаксис: STAFF текст_сообщения\n"
-"\n"
-"Позволяет отправить мемо-сообщение всем операторам/администраторам\n"
-"сервисов сети."
-
-#, fuzzy
-msgid ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered."
-msgstr ""
-"Синтаксис: SEND {ник | #канал} текст_сообщения\n"
-"\n"
-"Отправляет сообщение для ника или для #канала, содержащее\n"
-"текст_сообщения. Если в качестве получателя указан ник, то он\n"
-"будет уведомлен о том, что вы отправили ему мемо-собщение.\n"
-"Примечание: получатель, будь то ник или канал, должен быть\n"
-"зарегистрирован, для возможности отправки/получения мемо-сообщений."
-
-#, fuzzy
-msgid ""
-"Sends the named nick or channel a memo containing\n"
-"memo-text. When sending to a nickname, the recipient will\n"
-"receive a notice that he/she has a new memo. The target\n"
-"nickname/channel must be registered.\n"
-"Once the memo is read by its recipient, an automatic notification\n"
-"memo will be sent to the sender informing him/her that the memo\n"
-"has been read."
-msgstr ""
-"Синтаксис: RSEND {ник | #канал} текст_сообщения\n"
-"\n"
-"Данная команда аналогична команде SEND и позволяет послать\n"
-"сообщение для указанного ника или канала. Отличительной ее\n"
-"особенностью является то, что сразу после прочтения адресатом\n"
-"сообщения, отправитель автоматически получит извещение о прочтении.\n"
-"Само собой разумеется, что ник/канал отправителя/получателя должны\n"
-"быть зарегистрированы."
-
-#, fuzzy
-msgid ""
-"Sends you the text of the memos specified. If LAST is\n"
-"given, sends you the memo you most recently received. If\n"
-"NEW is given, sends you all of your new memos. If ALL is\n"
-"given, sends you all of your memos. Otherwise, sends you\n"
-"memo number num. You can also give a list of numbers,\n"
-"as in this example:\n"
-" \n"
-" READ 2-5,7-9\n"
-" Displays memos numbered 2 through 5 and 7 through 9."
-msgstr ""
-"Синтаксис: READ [#канал] {номер | список_записей | LAST | NEW}\n"
-"\n"
-"Позволяет прочесть указанные сообщения. С параметром LAST - выведет\n"
-"текст последнего полученного вами сообщения, с параметром NEW -\n"
-"отобразит все непрочитанные вами сообщения.\n"
-"Помимо этого, вы можете указать список записей или номер записи,\n"
-"например:\n"
-"\n"
-" READ 2-5,7-9\n"
-" выведет текст всех сообщений с 2-го по 5-ое и с 7-го по 9-ое."
-
-#, fuzzy
-msgid "Server"
-msgstr "NOOP {SET|REVOKE} сервер"
-
-#, fuzzy, c-format
-msgid "Server %s added to zone %s."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s already exists."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy, c-format
-msgid "Server %s does not exist."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s has no configured IPs."
-msgstr "Ник %s успешно удален из базы данных сервисов."
-
-#, fuzzy, c-format
-msgid "Server %s is already in zone %s."
-msgstr "You are already in %s! "
-
-#, fuzzy, c-format
-msgid "Server %s is already pooled."
-msgstr "Module %s is already loaded."
-
-#, fuzzy, c-format
-msgid "Server %s is not currently linked."
-msgstr "%s сейчас в сети."
-
-#, fuzzy, c-format
-msgid "Server %s is not in zone %s."
-msgstr " %s (does not expire)"
-
-#, fuzzy, c-format
-msgid "Server %s is not linked to the network."
-msgstr "Бот с канала %s успешно удален."
-
-#, fuzzy, c-format
-msgid "Server %s is not pooled."
-msgstr " %s (does not expire)"
-
-#, c-format
-msgid "Server %s must be quit before it can be deleted."
-msgstr ""
-
-#, fuzzy
-msgid "Servers"
-msgstr "NOOP {SET|REVOKE} сервер"
-
-#, c-format
-msgid "Servers found: %d"
-msgstr "Текущее кол-во серверов: %d"
-
-#, fuzzy
-msgid "Service"
-msgstr "Текущее кол-во серверов: %d"
-
-#, fuzzy, c-format
-msgid "Service's hold on %s has been released."
-msgstr "Ваш ник освобожден от удержания сервисами."
-
-#, fuzzy
-msgid "Services Operator commands"
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "Services are in DefCon mode, please try again later."
-msgstr ""
-"На данный момент сервисы работают в DEFCON-режиме. Повторите свой запрос "
-"позже."
-
-#, fuzzy
-msgid "Services are in read-only mode!"
-msgstr "Сервисы перешли в режим read-only (только чтение)."
-
-#, fuzzy, c-format
-msgid "Services are now at DEFCON %d."
-msgstr "DEFCON-режим активирован, уровень защиты: %d"
-
-#, fuzzy, c-format
-msgid "Services are now in debug mode (level %d)."
-msgstr "Режим работы сервисов изменен: активирован DEBUG-режим (уровень %d)."
-
-#, fuzzy
-msgid "Services are now in debug mode."
-msgstr "Режим работы сервисов изменен: активирован DEBUG-режим (отладка)."
-
-msgid "Services are now in expire mode."
-msgstr "Режим работы сервисов изменен: NOEXPIRE-режим деактивирован."
-
-msgid "Services are now in no expire mode."
-msgstr ""
-"Режим работы сервисов изменен: активирован NOEXPIRE-режим (режим 'не-"
-"истечения')."
-
-#, fuzzy
-msgid "Services are now in non-debug mode."
-msgstr "Режим работы сервисов изменен: DEBUG-режим деактивирован."
-
-msgid "Services are now in read-only mode."
-msgstr "Сервисы перешли в режим read-only (только чтение)."
-
-msgid "Services are now in read-write mode."
-msgstr "Сервисы перешли в режим read-write (чтение-запись)."
-
-msgid "Services have been configured to not send mail."
-msgstr ""
-"Настройки mail-функций сервисов некорректны или отключены, возможность "
-"отправки email недоступна."
-
-#, fuzzy
-msgid "Services ignore list:"
-msgstr " IGNORE Управление игнор-списком сервисов"
-
-#, fuzzy
-msgid ""
-"Services is unable to change modes. Are your servers' U:lines configured "
-"correctly?"
-msgstr ""
-"Возможность изменять режимы сервисам недоступна. Вы вообще уверены, что U:"
-"line-записи ваших серверов корректны?"
-
-#, fuzzy, c-format
-msgid "Services up %s."
-msgstr "Текущее кол-во серверов: %d"
-
-#, fuzzy, c-format
-msgid "Services will from now on set status modes on %s in channels."
-msgstr "Режим автостатуса для %s отключен"
-
-#, fuzzy, c-format
-msgid "Services will no longer automatically give modes to users in %s."
-msgstr "Режим автостатуса для %s отключен"
-
-#, fuzzy, c-format
-msgid "Services will no longer set status modes on %s in channels."
-msgstr "Режим автостатуса для %s отключен"
-
-#, fuzzy, c-format
-msgid "Services will now automatically give modes to users in %s."
-msgstr "Режим автостатуса для %s активирован"
-
-#, c-format
-msgid "Services will now reply to %s with messages."
-msgstr ""
-"Режим приватных сообщений для %s активирован, теперь сервисы будут отвечать "
-"ему в приват."
-
-#, c-format
-msgid "Services will now reply to %s with notices."
-msgstr ""
-"Режим приватных сообщений для %s отключен, сервисы будут отвечать ему "
-"посредством нотисов."
-
-#, fuzzy
-msgid "Services' configuration has been reloaded."
-msgstr "Конфигурационный файл сервисов был считан заново."
-
-msgid "Session"
-msgstr ""
-
-#, c-format
-msgid "Session limit for %s set to %d."
-msgstr "Лимит сессий для %s установлен на %d."
-
-msgid "Session limiting is disabled."
-msgstr "Ограничение сессий отключено, список исключений не требуется."
-
-#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, fuzzy
-msgid "Set SET-options on another nickname"
-msgstr " SASET Установка различных опций какого-либо ника"
-
-#, fuzzy
-msgid "Set channel options and information"
-msgstr " SET Настройка различных опций канала"
-
-#, fuzzy
-msgid "Set how Services make bans on the channel"
-msgstr " BANTYPE установка типа бана сервисами на канале"
-
-#, fuzzy
-msgid "Set options related to memos"
-msgstr " SET Установка опций для мемо-сообщений"
-
-#, fuzzy
-msgid "Set options, including kill protection"
-msgstr " SET Настройка опций ника, включая защиту KILL'ом"
-
-#, fuzzy
-msgid "Set the channel as permanent"
-msgstr " PERSIST Set the channel as permanent"
-
-#, fuzzy
-msgid "Set the channel description"
-msgstr " DESC изменение описания канала"
-
-#, fuzzy
-msgid "Set the display of your group in Services"
-msgstr " DISPLAY установка главного ника группы"
-
-#, fuzzy
-msgid "Set the founder of a channel"
-msgstr " FOUNDER смена владельца канала"
-
-#, fuzzy
-msgid "Set the language Services will use when messaging you"
-msgstr ""
-" LANGUAGE выбор языка, посредством которого\n"
-" сервисы будут с вами общаться"
-
-#, fuzzy
-msgid "Set the nickname password"
-msgstr " PASSWORD изменение текущего пароля на ник"
-
-#, fuzzy
-msgid "Set the successor for a channel"
-msgstr " SUCCESSOR установка наследника канала"
-
-#, fuzzy
-msgid "Set the vhost for all nicks in a group"
-msgstr " SETALL Установка вирт. хоста для всех ников указанной группы"
-
-#, fuzzy
-msgid "Set the vhost of another user"
-msgstr " SET Установка виртуального хоста указанному пользователю"
-
-#, fuzzy
-msgid "Set various global Services options"
-msgstr " SET Настройка различных опций сервисов"
-
-#, fuzzy
-msgid "Set your nickname password"
-msgstr " PASSWORD изменение текущего пароля на ник"
-
-#, fuzzy, c-format
-msgid ""
-"Sets the AMSG kicker on or off. When enabled, the bot will\n"
-"kick users who send the same message to multiple channels\n"
-"where %s bots are.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before they get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-
-#, fuzzy, c-format
-msgid ""
-"Sets the bad words kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who say certain words\n"
-"on the channels.\n"
-"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
-"more information.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал BADWORDS {ON|OFF} [ttb]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за использование на канале \"плохих\" слов.\n"
-"\n"
-"База \"плохих\" слов канала модифицируется посредством дополнительной\n"
-"команды BADWORDS. Для более подробной информации смотрите справку\n"
-"по /msg %s HELP BADWORDS.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the ban type that will be used by services whenever\n"
-"they need to ban someone from your channel.\n"
-" \n"
-"Bantype is a number between 0 and 3 that means:\n"
-" \n"
-"0: ban in the form *!user@host\n"
-"1: ban in the form *!*user@host\n"
-"2: ban in the form *!*@host\n"
-"3: ban in the form *!*user@*.domain"
-msgstr ""
-"Синтаксис: %s #канал BANTYPE тип_бана\n"
-"\n"
-"Позволяет установить шаблон банмаски, по которой будет забанен\n"
-"пользователь канала, относительно которого применяется сервисная\n"
-"команда BAN.\n"
-"\n"
-"Значение типа бана должно быть кокретным числом, от 0 до 3\n"
-"включительно. Допустимые значения представлены ниже:\n"
-"\n"
-"0 - бан вида *!идент@хост\n"
-"1 - бан вида *!*идент@хост\n"
-"2 - бан вида *!*@хост\n"
-"3 - бан вида *!*идент@*.домен"
-
-#, fuzzy
-msgid ""
-"Sets the bolds kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use bolds.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал BOLDS {ON|OFF} [ttb]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за чрезмерное использование жирного\n"
-"текста.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy, c-format
-msgid ""
-"Sets the caps kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are talking in\n"
-"CAPS.\n"
-"The bot kicks only if there are at least min caps\n"
-"and they constitute at least percent%% of the total\n"
-"text line (if not given, it defaults to 10 characters\n"
-"and 25%%).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал CAPS {ON|OFF} [ttb [минимум [проценты]]]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за чрезмерное использование CapsLOCK.\n"
-"\n"
-"Условия наказания рассчитываются следующим образом: строка, которую\n"
-"послал посетитель, должна содержать X больших букв, определенных\n"
-"минимумом, и количество этих заглавных букв должно составлять как\n"
-"минимум X процентов%% от числа букв всей строки.\n"
-"Например: предположим, что настройки у нас стоят как 10 и 25,\n"
-"тогда строка вида:\n"
-"\n"
-"BLABLABLAB BLABLABLAB BLABLABlab blablablab blablablab blablablab\n"
-"blablablab blablablab blablablab blablablab\n"
-"\n"
-"будет попадать под следующее условие: количество заглавных букв\n"
-"больше 10 и и процентаж его относительно общего кол-ва букв > 25%.\n"
-"Как видите, выставленное нами условие в данном случае сработает и\n"
-"пользователь будет кикнут с соответствующей причиной.\n"
-"\n"
-"Если вы не укажете параметры режима, будут использованы значения\n"
-"по-умолчанию: 10 для минимума букв и 25% для процентажа.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the colors kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use colors.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал COLORS {ON|OFF} [ttb]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за чрезмерное использование цветного\n"
-"текста.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the description for the channel, which shows up with\n"
-"the LIST and INFO commands."
-msgstr ""
-"Синтаксис: %s #канал DESC описание\n"
-"\n"
-"Позволяет установить описание канала, которое будет показано при\n"
-"использовании команд LIST и INFO."
-
-#, fuzzy
-msgid ""
-"Sets the flood kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are flooding\n"
-"the channel using at least ln lines in secs seconds\n"
-"(if not given, it defaults to 6 lines in 10 seconds).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал FLOOD {ON|OFF} [ttb [линий [секунды]]]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за флуд.\n"
-"\n"
-"Условия наказания рассчитываются следующим образом: пользователь\n"
-"должен послать на канал количество сообщений, превыщающее параметр\n"
-"линий, и, если это произошло в указанный промежуток секунды -\n"
-"бот кикнет его с соответствующей причиной.\n"
-"\n"
-"Если вы не укажете параметры режима, будут использованы значения\n"
-"по-умолчанию: 6 строк за 10 секунд.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Syntax: KICK channel ITALICS {ON|OFF} [ttb]\n"
-"Sets the italics kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use italics.\n"
-"ttb is the number of times a user can be kicked\n"
-"before it get banned. Don't give ttb to disable\n"
-"the ban system once activated."
-
-#, fuzzy
-msgid ""
-"Sets the repeat kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who are repeating\n"
-"themselves num times (if num is not given, it\n"
-"defaults to 3).\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал REPEAT {ON|OFF} [ttb [число_повторов]]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за повторы.\n"
-"\n"
-"Условия наказания рассчитываются следующим образом: пользователь\n"
-"должен X раз подряд послать на канал одинаковое сообщение, при этом\n"
-"сообщения других пользователей, посланные в это же время, никоим\n"
-"образом несбрасывают счетчик числа_повторов этого пользователя. \n"
-"\n"
-"Если вы не укажете параметры режима, будут использованы значения\n"
-"по-умолчанию: 3 повтора подряд.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the reverses kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use reverses.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал REVERSES {ON|OFF} [ttb]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за чрезмерное использование инверсного\n"
-"текста.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the underlines kicker on or off. When enabled, this\n"
-"option tells the bot to kick users who use underlines.\n"
-" \n"
-"ttb is the number of times a user can be kicked\n"
-"before it gets banned. Don't give ttb to disable\n"
-"the ban system once activated."
-msgstr ""
-"Синтаксис: KICK #канал UNDERLINES {ON|OFF} [ttb]\n"
-"\n"
-"Активируйте данную опцию с нужными вам значениями, если хотите\n"
-"чтобы бот кикал посетителей за чрезмерное использование подчеркиваний.\n"
-"\n"
-"Параметр ttb - это количество киков, по превышению которого бот\n"
-"поставит бан. Укажите вместо положительного числа значение \"0\" или\n"
-"\"-\" если не хотите чтобы бот банил нарушителя."
-
-#, fuzzy
-msgid ""
-"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
-"using SETALL <nick> <ident>@<hostmask> will set idents\n"
-"for users as well as vhosts.\n"
-"* NOTE, this will not update the vhost for any nicks\n"
-"added to the group after this command was used."
-msgstr ""
-"Синтаксис: SETALL <ник> <хостмаска>.\n"
-"\n"
-"Устанавливает виртуальный хост для всех ников указанной группы.Если\n"
-"IRCd вашей сети подерживает виртуальные иденты, можно использовать\n"
-"формат SETALL <ник> <идент>@<хостмаска> для установки виртуальных\n"
-"идента и хоста одновременно.\n"
-"\n"
-"Примечание: виртуальный хост устанавливается для всех текущих\n"
-"ников указанной группы и не будет автоматически обновлен для нового\n"
-"ника, внесенного в группу уже после установки виртуального хоста."
-
-#, fuzzy
-msgid ""
-"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
-"SET <nick> <ident>@<hostmask> set idents for users as\n"
-"well as vhosts."
-msgstr ""
-"Синтаксис: SET <ник> <хостмаска>.\n"
-"\n"
-"Устанавливает указанный виртуальный хост для указанного ника. Если\n"
-"IRCd вашей сети подерживает виртуальные иденты, можно использовать\n"
-"формат SET <ник> <идент>@<хостмаска> для установки виртуальных\n"
-"идента и хоста одновременно."
-
-#, fuzzy
-msgid ""
-"Sets various global Services options. Option names\n"
-"currently defined are:\n"
-" READONLY Set read-only or read-write mode\n"
-" DEBUG Activate or deactivate debug mode\n"
-" NOEXPIRE Activate or deactivate no expire mode\n"
-" SUPERADMIN Activate or deactivate super admin mode\n"
-" LIST List the options"
-msgstr ""
-"Синтаксис: SET опция параметр\n"
-"\n"
-"Позволяет настроить различные глобальные опции сервисов.\n"
-"Доступные опции:\n"
-"\n"
-" READONLY активация/деактивация режима read-only (только-чтение)\n"
-" LOGCHAN активация/деактивация логирования событий на сервисный канал\n"
-" DEBUG активация/деактивация режим отладки (debug mode)\n"
-" NOEXPIRE активация/деактивация режима не-истечения\n"
-" IGNORE активация/деактивация обработки списка игнора\n"
-" LIST просмотр статуса всех вышеперечисленных опций\n"
-" SUPERADMIN активация/деактивация режима Супер-Администратора\n"
-" (относительно использующего команду)"
-
-#, fuzzy, c-format
-msgid ""
-"Sets various memo options. option can be one of:\n"
-" \n"
-" NOTIFY Changes when you will be notified about\n"
-" new memos (only for nicknames)\n"
-" LIMIT Sets the maximum number of memos you can\n"
-" receive\n"
-" \n"
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
-msgstr ""
-"Синтаксис: SET опция параметры\n"
-"\n"
-"Позволяет настроить ваши личные опции службы сообщений.\n"
-"Валидные опции:\n"
-"\n"
-" NOTIFY выбор способа уведомления о новых собщениях\n"
-" LIMIT установка вашего максимального лимита сообщений\n"
-"\n"
-"Для более подробной информации о конкретной опции воспользуйтесь\n"
-"командой /msg %s HELP SET опция."
-
-#, fuzzy
-msgid "Sets various nickname options. option can be one of:"
-msgstr ""
-"Синтаксис: SET опция параметры\n"
-"\n"
-"Команда SET позволяет вам настроить различные опции ника.\n"
-"Список опций:"
-
-msgid ""
-"Sets whether services should set channel status modes on you automatically."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Sets whether the given channel will expire. Setting this\n"
-"to ON prevents the channel from expiring."
-msgstr ""
-"Синтаксис: SET #канал NOEXPIRE {ON | OFF}\n"
-"\n"
-"Позволяет установить режим не-истечения для указанного канала.\n"
-"Активирование этой опции автоматически исключит канал из условий\n"
-"истечения его регистрации по времени. Соответственно деактивирование\n"
-"режима вернет все на круги своя."
-
-#, fuzzy, c-format
-msgid ""
-"Sets whether the given nickname will be given its status modes\n"
-"in channels automatically. Set to ON to allow %s\n"
-"to set status modes on the given nickname automatically when it\n"
-"is entering channels. Note that depending on channel settings\n"
-"some modes may not get set automatically."
-msgstr ""
-"Синтаксис: SASET ник AUTOOP {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим автоматического получения статуса.\n"
-"Укажите ON, если хотите что бы сервисы автоматически давали\n"
-"владельцу ника статус при входе на канал. Соответственно OFF -\n"
-"для отключения."
-
-#, fuzzy
-msgid ""
-"Sets whether the given nickname will expire. Setting this\n"
-"to ON prevents the nickname from expiring."
-msgstr ""
-"Синтаксис: SASET ник NOEXPIRE {ON | OFF}\n"
-"\n"
-"Позволяет исключить указанный ник из условий истечения регистрации\n"
-"по времени. Укажите ON, что бы активировать так называемый режим\n"
-"'не-истечения'. Параметр OFF снова возвращает ник в режим истечения."
-
-#, fuzzy, c-format
-msgid ""
-"Sets whether you will be given your channel status modes automatically.\n"
-"Set to ON to allow %s to set status modes on you automatically\n"
-"when entering channels. Note that depending on channel settings some modes\n"
-"may not get set automatically."
-msgstr ""
-"Синтаксис: SET AUTOOP {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим втоматического получения статуса.\n"
-"Укажите ON, если хотите что бы сервисы автоматически давали вам\n"
-"статус при входе на канал. Соответственно OFF - для отключения."
-
-#, fuzzy, c-format
-msgid ""
-"Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
-msgstr ""
-"Неизвестный пункт %s. Для получения списка всех доступных значений см. /msg "
-"%s HELP LEVELS DESC"
-
-#, fuzzy
-msgid "Setting for DEBUG must be ON, OFF, or a positive number."
-msgstr ""
-"В качестве параметра для опции DEBUG вы должны указать ON, OFF, либо "
-"положительное число."
-
-#, fuzzy
-msgid "Setting for NOEXPIRE must be ON or OFF."
-msgstr ""
-"В качестве параметра для опции NOEXPIRE вы должны указать либо ON, либо OFF."
-
-#, fuzzy
-msgid "Setting for READONLY must be ON or OFF."
-msgstr ""
-"В качестве параметра для опции READONLY вы должны указать либо ON, либо OFF."
-
-#, fuzzy
-msgid "Setting for super admin must be ON or OFF."
-msgstr ""
-"В качестве параметра для опции READONLY вы должны указать либо ON, либо OFF."
-
-#, fuzzy
-msgid "Should services automatically give status to users"
-msgstr " AUTOOP активирование/деактивирование автостатуса"
-
-#, fuzzy
-msgid "Show status of Services and network"
-msgstr " STATS Запрос информаци о статусе сервисов и сети"
-
-#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr ""
-
-#, fuzzy
-msgid "Sign kicks that are done with the KICK command"
-msgstr " SIGNKICK настройка режима \"подписанных киков\""
-
-#, fuzzy, c-format
-msgid "Signed kick option for %s is now off."
-msgstr "Режим подписанных киков для канала %s активирован."
-
-#, fuzzy, c-format
-msgid ""
-"Signed kick option for %s is now on, but depends of the\n"
-"level of the user that is using the command."
-msgstr ""
-"Режим подписанных киков для канала %s активирован,\n"
-"но будет работать в зависимости от настроек уровней доступа."
-
-#, fuzzy, c-format
-msgid "Signed kick option for %s is now on."
-msgstr "Режим подписанных киков для канала %s активирован."
-
-msgid "Signed kicks"
-msgstr "Подписанные кики"
-
-#, fuzzy, c-format
-msgid "Sorry, %s currently has too many memos and cannot receive more."
-msgstr ""
-"Список сообщений для %s переполнен и принимать на данный момент новые он не "
-"может."
-
-#, c-format
-msgid "Sorry, I have not seen %s."
-msgstr ""
-
-#, fuzzy
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr "Извините, изменение базы данных плохих слов временно невозможно."
-
-#, fuzzy
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr "Извините, но возможность настройки опций бота временно недоступна."
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "Извините, изменение настроек ботов временно недоступно."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr "Извините, но возможность настройки опций бота временно недоступна."
-
-#, fuzzy
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr "Извините, но возможность настройки опций бота временно недоступна."
-
-#, fuzzy, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
-msgstr ""
-"Извините, но возможность модификации списка AOP'ов временно недоступна."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr ""
-"Извините, но возможность модификации списка доступа канала временно "
-"недоступна."
-
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr ""
-"Извините, но возможность модификации списка автокиков канала временно "
-"недоступна."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr "Извините, возможность удаление каналов временно недоступна."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Извините, регистрация каналов временно приостановлена."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
-msgstr ""
-"Извините, но возможность конфигурации условий киков временно недоступна."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr "Извините, но настройка опций службы сообщений временно невозможна."
-
-#, fuzzy
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr "Извините, но настройка опций службы сообщений временно невозможна."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Извините, но возможность удаления ников временно недоступна."
-
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Извините, но возможность группировки ников временно недоступна."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Извините, но регистрация ников временно приостановлена."
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
-msgstr "Извините, в списке доступа канала может быть не более %d записей."
-
-#, c-format
-msgid "Sorry, the maximum of %d auto join entries has been reached."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Sorry, the maximum of %d certificate entries has been reached."
-msgstr "Извините, но количество записей в списке доступа не может превышать %d"
-
-#, fuzzy, c-format
-msgid "Sorry, the memo ignore list for %s is full."
-msgstr "Приветствие для %s удалено."
-
-#, fuzzy, c-format
-msgid ""
-"Sorry, you can only have %d access entries on a channel, including access "
-"entries from other channels."
-msgstr "Извините, в списке доступа канала может быть не более %d записей."
-
-#, c-format
-msgid "Sorry, you can only have %d autokick masks on a channel."
-msgstr "Список автокиков канала может содержать не более %d записей."
-
-#, c-format
-msgid "Sorry, you can only have %d bad words entries on a channel."
-msgstr "Размер базы данных плохих слов не может превышать %d записей."
-
-#, fuzzy, c-format
-msgid "Sorry, you have already exceeded your limit of %d channels."
-msgstr "Размер базы данных плохих слов не может превышать %d записей."
-
-#, fuzzy, c-format
-msgid "Sorry, you have already reached your limit of %d channels."
-msgstr "Размер базы данных плохих слов не может превышать %d записей."
-
-msgid "State"
-msgstr ""
-
-msgid "Statistics and maintenance for seen data"
-msgstr ""
-
-msgid "Statistics reset."
-msgstr "Статистические данные сброшены."
-
-msgid "Status updated (memos, vhost, chmodes, flags)."
-msgstr ""
-"Статус на сервисах обновлен (мемо-сообщения, вирутальный хост, и т.д.)."
-
-msgid "Stop flooding!"
-msgstr "Хватит флудить!"
-
-msgid "Stop repeating yourself!"
-msgstr "Хватит повторов!"
-
-#, fuzzy
-msgid "Stricter control of channel founder status"
-msgstr " SECUREFOUNDER ограничение на получение статуса владельца канала"
-
-#, fuzzy
-msgid "Stricter control of chanop status"
-msgstr " SECUREOPS контроль за получением статуса оператора канала"
-
-msgid "Successor"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Successor for %s changed to %s."
-msgstr "Наследником канала %s назначен пользователь %s."
-
-#, c-format
-msgid "Successor for %s unset."
-msgstr "Наследник канал %s удален."
-
-#, fuzzy
-msgid ""
-"Super admin can not be set because it is not enabled in the configuration."
-msgstr "Директива SuperAdmin отключена в конфигурационном файле сервисов."
-
-#, fuzzy
-msgid "Suspend a given nick"
-msgstr " SUSPEND Установка режима саспенда (\"заморозки\") на ник"
-
-#, fuzzy
-msgid "Suspend reason"
-msgstr "JUPE имя_сервера [причина]"
-
-msgid "Suspended"
-msgstr ""
-
-msgid "Suspended by"
-msgstr ""
-
-#, fuzzy
-msgid "Suspended on"
-msgstr " SUSPEND Установка режима саспенда (\"заморозки\") на ник"
-
-#, fuzzy
-msgid ""
-"Suspends a registered nickname, which prevents it from being used\n"
-"while keeping all the data for that nick. If an expiry is given\n"
-"the nick will be unsuspended after that period of time, else the\n"
-"default expiry from the configuration is used."
-msgstr ""
-"Синтаксис: SUSPEND #канал [причина]\n"
-"\n"
-"Приостанавливает любую активность указанного канала (замораживает).\n"
-"В режиме саспенда, на канал не действуют условия истечения регистрации\n"
-"по времени, канал невозможно использовать или удалить. Единственное,\n"
-"что владелец все еще может - это изменять настройки своего канала.\n"
-"Эффект \"заморозки\" отменяется путем использования команды UNSUSPEND,\n"
-"которая полностью восстанавливает активность канала со всеми его\n"
-"настройками.\n"
-"\n"
-"Примечание: в зависимости от настроек сервисов, причина может\n"
-"быть параметром как опциональным, так и необходимым."
-
-#, fuzzy
-msgid "Suspension expires"
-msgstr " %s (does not expire)"
-
-#, fuzzy
-msgid "Sync users channel modes"
-msgstr "%s принудительно изменил ваши пользовательские режимы."
-
-msgid ""
-"Syncs all modes set on users on the channel with the modes\n"
-"they should have based on their access."
-msgstr ""
-
-#, fuzzy
-msgid "Syncs the vhost for all nicks in a group"
-msgstr " GROUP Синхронизирует виртуальный хост для всех ников группы"
-
-msgid "Syntax"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: %s\n"
-" \n"
-"Lists all nicks in your group."
-msgstr ""
-"Синтаксис: GLIST\n"
-"\n"
-"Выводит список ников в вашей группе."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: %s [nickname]\n"
-" \n"
-"Without a parameter, lists all nicknames that are in\n"
-"your group.\n"
-" \n"
-"With a parameter, lists all nicknames that are in the\n"
-"group of the given nick.\n"
-"Specifying a nick is limited to Services Operators."
-msgstr ""
-"Синтаксис: GLIST [ник]\n"
-"\n"
-"Без параметров, покажет список ников в вашей группе. С параметром,\n"
-"покажет все ники находящиеся в группе указанного ника.\n"
-"Для использования этой команды необходимы права Администратора сервисов."
-
-#, fuzzy
-msgid ""
-"Syntax: DEBUG {ON | OFF}\n"
-" \n"
-"Sets debug mode on or off.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--debug."
-msgstr ""
-"Синтаксис: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Включает или выключает режим глобального \"не-истечения\". В этом\n"
-"режиме, все ники, каналы, AKILL'ы и исключения из лимита сессий -\n"
-"никогда не истекут, по крайней мере до тех пор, пока эта опция не\n"
-"будет отключена.\n"
-"\n"
-"Активирование данной опции эквивалентно запуску сервисов с ключом\n"
-"-noexpire."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIMIT [channel] limit\n"
-" \n"
-"Sets the maximum number of memos you (or the given channel)\n"
-"are allowed to have. If you set this to 0, no one will be\n"
-"able to send any memos to you. However, you cannot set\n"
-"this any higher than %d."
-msgstr ""
-"Синтаксис: SET LIMIT [#канал] предел\n"
-"\n"
-"Позволяет ограничить максимальное количество сообщений, которое вы\n"
-"(или канал) можете принять. Установка значения в 0 полностью отключит\n"
-"возможность принятия сообщений.\n"
-"Максимально допустимое значение: %d."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIMIT [user | channel] {limit | NONE} [HARD]\n"
-" \n"
-"Sets the maximum number of memos a user or channel is\n"
-"allowed to have. Setting the limit to 0 prevents the user\n"
-"from receiving any memos; setting it to NONE allows the\n"
-"user to receive and keep as many memos as they want. If\n"
-"you do not give a nickname or channel, your own limit is\n"
-"set.\n"
-" \n"
-"Adding HARD prevents the user from changing the limit. Not\n"
-"adding HARD has the opposite effect, allowing the user to\n"
-"change the limit (even if a previous limit was set with\n"
-"HARD).\n"
-" \n"
-"This use of the SET LIMIT command is limited to Services\n"
-"Operators. Other users may only enter a limit for themselves\n"
-"or a channel on which they have such privileges, may not\n"
-"remove their limit, may not set a limit above %d, and may\n"
-"not set a hard limit."
-msgstr ""
-"Синтаксис: SET LIMIT [пользователь | #канал] {предел | NONE} [HARD]\n"
-"\n"
-"Устанавливает лимит на максимальное количество сообщений, которое\n"
-"пользователь (или канал) смогут принимать. Установка лимита равным\n"
-"0 отключит возможность принятия сообщения вообще, установка в NONE\n"
-"разрешает пользователю принимать и сохранять столько сообщений,\n"
-"сколько он пожелает. Если вы не укажете пользователя или канал,\n"
-"настройки буду применены относительно вас.\n"
-"\n"
-"Дополнительный параметр HARD запретит указанному пользователю\n"
-"изменять свой лимит сообщений. Соответственно установка лимита без\n"
-"параметра HARD отменяет эффект запрета и разрешает пользователю\n"
-"настраивать свой лимит сообщений.\n"
-"\n"
-"Расширенное использование команды SET LIMIT доступно только для\n"
-"Администраторов сервисов. Обычные пользователи могуть менять лимит\n"
-"только для себя или для канала, на котором у них есть соответствующие\n"
-"привилегии. Они не могут удалить свой лимит, не могут установить\n"
-"лимит выше %d, и не могут использовать опцию HARD."
-
-#, fuzzy, c-format
-msgid ""
-"Syntax: LIST\n"
-" \n"
-"Display the various %s settings."
-msgstr ""
-"Синтаксис: SET LIST\n"
-"\n"
-"Отображает статус различных сервисных настроек (вкл/выкл)."
-
-#, fuzzy
-msgid ""
-"Syntax: NOEXPIRE {ON | OFF}\n"
-" \n"
-"Sets no expire mode on or off. In no expire mode, nicks,\n"
-"channels, akills and exceptions won't expire until the\n"
-"option is unset.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--noexpire."
-msgstr ""
-"Синтаксис: SET NOEXPIRE {ON | OFF}\n"
-"\n"
-"Включает или выключает режим глобального \"не-истечения\". В этом\n"
-"режиме, все ники, каналы, AKILL'ы и исключения из лимита сессий -\n"
-"никогда не истекут, по крайней мере до тех пор, пока эта опция не\n"
-"будет отключена.\n"
-"\n"
-"Активирование данной опции эквивалентно запуску сервисов с ключом\n"
-"-noexpire."
-
-#, fuzzy
-msgid ""
-"Syntax: NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-" \n"
-"Changes when you will be notified about new memos:\n"
-" \n"
-" ON You will be notified of memos when you log on,\n"
-" when you unset /AWAY, and when they are sent\n"
-" to you.\n"
-" LOGON You will only be notified of memos when you log\n"
-" on or when you unset /AWAY.\n"
-" NEW You will only be notified of memos when they\n"
-" are sent to you.\n"
-" MAIL You will be notified of memos by email as well as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF You will not receive any notification of memos.\n"
-" \n"
-"ON is essentially LOGON and NEW combined."
-msgstr ""
-"Синтаксис: SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\n"
-"\n"
-"Данная опция позволяет настроить ваш личный метод уведомления о\n"
-"новых сообщениях, посланных вам кем-либо.\n"
-"Доступные режимы:\n"
-" ON уведомление будет поступать сразу, как только вы\n"
-" идентифицируетесь к нику, снимете с себя статус\n"
-" /AWAY или кто-то отправит вам новое сообщение.\n"
-" LOGON уведомление будет поступать сразу, как только вы\n"
-" идентифицируетесь к нику или снимете с себя статус\n"
-" /AWAY (отошел).\n"
-" NEW уведомление будет поступать сразу, как только кто-то\n"
-" отправит вам новое сообщение.\n"
-" MAIL You will be notified of memos by email aswell as\n"
-" any other settings you have.\n"
-" NOMAIL You will not be notified of memos by email.\n"
-" OFF уведомлений о получении новых сообщений поступать\n"
-" не будет\n"
-"\n"
-"Параметр ON является комбинацией значений LOGON и NEW."
-
-#, fuzzy
-msgid ""
-"Syntax: READONLY {ON | OFF}\n"
-" \n"
-"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
-"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
-"suspend or forbid nicknames and channels, and manage news,\n"
-"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
-"terminated or restarted.\n"
-" \n"
-"This option is equivalent to the command-line option\n"
-"--readonly."
-msgstr ""
-"Синтаксис: SET READONLY {ON | OFF}\n"
-"\n"
-"Включает или выключает глобальный режим READONLY - только-чтение.\n"
-"Работа сервисов в данном режиме запрещает обычным пользователям\n"
-"изменять какие-либо сервисные данные, например - списки доступа для\n"
-"ников или каналов, их настройки и т. д. Тем не менее, IRC-операторы\n"
-"с достаточными привилегиями на сервисах смогут модифицировать список\n"
-"AKILL'ов и удалять или запрещать ники и каналы, но все эти изменения\n"
-"не будут сохранены до тех пор, пока режим READONLY активен. Что бы\n"
-"сохранить все изменения, сделанные во время работы сервисов в этом\n"
-"режиме, вы должны деактивировать режим только-чтения прежде, чем\n"
-"работа сервисов будет завершена или они будут перезапущены.\n"
-"\n"
-"Активирование данной опции эквивалентно запуску сервисов с ключом\n"
-"-readonly."
-
-#, fuzzy
-msgid ""
-"Syntax: SUPERADMIN {ON | OFF}\n"
-" \n"
-"Setting this will grant you extra privileges such as the\n"
-"ability to be \"founder\" on all channel's etc...\n"
-" \n"
-"This option is not persistent, and should only be used when\n"
-"needed, and set back to OFF when no longer needed."
-msgstr ""
-"Синтаксис: SET SUPERADMIN {ON | OFF}\n"
-"\n"
-"Режим Супер-Администратора не влияет на саму работу сервисов как\n"
-"таковую, однако его активирование влияет на условия проверки уровня\n"
-"доступа пользователя к тем или иным функциям. В частности, данный\n"
-"режим предоставляет использовавшему его Руту сервисов неограниченные\n"
-"привилегии на сервисах, например такие, как статус владельца на всех\n"
-"каналах сети, и т. п.\n"
-"\n"
-"Эта опция не постоянная и должна использоваться только при крайней\n"
-"необходимости. Отключите ее сразу, как только перестанете нуждаться\n"
-"в ней."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s that you are really the owner of this\n"
-"nick. Many commands require you to authenticate yourself\n"
-"with this command before you use them. The password\n"
-"should be the same one you sent with the REGISTER\n"
-"command."
-msgstr ""
-"Синтаксис: IDENTIFY [account] пароль\n"
-"\n"
-"Позволяет вам идентифицироваться на %s к зарегистрированному\n"
-"ранее нику. Большинство сервисных команд, такие как SET, OP, BAN\n"
-"и т. д., требуют идентификации перед использованием. В качестве\n"
-"пароля вы должны указать тот самый пароль, который указывали при\n"
-"регистрации вашего ника."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s to invite you or an optionally specified\n"
-"nick into the given channel.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
-msgstr ""
-"Синтаксис: INVITE #канал\n"
-"\n"
-"Заставляет %s пригласить вас на указанный канал.\n"
-"\n"
-"По-умолчанию, данная команда может быть использована AOP'ами или\n"
-"лицами с уровнем доступа 5 и выше."
-
-#, fuzzy, c-format
-msgid ""
-"Tells %s to remove all bans preventing you or the given\n"
-"user from entering the given channel. If no channel is\n"
-"given, all bans affecting you in channels you have access\n"
-"in are removed.\n"
-" \n"
-"By default, limited to AOPs or those with level 5 access and above\n"
-"on the channel."
-msgstr ""
-"Синтаксис: UNBAN #канал [nick]\n"
-"\n"
-"Remove all bans preventing a user from entering a channel\n"
-"user from entering the given channel.\n"
-"\n"
-"По-умолчанию, данная команда может быть использована AOP'ами\n"
-"или лицами с уровнем доступа 5 и выше."
-
-#, fuzzy
-msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
-"the real server of that name from connecting. The jupe\n"
-"may be removed using a standard SQUIT. If a reason is\n"
-"given, it is placed in the server information field;\n"
-"otherwise, the server information field will contain the\n"
-"text \"Juped by <nick>\", showing the nickname of the\n"
-"person who jupitered the server."
-msgstr ""
-"Синтаксис: JUPE сервер [причина]\n"
-"\n"
-"Позволяет \"джупнуть\" указанный сервер с указанной причиной.\n"
-"В данном случае эффект джупа состоит в следующем: сервисы посылают\n"
-"SQUIT указанному серверу, тем самым отключая его от сети, а затем\n"
-"тут же создают виртуальный сервер с тем же именем, и причиной в\n"
-"качестве описания сервера (server description). Данный фальшивый\n"
-"сервер не позволит присоединиться к сети реальному, джупнутому\n"
-"серверу. Отменить эффект вы можете путем SQUIT'а виртуальной копии\n"
-"джупнутого сервера.\n"
-"Примечание: параметр причина является не обязательным, если вы его\n"
-"не укажете, будет использована стандартная, вида: \"Juped by <ник>\"."
-
-msgid "Tells you about the last time a user was seen"
-msgstr ""
-
-#, fuzzy
-msgid "Terminate Services WITHOUT saving"
-msgstr " SHUTDOWN Завершить работу сервисов с сохранением базы данных"
-
-#, fuzzy
-msgid "Terminate services with save"
-msgstr " SHUTDOWN Завершить работу сервисов с сохранением базы данных"
-
-msgid "Text"
-msgstr ""
-
-msgid ""
-"The ACCESS ADD command adds the given mask to the\n"
-"access list with the given user level; if the mask is\n"
-"already present on the list, its access level is changed to\n"
-"the level specified in the command. The level specified\n"
-"may be a numerical level or the name of a privilege (eg AUTOOP).\n"
-"When a user joins the channel the access they receive is from the\n"
-"highest level entry in the access list."
-msgstr ""
-
-msgid ""
-"The ACCESS DEL command removes the given nick from the\n"
-"access list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-"You may remove yourself from an access list, even if you\n"
-"do not have access to modify that list otherwise."
-msgstr ""
-
-msgid ""
-"The ACCESS LIST command displays the access list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" ACCESS #channel LIST 2-5,7-9\n"
-" Lists access entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The ACCESS VIEW command displays the access list similar\n"
-"to ACCESS LIST but shows the creator and last used time.\n"
-" \n"
-"The ACCESS CLEAR command clears all entries of the\n"
-"access list."
-msgstr ""
-
-msgid ""
-"The CLEAR command clears the channel access list. This requires channel "
-"founder access."
-msgstr ""
-
-#, c-format
-msgid ""
-"The CLEAR command lets you clean the database by removing all entries from "
-"the\n"
-"database that were added within time.\n"
-" \n"
-"Example:\n"
-" %s CLEAR 30m\n"
-" Will remove all entries that were added within the last 30 minutes."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The DEL command removes the given word from the\n"
-"bad words list. If a list of entry numbers is given, those\n"
-"entries are deleted. (See the example for LIST below.)\n"
-" \n"
-"The LIST command displays the bad words list. If\n"
-"a wildcard mask is given, only those entries matching the\n"
-"mask are displayed. If a list of entry numbers is given,\n"
-"only those entries are shown; for example:\n"
-" #channel LIST 2-5,7-9\n"
-" Lists bad words entries numbered 2 through 5 and\n"
-" 7 through 9.\n"
-" \n"
-"The CLEAR command clears all entries from the\n"
-"bad words list."
-msgstr ""
-"Синтаксис: HOP #канал ADD ник\n"
-" HOP #канал DEL {ник | номер_записи | список_записей}\n"
-" HOP #канал LIST [маска | список_записей]\n"
-" HOP #канал CLEAR\n"
-"\n"
-"Позволяет управлять списком HOP'ов (полуоператоров) вашего канала.\n"
-"Привилегии HOP'а дают пользователю возможность получить статус хопа\n"
-"сразу при входе на канал, или запросить его вручную, через сервисы.\n"
-"\n"
-"Команда HOP ADD добавляет указанный ник в список HOP'ов.\n"
-"\n"
-"Команда HOP DEL удаляет указанный ник из списка HOP'ов. В качестве\n"
-"параметра вы можете указать не только ник, но и конкретный номер\n"
-"записи или список записей (см. примеры использования LIST ниже).\n"
-"\n"
-"Команда HOP LIST выводит текущий список HOP'ов канала. В качестве\n"
-"дополнительного параметра, вы можете указать символьную маску, что\n"
-"позволит вам получить список с конкретными никами, попадающими под\n"
-"эту маску, или же, вы можете указать список записей.\n"
-"\n"
-"Например:\n"
-"\n"
-" HOP #канал LIST 2-5,7-9\n"
-" отобразит все записи со 2-ой по 5-ую, и с 7-ой по 9-ю.\n"
-" HOP #канал LIST *vas*\n"
-" отобразит все записи, которые содержат подстроку \"vas\"\n"
-"\n"
-"Команда HOP CLEAR позволяет полностью очистить список HOP'ов.\n"
-"\n"
-"Команды HOP ADD, HOP DEL и HOP LIST могут использовать AOP'ы\n"
-"канала или выше, команду HOP CLEAR может использовать только\n"
-"владелец канала.\n"
-"\n"
-"Помните, что данная команда работает только в случае использования\n"
-"системы привилегий xOP. Если вы используете систему LEVELS, все\n"
-"изменения списка доступа канала должны производится посредством\n"
-"команды ACCESS. Для более подробной информации по использованию\n"
-"команды ACCESS и системы привилегий xOP см. справочную информацию\n"
-"по /msg %s HELP ACCESS и /msg %s HELP SET XOP."
-
-msgid ""
-"The ENTRYMSG ADD command adds the given message to\n"
-"the list of messages shown to users when they join\n"
-"the channel."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG CLEAR command clears all entries from\n"
-"the list of messages shown to users when they join\n"
-"the channel, effectively disabling entry messages."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG DEL command removes the specified message from\n"
-"the list of messages shown to users when they join\n"
-"the channel. You can remove a message by specifying its number\n"
-"which you can get by listing the messages as explained below."
-msgstr ""
-
-msgid ""
-"The ENTRYMSG LIST command displays a listing of messages\n"
-"shown to users when they join the channel."
-msgstr ""
-
-msgid "The IMMED option is not available on this network."
-msgstr "Возможность установки режима IMMED в вашей IRC-сети недоступна."
-
-#, fuzzy, c-format
-msgid ""
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-" \n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it). Use LEVELS SET founder to make a level\n"
-"founder only.\n"
-" \n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel.\n"
-" \n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
-msgstr ""
-"Синтаксис: LEVELS #канал SET тип [уровень|FOUNDER]\n"
-" LEVELS #канал {DIS | DISABLE} тип\n"
-" LEVELS #канал LIST\n"
-" LEVELS #канал RESET\n"
-"\n"
-"The LEVELS command allows fine control over the meaning of\n"
-"the numeric access levels used for channels. With this\n"
-"command, you can define the access level required for most\n"
-"of %s's functions. (The SET FOUNDER and this command\n"
-"are always restricted to the channel founder.)\n"
-"\n"
-"LEVELS SET allows the access level for a function or group of\n"
-"functions to be changed. LEVELS DISABLE (or DIS for short)\n"
-"disables an automatic feature or disallows access to a\n"
-"function by anyone, INCLUDING the founder (although, the founder\n"
-"can always reenable it).\n"
-"\n"
-"LEVELS LIST shows the current levels for each function or\n"
-"group of functions. LEVELS RESET resets the levels to the\n"
-"default levels of a newly-created channel (see\n"
-"HELP ACCESS LEVELS).\n"
-"\n"
-"For a list of the features and functions whose levels can be\n"
-"set, see HELP LEVELS DESC."
-
-msgid ""
-"The LIST command allows you to list existing entries on the channel access "
-"list.\n"
-"If a mask is given, the mask is wildcard matched against all existing "
-"entries on the\n"
-"access list, and only those entries are returned. If a set of flags is "
-"given, only those\n"
-"on the access list with the specified flags are returned."
-msgstr ""
-
-msgid ""
-"The MODIFY command allows you to modify the access list. If the mask is\n"
-"not already on the access list it is added, then the changes are applied.\n"
-"If the mask has no more flags, then the mask is removed from the access "
-"list.\n"
-"Additionally, you may use +* or -* to add or remove all flags, respectively. "
-"You are\n"
-"only able to modify the access list if you have the proper permission on the "
-"channel,\n"
-"and even then you can only give other people access to the equivalent of "
-"what your access is."
-msgstr ""
-
-msgid ""
-"The STATS command prints out statistics about stored nicks and memory usage."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
-"after registering if it isn't the default setting already."
-msgstr ""
-"Используйте команду /msg %s SET EMAIL email-адрес чтобы установить email-"
-"адрес.\n"
-"Не волнуйтесь, данный email-адрес знать будете лишь вы и Администрация сети."
-
-#, c-format
-msgid ""
-"The %s command allows users to configure logging settings\n"
-"for their channel. If no parameters are given this command\n"
-"lists the current logging methods in place for this channel.\n"
-" \n"
-"Otherwise, command must be a command name, and method\n"
-"is one of the following logging methods:\n"
-" \n"
-" MESSAGE [status], NOTICE [status], MEMO\n"
-" \n"
-"Which are used to message, notice, and memo the channel respectively.\n"
-"With MESSAGE or NOTICE you must have a service bot assigned to and joined\n"
-"to your channel. Status may be a channel status such as @ or +.\n"
-" \n"
-"To remove a logging method use the same syntax as you would to add it.\n"
-" \n"
-"Example:\n"
-" %s #anope chanserv/access MESSAGE @\n"
-" Would message any channel operators whenever someone used the\n"
-" ACCESS command on ChanServ on the channel."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The %s list for %s is full."
-msgstr "Приветствие для %s удалено."
-
-#, fuzzy, c-format
-msgid "The %s list has been cleared."
-msgstr "Список AKILL'ов полностью очищен."
-
-msgid "The AKILL list has been cleared."
-msgstr "Список AKILL'ов полностью очищен."
-
-#, fuzzy, c-format
-msgid "The Defcon level is now at: %d"
-msgstr "Уровень DEFCON теперь равен %d"
-
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr ""
-"С этого момента, email-адрес ника %s будет скрыт из информации по %s INFO."
-
-#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr ""
-"Теперь, email-адрес ника %s будет показываться в информации по %s INFO."
-
-msgid "The available flags are:"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"The defcon system can be used to implement a pre-defined\n"
-"set of restrictions to services useful during an attempted\n"
-"attack on the network."
-msgstr ""
-"Синтаксис: DEFCON [1|2|3|4|5]\n"
-"\n"
-"Система DEFCON позволяет вам устанавливать определенные глобальные\n"
-"ограничения в сети со стороны сервисов. Данные ограничения могут\n"
-"касаться не только работы самих сервисов, но и функционирования сети\n"
-"в целом, что, порою, весьма полезно при разного рода атаках на сеть."
-
-#, c-format
-msgid "The email address %s has reached its usage limit of %d users."
-msgstr ""
-
-#, c-format
-msgid "The email address %s has reached its usage limit of 1 user."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The entry message list for %s is full."
-msgstr "Приветствие для %s удалено."
-
-msgid "The following feature/function names are available:"
-msgstr ""
-
-msgid ""
-"The given mask may also be a channel, which will use the\n"
-"access list from the other channel up to the given level."
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"The host %s currently has %d sessions with a limit of %d because it matches "
-"entry: %s."
-msgstr ""
-"Количество сессий с хоста %s: %d, допустимый максимум для данного хоста: %d"
-
-#, c-format
-msgid "The last memo you sent to %s (sent on %s) has been read."
-msgstr ""
-"Последнее сообщение, которое вы посылали для %s (а было это %s) уже "
-"прочитано."
-
-#, c-format
-msgid "The last memo you sent to %s (sent on %s) has not yet been read."
-msgstr ""
-"Последнее сообщение, которое вы посылали для %s (а было это %s) еще не "
-"прочитано."
-
-#, c-format
-msgid "The last quit message of %s will now be hidden from %s INFO displays."
-msgstr ""
-"Последнее quit-сообщение для %s теперь будет скрыто из информации по %s INFO."
-
-#, c-format
-msgid "The last quit message of %s will now be shown in %s INFO displays."
-msgstr ""
-"Последнее quit-сообщение для %s теперь будет показываться в информации по %s "
-"INFO."
-
-#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be hidden from %s INFO displays."
-msgstr ""
-"Последняя маска (идент@хост) для %s теперь будет скрыта из информации по %s "
-"INFO."
-
-#, c-format
-msgid ""
-"The last seen user@host mask of %s will now be shown in %s INFO displays."
-msgstr ""
-"Последняя маска (идент@хост) для %s теперь будет показываться в информации "
-"по %s INFO."
-
-#, fuzzy, c-format
-msgid "The limit on %s is not valid."
-msgstr "Лимит сообщений для %s не может быть изменен."
-
-msgid "The mask must contain at least one non wildcard character."
-msgstr ""
-
-#, c-format
-msgid "The memo limit for %s may not be changed."
-msgstr "Лимит сообщений для %s не может быть изменен."
-
-#, fuzzy, c-format
-msgid "The mode lock list of %s is full."
-msgstr "Приветствие для %s удалено."
-
-#, c-format
-msgid "The new display MUST be a nickname of the nickname group %s."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The new display is now %s."
-msgstr "Уровень DEFCON теперь равен %d"
-
-#, c-format
-msgid "The nick %s is now being changed to %s."
-msgstr "Ник пользователя %s был изменен на %s."
-
-msgid "The old information is the same as the new information specified."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "The oper info already exists on %s."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy, c-format
-msgid "The oper info list for %s is full."
-msgstr "Приветствие для %s удалено."
-
-#, c-format
-msgid ""
-"The services access status of %s will now be hidden from %s INFO displays."
-msgstr ""
-"Уровень доступа к сервисам для %s теперь будет скрыт из информации по %s "
-"INFO."
-
-#, c-format
-msgid "The services access status of %s will now be shown in %s INFO displays."
-msgstr ""
-"Уровень доступа к сервисам для %s теперь будет показываться в информации по "
-"%s INFO."
-
-#, fuzzy
-msgid "The session exception list is empty."
-msgstr " EXCEPTION Управление списком исключений из лимита сессий"
-
-msgid ""
-"The user with your nick has been removed. Use this command again\n"
-"to release services's hold on your nick."
-msgstr ""
-
-#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "%d сообщений на канале %s."
-
-msgid ""
-"There are no bots available at this time.\n"
-"Ask a Services Operator to create one!"
-msgstr ""
-"Список доступных ботов пуст.\n"
-"По вопросам создания ботов обращайтесь к Администраторам сервисов."
-
-msgid "There are no configured servers."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "There are no forbids of type %s."
-msgstr "%d сообщений на канале %s."
-
-#, fuzzy
-msgid "There are too many nicks in your group."
-msgstr " DELALL Удаление вирт. хоста у всех ников указанной группы"
-
-#, fuzzy, c-format
-msgid "There currently are no logging configurations for %s."
-msgstr " RELOAD Перезагрузка конфигурационного файла сервисов"
-
-#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "%d сообщение на канале %s."
-
-#, fuzzy, c-format
-msgid ""
-"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
-msgstr "Напишите /msg %s READ %d чтобы прочитать его."
-
-#, c-format
-msgid "There is no bot assigned to %s anymore."
-msgstr "Бот с канала %s успешно удален."
-
-msgid "There is no logon news."
-msgstr "Список новостей пуст."
-
-msgid "There is no oper news."
-msgstr "Список опер-новостей пуст."
-
-msgid "There is no random news."
-msgstr "Список случайных новостей пуст."
-
-#, fuzzy, c-format
-msgid "There is no such configuration block %s."
-msgstr " RELOAD Перезагрузка конфигурационного файла сервисов"
-
-#, fuzzy, c-format
-msgid "There is no such mode %s."
-msgstr "Список опер-новостей пуст."
-
-msgid "There's no email address set for your nick."
-msgstr "Для вашего ника не установлен email-адрес."
-
-#, fuzzy, c-format
-msgid "This channel has been forbidden: %s"
-msgstr "Этот канал был зарегистрирован с помощью %s"
-
-#, fuzzy
-msgid "This channel has been suspended."
-msgstr "Использование данного канала запрещено."
-
-#, fuzzy
-msgid "This channel is suspended."
-msgstr "Использование данного канала запрещено."
-
-msgid "This channel may not be used."
-msgstr "Использование данного канала запрещено."
-
-msgid ""
-"This command allows managing DNS zones used for controlling what servers "
-"users\n"
-"are directed to when connecting. Omitting all parameters prints out the "
-"status of\n"
-"the DNS zone.\n"
-" \n"
-"ADDZONE adds a zone, eg us.yournetwork.tld. Servers can then be added to "
-"this\n"
-"zone with the ADDSERVER command.\n"
-" \n"
-"The ADDSERVER command adds a server to the given zone. When a query is done, "
-"the\n"
-"zone in question is served if it exists, else all servers in all zones are "
-"served.\n"
-"A server may be in more than one zone.\n"
-" \n"
-"The ADDIP command associates an IP with a server.\n"
-" \n"
-"The POOL and DEPOOL commands actually add and remove servers to their given "
-"zones."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command allows users to set the vhost of their\n"
-"CURRENT nick to be the vhost for all nicks in the same\n"
-"group."
-msgstr ""
-"Синтаксис: GROUP\n"
-"\n"
-"Эта команда позволяет пользователям установить виртуальный хост\n"
-"с их ТЕКУЩЕГО ника на все ники группы."
-
-msgid ""
-"This command also creates a new group for your nickname,\n"
-"that will allow you to register other nicks later sharing\n"
-"the same configuration, the same set of memos and the\n"
-"same channel privileges."
-msgstr ""
-
-#, c-format
-msgid "This command is an alias to the command %s."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command is used by several commands as a way to confirm\n"
-"changes made to your account.\n"
-" \n"
-"This is most commonly used to confirm your email address once\n"
-"you register or change it.\n"
-" \n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-msgstr ""
-"Синтаксис: CONFIRM auth-код\n"
-"\n"
-"Данная команда необходима, что бы завершить второй шаг регистрации\n"
-"ника - подтверждение. После выполнения данного тербования, ваш ник\n"
-"будет зарегистрирован на %s.\n"
-"Кодовая фраза, которая указывается в качестве параметра, высылается\n"
-"на ваш e-mail в первой части процесса регистрации ника. Для более\n"
-"подробной информации см. /msg %s HELP REGISTER\n"
-"\n"
-"This is also used after the RESETPASS command has been used to\n"
-"force identify you to your nick so you may change your password."
-
-#, fuzzy
-msgid "This command lists information about the specified loaded module."
-msgstr ""
-"Синтаксис: MODINFO имя_файла\n"
-"\n"
-"Выводит подробную информацию о конкретном загруженном модуле."
-
-#, fuzzy
-msgid ""
-"This command lists registered vhosts to the operator.\n"
-"If a key is specified, only entries whose nick or vhost match\n"
-"the pattern given in key are displayed e.g. Rob* for all\n"
-"entries beginning with \"Rob\"\n"
-"If a #X-Y style is used, only entries between the range of X\n"
-"and Y will be displayed, e.g. #1-3 will display the first 3\n"
-"nick/vhost entries."
-msgstr ""
-"Синтаксис: LIST [<маска>|<#X-Y>]\n"
-"\n"
-"Выводит список всех виртуальных хостов и ников, на которые эти хосты\n"
-"установлены.\n"
-"\n"
-"В качестве дополнительного параметра, вы можете указать маску поиска,\n"
-"что позволит вам получить только совпадающие по символьной маске\n"
-"записи. Помимо этого, вы, так же, можете указать спискок записей в\n"
-"формате #X-Y, где X - номер стартовой запись, а Y - конечной.\n"
-"\n"
-"Например:\n"
-"\n"
-" LIST *invis*\n"
-" выведет список записей, ник или вирт. хост которых содержит\n"
-" подстроку *invis* (invisible, covinis и т. д.)\n"
-"\n"
-" LIST #2-5\n"
-" выведет список записей со 2-ой по 5-ю.\n"
-"\n"
-"Лимит одновременно показываемых записей ограничен числом, указанным\n"
-"в конфигурационном файле сервисов директивой NSListMax."
-
-#, fuzzy
-msgid ""
-"This command loads the module named modname from the modules\n"
-"directory."
-msgstr ""
-"Синтаксис: MODLOAD имя_файла\n"
-"\n"
-"Позволяет загрузить какой-либо дополнительный модуль из директории\n"
-"с модулями (modules/). "
-
-#, fuzzy
-msgid ""
-"This command makes your nickname join the target nickname's\n"
-"group. password is the password of the target nickname.\n"
-" \n"
-"Joining a group will allow you to share your configuration,\n"
-"memos, and channel privileges with all the nicknames in the\n"
-"group, and much more!\n"
-" \n"
-"A group exists as long as it is useful. This means that even\n"
-"if a nick of the group is dropped, you won't lose the\n"
-"shared things described above, as long as there is at\n"
-"least one nick remaining in the group.\n"
-" \n"
-"You may be able to use this command even if you have not registered\n"
-"your nick yet. If your nick is already registered, you'll\n"
-"need to identify yourself before using this command.\n"
-" \n"
-"It is recommended to use this command with a non-registered\n"
-"nick because it will be registered automatically when\n"
-"using this command. You may use it with a registered nick (to\n"
-"change your group) only if your network administrators allowed\n"
-"it.\n"
-" \n"
-"You can only be in one group at a time. Group merging is\n"
-"not possible.\n"
-" \n"
-"Note: all the nicknames of a group have the same password."
-msgstr ""
-"Синтаксис: GROUP главный_ник пароль\n"
-"\n"
-"Данная команда позволяет вам присоединить ваш текущий ник к группе\n"
-"главного_ника. В качестве пароля вам необходимо указать пароль\n"
-"главного ника.\n"
-"\n"
-"Использование групп дает вам возможность объединить несколько ников\n"
-"в одну группу с едиными настройками и привилегиями на каналах,\n"
-"едиными ассоциированными данными и паролем, единым списком сообщений.\n"
-"Группа существует и активна пока используется. Даже если вы удалите\n"
-"один из ников группы, все вышеописанные данные (ну и сама регистрация)\n"
-"будут существовать до тех пор, пока в группе есть хотя бы 1 ник.\n"
-"\n"
-"Вы можете использовать эту команду даже если ваш текущий ник все еще\n"
-"незарегистрирован. В противном случае, для использования описываемой\n"
-"команды вам необходимо будет идентифицироваться к группируемому нику.\n"
-"См. /msg %s HELP IDENTIFY для более подробной информации.\n"
-"Примечание: возможность группировки уже зарегистрированных ников\n"
-"может быть недоступна в вашей IRC-сети.\n"
-"\n"
-"Оптимальным вариантом будет объединение еще не зарегистрированных\n"
-"ников с уже зарегистрированным (они указываются как главный ник).\n"
-"В противном случае, все данные группируемого ника будут уничтожены\n"
-"в процессе объединения двух ников. Именно поэтому, слияние групп -\n"
-"невозможно. Один зарегистрированный ник, не состоящий ни в одной\n"
-"группе - уже образует группу. И находится в двух группах этот ник\n"
-"никак неможет.\n"
-"Примечание 2: у всех ников в группе - единый пароль."
-
-msgid ""
-"This command manages your auto join list. When you identify\n"
-"you will automatically join the channels on your auto join list.\n"
-"Services Operators may provide a nick to modify other users'\n"
-"auto join lists."
-msgstr ""
-
-msgid ""
-"This command may not be used on this network because nickname ownership is "
-"disabled."
-msgstr ""
-
-#, fuzzy
-msgid "This command reloads the module named modname."
-msgstr ""
-"Синтаксис: MODLOAD имя_файла\n"
-"\n"
-"Позволяет загрузить какой-либо дополнительный модуль из директории\n"
-"с модулями (modules/). "
-
-msgid "This command retrieves the vhost requests."
-msgstr ""
-
-msgid ""
-"This command searches the Services logfiles for messages\n"
-"that match the given pattern. The day and limit argument\n"
-"may be used to specify how many days of logs to search\n"
-"and the number of replies to limit to. By default this\n"
-"command searches one week of logs, and limits replies\n"
-"to 50.\n"
-" \n"
-"For example:\n"
-" LOGSEARCH +21d +500l Anope\n"
-" Searches the last 21 days worth of logs for messages\n"
-" containing Anope and lists the most recent 500 of them."
-msgstr ""
-
-msgid ""
-"This command tells you what a users access is on a channel\n"
-"and what access entries, if any, they match. Additionally it\n"
-"will tell you of any auto kick entries they match. Usage of\n"
-"this command is limited to users who have the ability to modify\n"
-"access entries on the channel."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, and url. Everything else\n"
-"is reset. You may not ungroup yourself if there is only one nick in\n"
-"your group."
-msgstr ""
-"Syntax: UNGROUP [nick]\n"
-"This command ungroups your nick, or if given, the specificed nick,\n"
-"from the group it is in. The ungrouped nick keeps its registration\n"
-"time, password, email, greet, language, url, and icq. Everything\n"
-"else is reset. You may not ungroup yourself if there is only one\n"
-"nick in your group."
-
-#, fuzzy
-msgid "This command unloads the module named modname."
-msgstr ""
-"Синтаксис: MODLOAD имя_файла\n"
-"\n"
-"Позволяет загрузить какой-либо дополнительный модуль из директории\n"
-"с модулями (modules/). "
-
-msgid "This command will resend you the registration confirmation email."
-msgstr ""
-
-#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "This nickname has been forbidden: %s"
-msgstr "Дополнительно: этот ник находится в режиме саспенда по причине: %s"
-
-#, fuzzy, c-format
-msgid "This nickname has been recovered by %s."
-msgstr "Дополнительно: этот ник находится в режиме саспенда по причине: %s"
-
-#, c-format
-msgid ""
-"This nickname has been recovered by %s. If you did not do\n"
-"this then %s may have your password, and you should change it."
-msgstr ""
-
-#, fuzzy
-msgid "This nickname has been registered; you may not use it."
-msgstr "Этот канал был зарегистрирован с помощью %s"
-
-#, fuzzy
-msgid "This nickname is suspended."
-msgstr "Использование данного канала запрещено."
-
-#, c-format
-msgid ""
-"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
-"please choose a different nick."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr ""
-"Сообщение %d от %s (%s). Чтобы удалить его, напишите команду: /msg %s DEL %s "
-"%d"
-
-#, fuzzy, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr ""
-"Сообщение %d от %s (%s). Чтобы удалить его, напишите команду: /msg %s DEL %s "
-"%d"
-
-msgid "To protect ops against bot kicks"
-msgstr ""
-
-msgid "To protect voices against bot kicks"
-msgstr ""
-
-msgid ""
-"To search for channels starting with #, search for the channel\n"
-"name without the #-sign prepended (anope instead of #anope)."
-msgstr ""
-"Что бы найти канал, начинающийся с символа #, просто укажите его\n"
-"название без #. Например anope вместо #anope."
-
-#, fuzzy, c-format
-msgid "Too many results for %s."
-msgstr "Список доступа для %s:"
-
-#, c-format
-msgid "Top %i of %s"
-msgstr ""
-
-#, fuzzy
-msgid "Topic"
-msgstr "Блокировка топика"
-
-#, fuzzy
-msgid "Topic lock"
-msgstr "Блокировка топика"
-
-#, fuzzy, c-format
-msgid "Topic lock option for %s is now off."
-msgstr "Режим блокировки топика для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Topic lock option for %s is now on."
-msgstr "Режим блокировки топика для канала %s активирован."
-
-#, fuzzy
-msgid "Topic retention"
-msgstr "Хранение топика"
-
-#, fuzzy, c-format
-msgid "Topic retention option for %s is now off."
-msgstr "Режим хранения топика для канала %s активирован."
-
-#, fuzzy, c-format
-msgid "Topic retention option for %s is now on."
-msgstr "Режим хранения топика для канала %s активирован."
-
-msgid "Topic set by"
-msgstr ""
-
-msgid "Turn caps lock OFF!"
-msgstr "Выключи CapsLOCK!"
-
-#, fuzzy
-msgid "Turn chanstats statistics on or off"
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-#, fuzzy
-msgid "Turn nickname security on or off"
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-#, fuzzy
-msgid "Turn protection on or off"
-msgstr " KILL активирование/деактивирование режима защиты"
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's privacy option on or off for the nick.\n"
-"With PRIVATE set, the nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows the nickname can still get\n"
-"information on it using the INFO command.)"
-msgstr ""
-"Синтаксис: SASET ник PRIVATE {ON | OFF}\n"
-"\n"
-"Активируетдеактивирует опцию приватности указанного ника.\n"
-"Включенная таким образом PRIVATE скрывает отображение ника в\n"
-"списках по %s LIST.\n"
-"Примечание: тем не менее любой, кто знает точное написание ника,\n"
-"имеет возможность получить информацию о нем используя команду INFO."
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's privacy option on or off for your nick.\n"
-"With PRIVATE set, your nickname will not appear in\n"
-"nickname lists generated with %s's LIST command.\n"
-"(However, anyone who knows your nickname can still get\n"
-"information on it using the INFO command.)"
-msgstr ""
-"Синтаксис: SET PRIVATE {ON | OFF}\n"
-"\n"
-"Активируетдеактивирует опцию приватности вашего ника на %s.\n"
-"Включенная таким образом PRIVATE скрывает ваш ник из информации\n"
-"по %s LIST.\n"
-"Примечание: тем не менее, любой, кто знает ваш ник, имеет возможность\n"
-"получить информацию о вас используя команду INFO."
-
-#, fuzzy, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Синтаксис: SET SECURE {ON | OFF}\n"
-"\n"
-"Активирует/деактивирует режим безопасности для вашего ника. При\n"
-"включенной опции SECURE вы должны идентифицироваться на %s \n"
-"с помощью пароля, чтобы подтвердить что именно вы владелец текущего\n"
-"используемого вами ника. При этом на список хостмасок ника сервисы\n"
-"внимания не обращают.\n"
-"Отключение этой опции позволит вам идентифицироваться на %s\n"
-"через список масок ника, однако, максимально допустимый статус в\n"
-"данном случае будет равняться 2.\n"
-"\n"
-"Стоит также заметить, что сервисы не будут принудительно менять ваш\n"
-"ник, если в ACCESS-списке зарегистрированного ника есть хотя бы одна\n"
-"хостмаска, совпадающая с вашей текущей. Режим опции KILL при этом\n"
-"значения не имеет."
-
-#, fuzzy
-msgid "Turns chanstats channel statistics ON or OFF for this user."
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-#, fuzzy
-msgid "Turns chanstats statistics ON or OFF."
-msgstr " SECURE активирование/деактивирование режима безопасности"
-
-#, fuzzy, c-format
-msgid ""
-"Turns the automatic protection option for the nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take the nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-msgstr ""
-"Синтаксис: SASET ник KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Активирует/деактивирует автоматическую защиту для указанного ника.\n"
-"Активирование защиты ника позволяет вам лимитировать период времени\n"
-"на ввод пароля идентификации. ON выставляет период в 60 секунд,\n"
-"по истечении которого %s принудительно сменит ник лже-владельца,\n"
-"попытавшегося взять указанный ник.\n"
-"\n"
-"Параметр QUICK позволяет назначить 20-секундный период.\n"
-"Параметр IMMED позволяет отключить этот период вообще. Помните,\n"
-"что активирование данной опции может привести к тому, что указанный\n"
-"ник не сможет взять никто! Не используйте эту опцию без крайней\n"
-"необходимости, а перед ее включением убедитесь, что ACCESS-список\n"
-"указанного ника содержит хотя бы одну из хостмасок, с которой его\n"
-"владелец заходит в IRC.\n"
-"Примечание: возможность установки метода защиты IMMED может быть\n"
-"отключена в вашей IRC-сети."
-
-#, fuzzy, c-format
-msgid ""
-"Turns the automatic protection option for your nick\n"
-"on or off. With protection on, if another user\n"
-"tries to take your nick, they will be given one minute to\n"
-"change to another nick, after which %s will forcibly change\n"
-"their nick.\n"
-" \n"
-"If you select QUICK, the user will be given only 20 seconds\n"
-"to change nicks instead of the usual 60. If you select\n"
-"IMMED, the user's nick will be changed immediately without being\n"
-"warned first or given a chance to change their nick; please\n"
-"do not use this option unless necessary. Also, your\n"
-"network's administrators may have disabled this option."
-msgstr ""
-"Синтаксис: SET KILL {ON | QUICK | IMMED | OFF}\n"
-"\n"
-"Активирует/деактивирует автоматическую защиту для вашего ника.\n"
-"Активирование защиты ника позволяет вам лимитировать период времени\n"
-"на ввод пароля для идентификации. ON выставляет период в 60 секунд,\n"
-"по истечении которого сервисы принудительно сменят ник лже-владельца\n"
-"(или ваш, если вы не успели ввести пароль вовремя).\n"
-"\n"
-"Параметр QUICK позволяет назначить 20-секундный период.\n"
-"\n"
-"Параметр IMMED позволяет отключить этот период вообще. Помните,\n"
-"что активирование этой опции может привести к потере вашего ника!\n"
-"Не используйте эту опцию без крайней на то необходимости, а перед ее\n"
-"включением, убедитесь, что ACCESS-список вашего ника содержит хотя\n"
-"бы одну из хостмасок, которая совпадает с вашей текущей.\n"
-"Примечание: возможность установки метода защиты IMMED может быть\n"
-"отключена в вашей IRC-сети."
-
-msgid "Type"
-msgstr ""
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option."
-msgstr ""
-"Для более подробной информации о какой-либо конкретной опции, см.\n"
-"справку по /msg %s HELP опция"
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option.\n"
-" \n"
-"Note: access to this command is controlled by the\n"
-"level SET."
-msgstr ""
-"Чтобы получить справочную информацию по отдельно взятой опции\n"
-"воспользуйтесь командой /msg %s HELP SASET опция\n"
-"Помните, вы должны указать ник, опции которого вы хотите изменить."
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information\n"
-"on a specific option. The options will be set on the given\n"
-"nickname."
-msgstr ""
-"Чтобы получить справочную информацию по отдельно взятой опции\n"
-"воспользуйтесь командой /msg %s HELP SASET опция\n"
-"Помните, вы должны указать ник, опции которого вы хотите изменить."
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s HELP %s option for more information on a\n"
-"particular option."
-msgstr ""
-"Для более подробной информации о какой-либо конкретной опции, см.\n"
-"справку по /msg %s HELP опция"
-
-#, fuzzy, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
-msgstr ""
-"Используйте команду /msg %s SET EMAIL email-адрес чтобы установить email-"
-"адрес.\n"
-"Не волнуйтесь, данный email-адрес знать будете лишь вы и Администрация сети."
-
-#, fuzzy
-msgid "Un-Load a module"
-msgstr " MODUNLOAD Выгрузить модуль"
-
-#, fuzzy, c-format
-msgid "Unable to find regex engine %s."
-msgstr "Невозможно выгрузить модуль %s"
-
-#, fuzzy, c-format
-msgid "Unable to load module %s."
-msgstr "Невозможно загрузить модуль %s"
-
-#, fuzzy, c-format
-msgid "Unable to remove module %s."
-msgstr "Невозможно выгрузить модуль %s"
-
-#, fuzzy
-msgid "Unassigns a bot from a channel"
-msgstr "UNASSIGN Снять бота с указанного канала"
-
-#, fuzzy
-msgid ""
-"Unassigns a bot from a channel. When you use this command,\n"
-"the bot won't join the channel anymore. However, bot\n"
-"configuration for the channel is kept, so you will always\n"
-"be able to reassign a bot later without having to reconfigure\n"
-"it entirely."
-msgstr ""
-"Синтаксис: UNASSIGN #канал\n"
-"\n"
-"Позволяет снять бота с указанного канала. Канал будет удален из базы\n"
-"данных бота и сам бот больше на него заходить не будет, однако, все\n"
-"данные и настройки канала буду сохранены. В дальнейшем, это позволит\n"
-"вам переназначить бота на канал с восстановлением всех старых настроек."
-
-#, fuzzy
-msgid "Underlines kicker"
-msgstr "Цензор подчеркиваний.: %s"
-
-#, fuzzy
-msgid "Unknown SET option."
-msgstr "Неизвестная SASET-опция %s."
-
-#, fuzzy, c-format
-msgid "Unknown STATS option: %s"
-msgstr "Неизвестный STATS-параметр %s."
-
-#, fuzzy, c-format
-msgid "Unknown command %s."
-msgstr "Неизвестная опция %s."
-
-#, fuzzy, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Неизвестная команда %s. Список команд доступен по %s%s HELP"
-
-#, fuzzy, c-format
-msgid "Unknown mode character %c ignored."
-msgstr "Неизвестный режим %c - проигнорирован."
-
-#, fuzzy, c-format
-msgid "Unknown parameter: %s"
-msgstr "SET опция параметры"
-
-msgid "Unpooled"
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Unregisters the named channel. Can only be used by\n"
-"the channel founder."
-msgstr ""
-"Синтаксис: DROP #канал\n"
-"\n"
-"Удаляет указанный канал из базы данных сервисов. Использовать DROP\n"
-"может лишь владелец канала."
-
-#, fuzzy
-msgid ""
-"Unregisters the specified channel. Only Services Operators\n"
-"can drop a channel of which they are not the founder of."
-msgstr ""
-"Синтаксис: DROP #канал\n"
-"\n"
-"Удаляет указанный канал из базы данных сервисов. Вы м ожете удалить\n"
-"только те каналы, которыми вы владеете.\n"
-"Как Администратор сервисов, вы можете удалить любой зарегистрированный\n"
-"канал сети без какой-либо идентификации к нему."
-
-#, fuzzy
-msgid "Unsuspend a given nick"
-msgstr " UNSUSPEND Снятие режима саспенда с ника"
-
-msgid "Unsuspends a nickname which allows it to be used again."
-msgstr ""
-
-msgid ""
-"Updates a selected nicks status modes on a channel. If nick is\n"
-"omitted then your status is updated. If channel is omitted then\n"
-"your channel status is updated on every channel you are in."
-msgstr ""
-
-#, fuzzy
-msgid "Updates a selected nicks status on a channel"
-msgstr " BAN Установка бана на канале"
-
-#, fuzzy
-msgid "Updates your current status, i.e. it checks for new memos"
-msgstr " UPDATE Обновление вашего текущего статуса на сервисах"
-
-#, fuzzy
-msgid ""
-"Updates your current status, i.e. it checks for new memos,\n"
-"sets needed channel modes and updates your vhost and\n"
-"your userflags (lastseentime, etc)."
-msgstr ""
-"Синтаксис: UPDATE\n"
-"Обновляет ваш текущий статус на сервисах, в частности, проверяет на\n"
-"наличие новых мемо-сообщений, устанавливает необходимые режимы на\n"
-"всех каналах, где у вас есть статус (ModeonID), обновляет ваши\n"
-"виртуальные хосты и настройки (дата последнего посещения IRC, и т.д.)."
-
-msgid "Updating databases."
-msgstr "Обновление баз данных..."
-
-#, c-format
-msgid "Uplink capab: %s"
-msgstr "Uplink capab: %s"
-
-#, c-format
-msgid "Uplink server: %s"
-msgstr "Uplink-сервер: %s"
-
-#, c-format
-msgid "Use the %s ALL command to list all commands and their descriptions."
-msgstr ""
-
-msgid "Used on"
-msgstr ""
-
-#, fuzzy
-msgid "Used to manage channels"
-msgstr "%s принудительно изменил ваши пользовательские режимы."
-
-#, fuzzy
-msgid "Used to manage the list of privileged users"
-msgstr " ACCESS Управление ACCESS-списком привилегий канала"
-
-msgid "Used to modify the channel status of you or other users"
-msgstr ""
-
-#, fuzzy
-msgid "User has been banned from the channel"
-msgstr "Вы были разбанены на канале %s."
-
-#, fuzzy, c-format
-msgid "User limit for %s removed."
-msgstr "Виртуальный хост для %s удален."
-
-#, fuzzy, c-format
-msgid "User limit for %s set to %d."
-msgstr "Лимит собщений для %s установлен на %d."
-
-#, fuzzy
-msgid "Users"
-msgstr "Список ботов:"
-
-#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr ""
-
-#, fuzzy
-msgid "Users list:"
-msgstr "Список ботов:"
-
-msgid "VHost"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "VHost for %s set to %s."
-msgstr "Виртуальный хост для %s установлен на %s."
-
-#, fuzzy, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "Виртуальный хост для %s установлен на %s@%s."
-
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s."
-msgstr "Виртуальный хост для группы %s установлен на %s."
-
-#, fuzzy, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "Виртуальный хост для группы %s установлен в %s@%s."
-
-msgid "VIEW host"
-msgstr ""
-
-#, fuzzy
-msgid "VIEW [mask | list | id]"
-msgstr "LIST [#канал] [список_записей | NEW]"
-
-msgid "VIEW [mask | list]"
-msgstr ""
-
-msgid "Value"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Value of %s:%s changed to %s"
-msgstr "Все права на владение каналом %s успешно переданы пользователю %s."
-
-msgid "Vhost"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Vhost for %s removed."
-msgstr "Виртуальный хост для %s удален."
-
-#, fuzzy
-msgid "View and change Services Operators"
-msgstr "%s is a services operator of type %s."
-
-msgid "View and change configuration file settings"
-msgstr ""
-
-#, fuzzy
-msgid "View the list of host sessions"
-msgstr " SESSION Просмотр количества сессий с указанного хоста"
-
-msgid "Voices protection"
-msgstr "Не кикать войсов"
-
-msgid "Watch your language!"
-msgstr "Следи за своим языком!"
-
-#, c-format
-msgid ""
-"When private is set, the channel will not appear in\n"
-"%s's %s command."
-msgstr ""
-
-#, fuzzy
-msgid ""
-"Without a parameter, displays information on the number of\n"
-"memos you have, how many of them are unread, and how many\n"
-"total memos you can receive.\n"
-" \n"
-"With a channel parameter, displays the same information for\n"
-"the given channel.\n"
-" \n"
-"With a nickname parameter, displays the same information\n"
-"for the given nickname. This is limited to Services\n"
-"Operators."
-msgstr ""
-"Синтаксис: INFO [ник | #канал]\n"
-"\n"
-"Без параметров, покажет общее количество сообщений, которое вы\n"
-"имеете, сколько из них непрочитано, и сколько всего сообщений вы\n"
-"можете принимать.\n"
-"\n"
-"Если указать канал, покажет ту же информацию об указанном канале.\n"
-"\n"
-"Если указать в качестве параметра ник, покажет ту же информацию об\n"
-"указанном нике.\n"
-"Данный параметр могут использовать только Администраторы сервисов."
-
-#, fuzzy
-msgid ""
-"Without a parameter, reverses the effect of the IDENTIFY\n"
-"command, i.e. make you not recognized as the real owner of the nick\n"
-"anymore. Note, however, that you won't be asked to reidentify\n"
-"yourself.\n"
-" \n"
-"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
-"to re-identify. This is limited to Services Operators."
-msgstr ""
-"Синтаксис: LOGOUT [ник [REVALIDATE]]\n"
-"\n"
-"Использованная без параметров, команда LOGOUT производит эффект,\n"
-"обратный эффекту команды IDENTIFY, то есть - деидентифицирует вас\n"
-"от используемого на данный момент ника. Тем не менее, сервисы не\n"
-"пошлют повторный запрос на идентификацию.\n"
-"\n"
-"Если в качестве параметра вы укажете ник - деидентифицирует указанный\n"
-"ник. Дополнительно указанный параметр REVALIDATE заставит сервисы\n"
-"послать дендинтифицированному нику запрос на переавторизацию.\n"
-"Использовать параметры ник и REVALIDATE могут лишь Администраторы\n"
-"сервисов."
-
-#, fuzzy
-msgid ""
-"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
-" \n"
-"With the AKILL option, displays the current size of the\n"
-"AKILL list and the current default expiry time.\n"
-" \n"
-"The RESET option currently resets the maximum user count\n"
-"to the number of users currently present on the network.\n"
-" \n"
-"The UPLINK option displays information about the current\n"
-"server Anope uses as an uplink to the network.\n"
-" \n"
-"The HASH option displays information about the hash maps.\n"
-" \n"
-"The ALL option displays all of the above statistics."
-msgstr ""
-"Синтаксис: STATS [AKILL | ALL | RESET | MEMORY | UPLINK]\n"
-"\n"
-"Использованная без параметров, команда покажет текущее количество\n"
-"пользователей сети, текущее кол-во IRC-операторов (за исключением\n"
-"самих сервисов), максимально зафиксированное число пользователей\n"
-"и время работы сервисов в сети.\n"
-"\n"
-"С параметром AKILL, покажет текущий размер списка AKILL'ов и время\n"
-"истечения AKILL'ов по-умолчанию (AKILL, SZLINE, ZGLINE, ZQLINE).\n"
-"\n"
-"Параметр RESET сбрасывает счетчик зафиксированного максимума \n"
-"пользователей сети.\n"
-"\n"
-"Параметр MEMORY выведет информацию об использовании сервисами\n"
-"оперативной памяти. Запросы подобной статистики могу затормозить\n"
-"работу сервисов на определенный промежуток времени, поэтому, не\n"
-"рекомендуется использовать параметр MEMORY слишком часто.\n"
-"\n"
-"Параметр UPLINK покажет информацию о сервере, к которому\n"
-"прилинкованы сервисы сети.\n"
-"\n"
-"Параметр ALL выведет общую статистику в комбинации с данными из\n"
-"MEMORY и UPLINK."
-
-msgid "Word"
-msgstr ""
-
-#, c-format
-msgid "You are already a member of the group of %s."
-msgstr "Вы уже состоите в группе %s."
-
-msgid "You are already identified."
-msgstr "Вы уже идентифицированы."
-
-#, fuzzy, c-format
-msgid "You are already in %s!"
-msgstr "You are already in %s! "
-
-#, fuzzy
-msgid "You are no longer a super admin."
-msgstr "Режим Супер-Администратора деактивирован."
-
-#, fuzzy
-msgid "You are not identified."
-msgstr "Вы уже идентифицированы."
-
-#, fuzzy
-msgid "You are not permitted to be on this channel."
-msgstr "Вам запрещено изменять свой лимит сообщений."
-
-msgid "You are not permitted to change your memo limit."
-msgstr "Вам запрещено изменять свой лимит сообщений."
-
-#, fuzzy
-msgid "You are not using a client certificate."
-msgstr "Вы уже идентифицированы."
-
-#, fuzzy
-msgid "You are now a super admin."
-msgstr "Режим Супер-Администратора активирован."
-
-msgid "You are now an IRC Operator."
-msgstr "Теперь вы IRC-оператор."
-
-#, fuzzy
-msgid "You are now identified for your nick. Change your password now."
-msgstr "You are now identified for your nick. Change your password now."
-
-#, c-format
-msgid "You are now in the group of %s."
-msgstr "Вы успешно внесены в группу %s."
-
-#, fuzzy, c-format
-msgid ""
-"You are over your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
-msgstr ""
-"Внимание: вы превысили лимит максимально допустимого числа хранимых "
-"сообщений (%d). Вы не сможете принимать новые сообщения, пока вы не удалите "
-"лишние."
-
-msgid "You can not NOOP Services."
-msgstr ""
-
-msgid ""
-"You can not disable the founder privilege because it would be impossible to "
-"reenable it at a later time."
-msgstr ""
-
-#, fuzzy
-msgid "You can not jupe an already juped server."
-msgstr "You can not jupe your services server or your uplink server."
-
-#, fuzzy
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
-msgstr "You can not jupe your services server or your uplink server."
-
-#, c-format
-msgid "You can not reload this module directly, instead reload %s."
-msgstr ""
-
-msgid "You can not request a receipt when sending a memo to yourself."
-msgstr ""
-"Вы не можете запросить информацию о получении, когда посылаете сообщение "
-"себе."
-
-#, fuzzy, c-format
-msgid "You can't %s yourself!"
-msgstr "Вы не можете закрыть свою сессию!"
-
-#, fuzzy
-msgid "You can't add a channel to its own access list."
-msgstr "Совпадающих записей в списке доступа канала %s не обнаружено."
-
-#, fuzzy, c-format
-msgid "You can't logout %s, they are a Services Operator."
-msgstr "Невозможно деидентифицировать %s так как он Администратор сервисов."
-
-#, fuzzy, c-format
-msgid "You cannot %s on this network."
-msgstr "Возможность удаления email-адреса в вашей IRC-сети недоступна."
-
-#, fuzzy, c-format
-msgid "You cannot set the %c flag."
-msgstr "You cannot use this command."
-
-#, c-format
-msgid "You cannot set the memo limit for %s higher than %d."
-msgstr "Вы не можете установить лимит сообщений для %s больше чем %d."
-
-#, c-format
-msgid "You cannot set your memo limit higher than %d."
-msgstr "Вы не можете установить лимит сообщений больше чем %d."
-
-#, fuzzy
-msgid "You cannot unassign bots while persist is set on the channel."
-msgstr "You can not unassign bots while persist is set on the channel."
-
-msgid "You cannot unset the e-mail on this network."
-msgstr "Возможность удаления email-адреса в вашей IRC-сети недоступна."
-
-msgid "You cannot use this command."
-msgstr "You cannot use this command."
-
-#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "На данный момент у вас имеется %d сообщений, %d из них не прочитано."
-
-#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "На данный момент у вас имеется %d сообщений, 1 из них не прочитано."
-
-#, c-format
-msgid "You currently have %d memos."
-msgstr "На данный момент у вас имеется %d сообщений."
-
-#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr ""
-"На данный момент у вас имеется %d сообщений, ни одно из них не прочитано."
-
-msgid "You currently have 1 memo, and it has not yet been read."
-msgstr "На данный момент у вас имеется 1 новое, непрочитанное сообщение."
-
-msgid "You currently have 1 memo."
-msgstr "На данный момент у вас имеется 1 сообщение."
-
-msgid "You currently have no memos."
-msgstr "На данный момент у вас нет сообщений."
-
-#, c-format
-msgid "You do not have access to set mode %c."
-msgstr ""
-
-#, c-format
-msgid "You do not have the access to change %s's modes."
-msgstr ""
-
-#, c-format
-msgid "You found me, %s!"
-msgstr ""
-
-#, c-format
-msgid "You have %d new memos."
-msgstr "Вам пришло %d новых сообщений."
-
-msgid "You have 1 new memo."
-msgstr "Вам пришло 1 новое сообщение."
-
-#, fuzzy, c-format
-msgid ""
-"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
-msgstr "Напишите /msg %s READ %d чтобы прочитать его."
-
-#, fuzzy, c-format
-msgid "You have been invited to %s by %s."
-msgstr "You have been invited to %s."
-
-#, c-format
-msgid "You have been invited to %s."
-msgstr "You have been invited to %s."
-
-#, fuzzy, c-format
-msgid "You have been logged in as %s."
-msgstr "Деидентификация выполнена успешно."
-
-#, fuzzy
-msgid "You have been logged out."
-msgstr "Деидентификация выполнена успешно."
-
-#, c-format
-msgid "You have been unbanned from %s."
-msgstr "Вы были разбанены на канале %s."
-
-#, fuzzy, c-format
-msgid "You have been unbanned from %d channels."
-msgstr "Вы были разбанены на канале %s."
-
-msgid "You have no limit on the number of memos you may keep."
-msgstr "У вас нет ограничения на количество хранимых сообщений."
-
-#, fuzzy
-msgid "You have no memos."
-msgstr "Вам пришло %d новых сообщений."
-
-#, fuzzy
-msgid "You have no new memos."
-msgstr "Вам пришло %d новых сообщений."
-
-#, fuzzy, c-format
-msgid ""
-"You have reached your maximum number of memos (%d). You will be unable to "
-"receive any new memos until you delete some of your current ones."
-msgstr ""
-"Внимание: вы достигли максимально допустимого числа хранимых сообщений (%d). "
-"Вы не сможете принимать новые сообщения, пока не удалите лишние."
-
-#, fuzzy, c-format
-msgid "You have regained control of %s."
-msgstr "You have been invited to %s."
-
-#, fuzzy
-msgid "You may drop any nick within your group."
-msgstr " DELALL Удаление вирт. хоста у всех ников указанной группы"
-
-#, c-format
-msgid "You may not (un)lock mode %c."
-msgstr ""
-
-#, fuzzy
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "Возможность удаления email-адреса в вашей IRC-сети недоступна."
-
-#, fuzzy
-msgid "You may not change the email of an unconfirmed account."
-msgstr "Возможность удаления email-адреса в вашей IRC-сети недоступна."
-
-#, fuzzy
-msgid "You may not change the password of other Services Operators."
-msgstr "Невозможно деидентифицировать %s так как он Администратор сервисов."
-
-#, fuzzy
-msgid "You may not drop other Services Operators' nicknames."
-msgstr "%s is a services operator of type %s."
-
-#, fuzzy
-msgid "You may not get the password of other Services Operators."
-msgstr "Невозможно деидентифицировать %s так как он Администратор сервисов."
-
-#, fuzzy
-msgid "You may not suspend other Services Operators' nicknames."
-msgstr "Невозможно деидентифицировать %s так как он Администратор сервисов."
-
-#, fuzzy
-msgid ""
-"You may view but not modify the access list of other Services Operators."
-msgstr "Невозможно деидентифицировать %s так как он Администратор сервисов."
-
-#, fuzzy
-msgid ""
-"You may view but not modify the certificate list of other Services Operators."
-msgstr "Невозможно деидентифицировать %s так как он Администратор сервисов."
-
-#, c-format
-msgid "You might see yourself in the mirror, %s."
-msgstr ""
-
-msgid "You must assign a bot to the channel before using this command."
-msgstr ""
-
-msgid "You must be a channel operator to register the channel."
-msgstr "Чтобы зарегистрировать канал, вы должны быть его оператором."
-
-#, fuzzy, c-format
-msgid "You must be in %s to use this command."
-msgstr "You need to be identified to use this command."
-
-#, fuzzy
-msgid "You must confirm your account before you can register a channel."
-msgstr "Чтобы зарегистрировать канал, вы должны быть его оператором."
-
-#, fuzzy
-msgid "You must confirm your account before you may request a vhost."
-msgstr "Чтобы зарегистрировать канал, вы должны быть его оператором."
-
-#, fuzzy
-msgid "You must confirm your account before you may send a memo."
-msgstr "Чтобы зарегистрировать канал, вы должны быть его оператором."
-
-#, c-format
-msgid ""
-"You must enter the channel name twice as a confirmation that you wish to drop"
-" %s."
-msgstr ""
-
-#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr ""
-"Чтобы начать регистрацию вашего текущего ника, вы должны использовать его не "
-"менее %d секунд"
-
-#, fuzzy, c-format
-msgid "You must have the %s(ME) privilege on the channel to use this command."
-msgstr "You need to be identified to use this command."
-
-msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
-"case you forget it."
-msgstr ""
-"Сначала вы должны установить email-адрес для вашего ника. Реальный email-"
-"адрес\n"
-"позволит вам использовать функцию восстановления пароля, если вы его "
-"забудете."
-
-msgid "You need to be identified to use this command."
-msgstr "You need to be identified to use this command."
-
-#, fuzzy
-msgid "You will be notified by message and by mail when new memos arrive."
-msgstr "Вы будете уведомлены о новых сообщениях сразу при поступлении оных."
-
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon and when they arrive, and by mail "
-"when they arrive."
-msgstr ""
-"Вы будете уведомлены о новых сообщениях сразу после идентификации к нику или "
-"при поступлении новых сообщений."
-
-msgid "You will be notified of new memos at logon and when they arrive."
-msgstr ""
-"Вы будете уведомлены о новых сообщениях сразу после идентификации к нику или "
-"при поступлении новых сообщений."
-
-#, fuzzy
-msgid ""
-"You will be notified of new memos at logon, and by mail when they arrive."
-msgstr ""
-"Вы будете уведомлены о новых сообщениях сразу после идентификации к нику или "
-"при поступлении новых сообщений."
-
-msgid "You will be notified of new memos at logon."
-msgstr ""
-"Вы будете уведомлены о новых сообщениях сразу после идентификации к нику"
-
-msgid "You will be notified when new memos arrive."
-msgstr "Вы будете уведомлены о новых сообщениях сразу при поступлении оных."
-
-msgid "You will no longer be able to receive memos."
-msgstr "Лимит сообщений установлен на 0, возможность их получения отключена."
-
-msgid "You will no longer be informed via email."
-msgstr "Оповещение о новых сообщениях посредством email отключено"
-
-msgid "You will not be notified of new memos."
-msgstr "Уведомление о новых сообщениях отключено."
-
-msgid "You will now be informed about new memos via email."
-msgstr ""
-"С этого момента, вы будете получать уведомления о новых сообщениях по email."
-
-msgid "Your IRCd does not support SVSJOIN."
-msgstr ""
-
-msgid "Your IRCd does not support SVSNICK."
-msgstr ""
-
-msgid "Your IRCd does not support SVSPART."
-msgstr ""
-
-msgid ""
-"Your IRCd does not support vIdent's, if this is incorrect, please report "
-"this as a possible bug"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Your account %s has been successfully created."
-msgstr "Бот под ником %s успешно удален."
-
-#, fuzzy
-msgid "Your account is already confirmed."
-msgstr "Вы уже идентифицированы."
-
-#, fuzzy, c-format
-msgid "Your account will expire, if not confirmed, in %s."
-msgstr "Вы уже идентифицированы."
-
-#, fuzzy, c-format
-msgid "Your email address has been changed to %s."
-msgstr "Email-адрес для %s изменен на %s."
-
-#, fuzzy
-msgid "Your email address is not allowed, choose a different one."
-msgstr "Все OLINE-записи на сервере %s были удалены."
-
-msgid ""
-"Your email address is not confirmed. To confirm it, follow the instructions "
-"that were emailed to you."
-msgstr ""
-
-#, fuzzy, c-format
-msgid "Your email address of %s has been confirmed."
-msgstr "Все OLINE-записи на сервере %s были удалены."
-
-#, fuzzy, c-format
-msgid "Your email has been updated to %s"
-msgstr "Email-адрес для %s изменен на %s."
-
-#, fuzzy, c-format
-msgid "Your email has been updated to %s."
-msgstr "Email-адрес для %s изменен на %s."
-
-msgid "Your memo limit has been disabled."
-msgstr "Лимититирование вашего списка сообщений отключено."
-
-#, c-format
-msgid "Your memo limit has been set to %d."
-msgstr "Лимит сообщений был установлен на %d."
-
-#, c-format
-msgid "Your memo limit is %d, and may not be changed."
-msgstr "Ваш лимит сообщений равен %d и не может быть изменен."
-
-#, c-format
-msgid "Your memo limit is %d."
-msgstr "Ваш лимит сообщений равен %d."
-
-msgid "Your memo limit is 0; you will not receive any new memos."
-msgstr "Ваш лимит сообщений равен 0 и принимать их вы не можете."
-
-#, fuzzy
-msgid ""
-"Your memo limit is 0; you will not receive any new memos. You cannot change "
-"this limit."
-msgstr ""
-"Ваш лимит сообщений равен 0, у вас нет возможности принимать сообщения и/или "
-"изменять лимит."
-
-msgid "Your nick has been logged out."
-msgstr "Деидентификация выполнена успешно."
-
-#, fuzzy
-msgid "Your nick is already registered."
-msgstr ""
-"Перед внесением ника в группу, вы должны удалить его командой /msg %s DROP."
-
-msgid "Your nick is not grouped to anything, you can't ungroup it."
-msgstr "Your nick is not grouped to anything, you can't ungroup it."
-
-#, fuzzy
-msgid "Your nick isn't registered."
-msgstr "Ник %s успешно зарегистрирован."
-
-#, c-format
-msgid "Your nickname is now being changed to %s"
-msgstr "Ваш ник изменен на %s"
-
-msgid "Your oper block doesn't require logging in."
-msgstr ""
-
-#, c-format
-msgid "Your passcode has been re-sent to %s."
-msgstr "Ваш код аутенфикации был заново выслан на %s."
-
-#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr ""
-"Пароль для вашего ника - %s - запомните его, он пригодится вам в дальнейшем!"
-
-#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr ""
-
-msgid "Your password reset request has expired."
-msgstr "Your password reset request has expired."
-
-#, fuzzy
-msgid "Your vHost has been requested."
-msgstr "Бот под ником %s успешно удален."
-
-#, c-format
-msgid "Your vhost of %s is now activated."
-msgstr "Ваш виртуальный хост %s активирован."
-
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "Ваш виртуальный хост %s@%s активирован."
-
-msgid "Your vhost was removed and the normal cloaking restored."
-msgstr "Your vhost was removed and the normal cloaking restored."
-
-#, fuzzy
-msgid "Zone"
-msgstr "отсутствуют"
-
-#, fuzzy, c-format
-msgid "Zone %s already exists."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy, c-format
-msgid "Zone %s does not exist."
-msgstr "Бот с ником %s уже существует."
-
-#, fuzzy, c-format
-msgid "Zone %s removed."
-msgstr "Виртуальный хост для %s удален."
-
-#, fuzzy
-msgid "[1|2|3|4|5]"
-msgstr "DEFCON [1|2|3|4|5]"
-
-#, c-format
-msgid "[Logon News - %s] %s"
-msgstr "[Новости сети - %s] %s"
-
-#, c-format
-msgid "[Oper News - %s] %s"
-msgstr "[Опер-новости - %s] %s"
-
-#, c-format
-msgid "[Random News - %s] %s"
-msgstr "[Случайная новость - %s] %s"
-
-#, fuzzy
-msgid "[account] password"
-msgstr "IDENTIFY пароль"
-
-#, fuzzy
-msgid "[channel [nick]]"
-msgstr "OP #channel [nick]"
-
-#, fuzzy
-msgid "[channel] ADD entry"
-msgstr "AOP #канал {ADD|DEL|LIST|CLEAR} [ник | номер запис]"
-
-#, fuzzy
-msgid "[channel] DEL entry"
-msgstr "MODE #канал режимы"
-
-#, fuzzy
-msgid "[channel] LIST"
-msgstr "DROP #канал"
-
-#, fuzzy
-msgid "[channel] [list | NEW]"
-msgstr "LIST [#канал] [список_записей | NEW]"
-
-#, fuzzy
-msgid "[channel] [nick]"
-msgstr "OP #channel [nick]"
-
-#, fuzzy
-msgid "[channel] {num | list | LAST | ALL}"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-#, fuzzy
-msgid "[channel] {num | list | LAST | NEW | ALL}"
-msgstr "DEL [#канал] {номер_сообщения | список_записей | ALL}"
-
-msgid "[key|#X-Y]"
-msgstr ""
-
-#, fuzzy
-msgid "[nick | channel]"
-msgstr "CANCEL {ник | #канал}"
-
-#, fuzzy
-msgid "[nick]"
-msgstr "INFO ник"
-
-msgid "[nickname [REVALIDATE]]"
-msgstr ""
-
-#, fuzzy
-msgid "[nickname]"
-msgstr "CHECK ник"
-
-msgid "[parameter]"
-msgstr ""
-
-msgid "[+daysd] [+limitl] pattern"
-msgstr ""
-
-#, fuzzy
-msgid "[+expiry] channel reason"
-msgstr "CHANKILL [+срок_истечения] {#канал} [причина]"
-
-msgid "[Hostname hidden]"
-msgstr ""
-
-msgid "[Suspended]"
-msgstr ""
-
-msgid "[Unconfirmed]"
-msgstr ""
-
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been approved."
-msgstr ""
-"[авто-сообщение] Мемо-сообщение, которые вы посылали %s, было прочитано."
-
-#, fuzzy
-msgid "[auto memo] Your requested vHost has been rejected."
-msgstr ""
-"[авто-сообщение] Мемо-сообщение, которые вы посылали %s, было прочитано."
-
-#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
-msgstr ""
-
-#, fuzzy, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "Последнее ваше сообщение адресату %s успешно отменено."
-
-msgid "[{pattern | channel} [INVISIBLE]]"
-msgstr ""
-
-msgid "[{pattern | nick} [SECRET]]"
-msgstr ""
-
-msgid "day"
-msgstr ""
-
-msgid "days"
-msgstr ""
-
-#, fuzzy
-msgid "does not expire"
-msgstr " %s (does not expire)"
-
-#, c-format
-msgid "expires in %d day"
-msgstr "истечет через %d дней"
-
-#, c-format
-msgid "expires in %d days"
-msgstr "истечет через %d дней"
-
-#, c-format
-msgid "expires in %d hour, %d minute"
-msgstr "истечет через %d часов %d минут"
-
-#, c-format
-msgid "expires in %d hour, %d minutes"
-msgstr "истечет через %d часов, %d минут"
-
-#, c-format
-msgid "expires in %d hours, %d minute"
-msgstr "истечет через %d часов, %d минут"
-
-#, c-format
-msgid "expires in %d hours, %d minutes"
-msgstr "истечет через %d часов, %d минут"
-
-#, c-format
-msgid "expires in %d minute"
-msgstr "истечет через %d минут"
-
-#, c-format
-msgid "expires in %d minutes"
-msgstr "истечет через %d минут"
-
-#, fuzzy
-msgid "expires momentarily"
-msgstr "истечет через %d дней"
-
-msgid "hour"
-msgstr ""
-
-msgid "hours"
-msgstr ""
-
-#, c-format
-msgid "letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr ""
-
-msgid "minute"
-msgstr ""
-
-msgid "minutes"
-msgstr ""
-
-msgid "not assigned yet"
-msgstr ""
-
-msgid "second"
-msgstr ""
-
-#, fuzzy
-msgid "seconds"
-msgstr "Список команд %s:"
-
-#, fuzzy, c-format
-msgid "vHost for %s has been activated."
-msgstr "Ваш виртуальный хост %s активирован."
-
-#, fuzzy, c-format
-msgid "vHost for %s has been rejected."
-msgstr "Бот под ником %s успешно удален."
-
-msgid "vhost"
-msgstr ""
-
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "Все виртуальные хосты для группы %s были удалены."
-
-msgid "year"
-msgstr ""
-
-msgid "years"
-msgstr ""
-
-msgid "{MODIFY|VIEW} [block name item name item value]"
-msgstr ""
-
-#, fuzzy
-msgid "{channel | nickname}"
-msgstr "UNBAN #канал [nick]"
-
-#, fuzzy
-msgid "{nick | channel}"
-msgstr "CANCEL {ник | #канал}"
-
-#, fuzzy
-msgid "{nick | channel} memo-text"
-msgstr "SEND {ник | #канал} текст_сообщения"
diff --git a/language/anope.tr_TR.po b/language/anope.tr_TR.po
index 39ea600f7..203a0c0ca 100644
--- a/language/anope.tr_TR.po
+++ b/language/anope.tr_TR.po
@@ -7,20 +7,20 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-01-22 16:25+0000\n"
-"PO-Revision-Date: 2024-01-22 16:28+0000\n"
-"Last-Translator: CaPaCuL\n"
+"POT-Creation-Date: 2024-11-11 21:27+0000\n"
+"PO-Revision-Date: 2024-11-11 22:30+0300\n"
+"Last-Translator: CaPaCuL <capacul@gmail.com>\n"
"Language-Team: Turkish\n"
"Language: tr_TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 3.4\n"
+"X-Generator: Poedit 3.5\n"
#, c-format
msgid "%d channel(s) cleared, and %d channel(s) dropped."
-msgstr "%d kanal temizlendi ve %d kanal bırakıldı."
+msgstr "%d kanal temizlendi ve %d kanal düşürüldü."
#, c-format
msgid "%d nickname(s) dropped."
@@ -40,15 +40,11 @@ msgstr "%s, %s ayrıcalığına sahip %s erişim listesine eklendi (seviye %d)
#, c-format
msgid "%s added to %s autokick list."
-msgstr "%s, %s otomatik atma listesine eklendi."
+msgstr "%s, %s oto-at listesine eklendi."
#, c-format
msgid "%s added to %s bad words list."
-msgstr "%s, %s kötü kelimeler listesine eklendi."
-
-#, c-format
-msgid "%s added to %s's access list."
-msgstr "%s, %s kullanıcısının erişim listesine eklendi."
+msgstr "%s, %s küfür listesine eklendi."
#, c-format
msgid "%s added to %s's certificate list."
@@ -85,47 +81,47 @@ msgid ""
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
-"below; to use them, type %s%s command. For\n"
+"below; to use them, type %s command. For\n"
"more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
"%s kendi kanalınızda bir bot bulundurmanıza olanak tanır.\n"
"Bir botu barındıramayan veya yapılandıramayan kullanıcılar için ya da\n"
"kullanıcı botlarına izin vermeyen ağlarda kullanılmak üzere\n"
"oluşturulmuştur. Mevcut komutlar aşağıdaki listelendi;\n"
-"bunları kullanmak için %s%s komut yazın.\n"
-"Belirli bir komut hakkında daha fazla bilgi için şunu yazın:\n"
-"%s%s %s komut.\n"
+"bunları kullanmak için %s komut yazın.\n"
+"Belirli bir komut hakkında daha fazla bilgi için,\n"
+"%s %s komut yazın.\n"
#, c-format
msgid ""
"%s allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
-"nicknames; to use them, type %s%s command.\n"
+"nicknames; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
"%s bir rumuz kaydetmenizi ve başkalarının\n"
"bunu kullanmasının engellenmesini sağlar. Aşağıdaki\n"
"komutlar rumuz kaydı ve düzenlemesşne izin verir;\n"
-"bunları kullanmak için %s%s komut yazın.\n"
+"bunları kullanmak için %s komut yazın.\n"
"Belirli bir komut hakkında daha fazla bilgi için şunu yazın:\n"
-"%s%s %s komut.\n"
+"%s %s komut.\n"
#, c-format
msgid ""
"%s allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
-"accounts; to use them, type %s%s command.\n"
+"accounts; to use them, type %s command.\n"
"For more information on a specific command, type\n"
-"%s%s %s command.\n"
+"%s %s command.\n"
msgstr ""
"%s bir hesap kaydetmenizi sağlar. Aşağıdaki komutlar\n"
"hesap kaydı ve düzenlenmesine yapılmasına izin verir; bunları\n"
-"kullanmak için %s%s komut yazın. Belirli bir\n"
+"kullanmak için %s komut yazın. Belirli bir\n"
"komut hakkında daha fazla bilgi için şunu yazın:\n"
-"%s%s %s komut.\n"
+"%s %s komut.\n"
#, c-format
msgid ""
@@ -134,24 +130,24 @@ msgid ""
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
-"%s%s command. For more information on a\n"
-"specific command, type %s%s HELP command.\n"
+"%s command. For more information on a\n"
+"specific command, type %s HELP command.\n"
msgstr ""
"%s kanalların çeşitli yönlerini kaydetmenize ve kontrol\n"
"etmenize olanak tanır. %s, kanal operatörü ayrıcalıklarına izin verilen\n"
"kişileri sınırlayarak, genellikle kötü niyetli kullanıcıların kanalları\n"
"\"ele geçirmesini\" engelleyebilir. Mevcut komutlar aşağıda listelenmiştir;\n"
-"bunları kullanmak için %s%s komut yazın.\n"
+"bunları kullanmak için %s komut yazın.\n"
"Belirli bir komut hakkında daha fazla bilgi için\n"
-"%s%s HELP komut yazın.\n"
+"%s HELP komut yazın.\n"
#, c-format
msgid "%s already exists in %s bad words list."
-msgstr "%s zaten %s'in kötü kelimeler listesinde mevcut."
+msgstr "%s zaten %s'in küfür listesinde mevcut."
#, c-format
msgid "%s already exists on %s autokick list."
-msgstr "%s zaten %s otomatik atma listesinde mevcut."
+msgstr "%s zaten %s oto-at listesinde mevcut."
#, c-format
msgid "%s already exists on the EXCEPTION list."
@@ -179,15 +175,11 @@ msgstr "%s, %s erişim listesinden silindi."
#, c-format
msgid "%s deleted from %s autokick list."
-msgstr "%s, %s otomatik atma listesinden silindi."
+msgstr "%s, %s oto-at listesinden silindi."
#, c-format
msgid "%s deleted from %s bad words list."
-msgstr "%s, %s kötü kelimeler listesinden silindi."
-
-#, c-format
-msgid "%s deleted from %s's access list."
-msgstr "%s, %s'in erişim listesinden silindi."
+msgstr "%s, %s küfür listesinden silindi."
#, c-format
msgid "%s deleted from %s's certificate list."
@@ -210,6 +202,10 @@ msgid "%s disabled on channel %s."
msgstr "%s %s kanalında devre dışı bırakıldı."
#, c-format
+msgid "%s does not wish to be added to channel access lists."
+msgstr "%s kanal erişim listelerine eklenmek istemiyor."
+
+#, c-format
msgid "%s has been invited to %s."
msgstr "%s, %s'ye davet edildi."
@@ -286,7 +282,7 @@ msgid "%s is not a valid bot or registered channel."
msgstr "%s geçerli bir bot veya kayıtlı kanal değil."
#, c-format
-msgid "%s is not a valid e-mail address."
+msgid "%s is not a valid email address."
msgstr "%s geçerli bir e-posta adresi değil."
#, c-format
@@ -303,7 +299,7 @@ msgstr "%s yoksayılanlar listesinde değil."
#, c-format
msgid "%s is on the auto kick list of %s (%s)."
-msgstr "%s, %s (%s) otomatik atma listesinde."
+msgstr "%s, %s (%s) oto-at listesinde."
#, c-format
msgid "%s is the founder of %s."
@@ -323,7 +319,7 @@ msgstr "%s, %s üzerinde bir istisnayla eşleşiyor ve istisna kaldırılınca
#, c-format
msgid "%s matches auto kick entry %s on %s (%s)."
-msgstr "%s, %s (%s) üzerindeki %s otomatik atma girdisiyle eşleşir."
+msgstr "%s, %s (%s) üzerindeki %s oto-at girdisiyle eşleşir."
#, c-format
msgid "%s not found on %s %s list."
@@ -335,15 +331,11 @@ msgstr "%s %s erişim listesinde bulunamadı."
#, c-format
msgid "%s not found on %s autokick list."
-msgstr "%s %s otomatik atma listesinde bulunamadı."
+msgstr "%s %s oto-at listesinde bulunamadı."
#, c-format
msgid "%s not found on %s bad words list."
-msgstr "%s %s'in kötü kelimeler listesinde bulunamadı."
-
-#, c-format
-msgid "%s not found on %s's access list."
-msgstr "%s %s'in erişim listesinde bulunamadı."
+msgstr "%s %s'in küfür listesinde bulunamadı."
#, c-format
msgid "%s not found on %s's certificate list."
@@ -394,8 +386,8 @@ msgid "%s will now permanently be ignored."
msgstr "%s artık kalıcı olarak yok sayılacak."
#, c-format
-msgid "%s%s HELP %s for more information."
-msgstr "Daha fazla bilgi için %s%s HELP %s."
+msgid "%s HELP %s for more information."
+msgstr "Daha fazla bilgi için %s HELP %s."
msgid "ADD nick user host real"
msgstr "ADD rumuz kullanıcı host gerçek_ad"
@@ -465,11 +457,11 @@ msgstr ""
#, c-format
msgid ""
"User access levels can be seen by using the\n"
-"%s command; type %s%s HELP LEVELS for\n"
+"%s command; type %s HELP LEVELS for\n"
"information."
msgstr ""
"Kullanıcı erişim düzeyleri %s komutu\n"
-"kullanılarak görülebilir; bilgi için %s%s HELP LEVELS\n"
+"kullanılarak görülebilir; bilgi için %s HELP LEVELS\n"
"yazın."
#, c-format
@@ -491,9 +483,6 @@ msgstr "kanal"
msgid "channel bantype"
msgstr "kanal ban_tipi"
-msgid "channel channel"
-msgstr "kanal kanal"
-
msgid "channel command method [status]"
msgstr "kanal komut metot [durum]"
@@ -524,11 +513,11 @@ msgstr "kanal kullanıcı sebep"
msgid "channel what"
msgstr "kanal ne?"
-msgid "channel ADD mask"
-msgstr "kanal ADD maske"
+msgid "channel ADD mask level [description]"
+msgstr "kanal ADD maske seviye [açıklama]"
-msgid "channel ADD mask level"
-msgstr "kanal ADD maske seviye"
+msgid "channel ADD mask [description]"
+msgstr "kanall ADD maske [açıklama]"
msgid "channel ADD message"
msgstr "kanal ADD mesaj"
@@ -596,6 +585,9 @@ msgstr "kanal VIEW [maske | girdi-no | liste]"
msgid "channel VIEW [mask | list]"
msgstr "kanal VIEW [maske | liste]"
+msgid "channel [code]"
+msgstr "kanall [kod]"
+
msgid "channel [description]"
msgstr "kanal [açıklama]"
@@ -614,8 +606,8 @@ msgstr "kanal [+sona-erme] [sebep]"
msgid "channel [+expiry] {nick | mask} [reason]"
msgstr "kanal [+sona-erme] {rumuz | maske} [sebep]"
-msgid "channel [MODIFY] mask changes"
-msgstr "kanal [MODIFY] maske değişiklikler"
+msgid "channel [MODIFY] mask changes [description]"
+msgstr "kanal [MODIFY] maske değişiklikler [açıklama]"
msgid "channel [SET] [topic]"
msgstr "kanal [SET] [başlık]"
@@ -677,9 +669,6 @@ msgstr "rumuz kanal"
msgid "nick channel [reason]"
msgstr "rumuz kanal [sebep]"
-msgid "nick flags"
-msgstr "rumuz bayraklar"
-
msgid "nick hostmask"
msgstr "rumuz host_maskesi"
@@ -710,6 +699,9 @@ msgstr "rumuz yeni-afiş"
msgid "nickname new-password"
msgstr "rumuz yeni-şifre"
+msgid "nickname [code]"
+msgstr "rumuz [kod]"
+
msgid "nickname [parameter]"
msgstr "rumuz [parametre]"
@@ -764,6 +756,9 @@ msgstr "şablon [SUSPENDED] [NOEXPIRE]"
msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
msgstr "şablon [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
+msgid "server [message]"
+msgstr "sunucu [mesaj]"
+
msgid "server [reason]"
msgstr "sunucu [sebep]"
@@ -838,12 +833,12 @@ msgid ""
" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
-"after %d days if not used."
+"after %lu days if not used."
msgstr ""
" \n"
"Artık kullanılmayan hesaplar otomatik\n"
"olarak sona erecektir; yani kullanılmadıkları\n"
-"takdirde %d gün sonra silineceklerdir."
+"takdirde %lu gün sonra silineceklerdir."
msgid ""
" \n"
@@ -870,9 +865,9 @@ msgid ""
"fantasy commands on a channel when prefixed\n"
"with one of the following fantasy characters: %s\n"
" \n"
-"Note that users wanting to use fantaisist\n"
-"commands MUST have enough access for both\n"
-"the FANTASIA and the command they are executing."
+"Note that users wanting to use fantasy commands\n"
+"MUST have enough access for both the FANTASY\n"
+"privilege and the command they are executing."
msgstr ""
" \n"
"Bir kanalda fantezi modunu etkinleştirir veya devre dışı bırakır.\n"
@@ -939,26 +934,26 @@ msgstr ""
#, c-format
msgid ""
" \n"
-"Note that any channel which is not used for %d days\n"
+"Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
"for that period of time) will be automatically dropped."
msgstr ""
" \n"
-"%d gün boyunca kullanılmayan herhangi bir kanalın\n"
+"%lu gün boyunca kullanılmayan herhangi bir kanalın\n"
"(yani bu süre boyunca kanalın erişim listesindeki hiçbir\n"
-"kullanıcının girmediği) otomatik olarak bırakılacağını unutmayın."
+"kullanıcının girmediği) otomatik olarak düşürüleceğini unutmayın."
#, c-format
msgid ""
" \n"
-"See the %s command (%s%s HELP ACCESS) for\n"
+"See the %s command (%s HELP ACCESS) for\n"
"information on giving a subset of these privileges to\n"
"other channel users.\n"
msgstr ""
" \n"
"Bu ayrıcalıkların bir alt kümesini diğer kanal kullanıcılarına verme\n"
"hakkında bilgi için %s komutuna\n"
-"(%s%s HELP ACCESS) bakın.\n"
+"(%s HELP ACCESS) bakın.\n"
msgid ""
" \n"
@@ -1223,12 +1218,12 @@ msgstr ""
#, c-format
msgid ""
" \n"
-"Type %s%s HELP command for help on any of the\n"
+"Type %s HELP command for help on any of the\n"
"above commands."
msgstr ""
" \n"
"Yukarıdaki komutlardan herhangi biri hakkında yardım almak için\n"
-"%s%s HELP komut yazın."
+"%s HELP komut yazın."
#, c-format
msgid " %s is online using this oper block."
@@ -1253,10 +1248,6 @@ msgstr " Yüklenme zamanı: %p"
msgid " but %s mysteriously dematerialized."
msgstr " ama nedendir bilinmez %s artık yok."
-#, c-format
-msgid "\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."
-msgstr "\"/msg %s\" artık desteklenmiyor. Bunun yerine \"/msg %s@%s\" ve ya \"/%s\" kullanın."
-
msgid "\"Jupiter\" a server"
msgstr "Bir sunucuyu \"Jupiter\" yapın"
@@ -1265,11 +1256,11 @@ msgid "%-8s %s"
msgstr "%-8s %s"
#, c-format
-msgid "%2lu %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
-msgstr "%2lu %-16s harf: %s, kelime: %s, satır: %s, smiley: %s, eylem: %s"
+msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
+msgstr "%2d %-16s harf: %s, kelime: %s, satır: %s, smiley: %s, eylem: %s"
-msgid "%b %d %H:%M:%S %Y %Z"
-msgstr "%b %d %H:%M:%S %Y %Z"
+msgid "%b %d %Y %H:%M:%S %Z"
+msgstr "%b %d %Y %H:%M:%S %Z"
#, c-format
msgid "%c is an unknown status mode."
@@ -1296,10 +1287,6 @@ msgid "%d modules loaded."
msgstr "%d modül yüklendi."
#, c-format
-msgid "%d nickname(s) in the group."
-msgstr "Grupta %d rumuz."
-
-#, c-format
msgid "%lu nicks are stored in the database, using %.2Lf kB of memory."
msgstr "%lu rumuz veritabanında, %.2Lf kB bellek kullanılarak saklanıyor."
@@ -1396,6 +1383,14 @@ msgid "%s bad words list is empty."
msgstr "%s küfür listesi boş."
#, c-format
+msgid "%s can no longer be added to channel access lists."
+msgstr "%s artık kanal erişim listelerine eklenemez."
+
+#, c-format
+msgid "%s can now be added to channel access lists."
+msgstr "%s artık kanal erişim listelerine eklenebilir."
+
+#, c-format
msgid "%s cannot be the successor on channel %s as they are the founder."
msgstr "%s, %s kanalının halefi olamaz, çünkü o zaten kurucusu."
@@ -1408,20 +1403,20 @@ msgid "%s coverage is too wide; Please use a more specific mask."
msgstr "%s kapsamı çok geniş; Lütfen daha spesifik bir maske kullanın."
#, c-format
-msgid "%s currently has %d memos, of which %d are unread."
-msgstr "%s şu anda %d nota sahip ve bunların %d'si okunmamış."
+msgid "%s currently has %zu memos, of which %zu are unread."
+msgstr "%s şu anda %zu nota sahip ve bunların %zu'si okunmamış."
#, c-format
-msgid "%s currently has %d memos, of which 1 is unread."
-msgstr "%s şu anda %d memoya sahip ve bunların 1'i okunmamış."
+msgid "%s currently has %zu memos, of which 1 is unread."
+msgstr "%s şu anda %zu memoya sahip ve bunların 1'i okunmamış."
#, c-format
-msgid "%s currently has %d memos."
-msgstr "%s şuan %d memoya sahip."
+msgid "%s currently has %zu memos."
+msgstr "%s şuan %zu memoya sahip."
#, c-format
-msgid "%s currently has %d memos; all of them are unread."
-msgstr "%s şuan %d memoya sahip; hiç biri de okunmamış."
+msgid "%s currently has %zu memos; all of them are unread."
+msgstr "%s şuan %zu memoya sahip; hiç biri de okunmamış."
#, c-format
msgid "%s currently has 1 memo, and it has not yet been read."
@@ -1600,10 +1595,6 @@ msgid "%s!%s@%s (%s) added to the bot list."
msgstr "%s!%s@%s (%s) bot listesine eklendi."
#, c-format
-msgid "%s's access list is empty."
-msgstr "%s erişim listesi boş."
-
-#, c-format
msgid "%s's auto join list is empty."
msgstr "%s oto-gir listesi boş."
@@ -1624,6 +1615,10 @@ msgid "%s's memo limit is %d."
msgstr "%s memo sınırı %d."
#, c-format
+msgid "%zu nickname(s) in the group."
+msgstr "Grupta %zu rumuz."
+
+#, c-format
msgid "(%s ago)"
msgstr "(%s önce)"
@@ -1691,7 +1686,7 @@ msgid "<unknown>"
msgstr "<bilinmiyor>"
#, c-format
-msgid "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
+msgid "A confirmation email has been sent to %s. Follow the instructions in it to change your email address."
msgstr "%s adresine bir onay e-postası gönderildi. E-posta adresinizi değiştirmek için içindeki talimatları izleyin."
msgid "A massmemo has been sent to all registered users."
@@ -1708,18 +1703,21 @@ msgid ""
"A notification memo has been sent to %s informing them you have\n"
"read their memo."
msgstr ""
-"%s rumuzlu kişiye, notunu okuduğunuzu bildiren bir\n"
-"bildirim notu gönderildi."
+"%s adlı kullanıcıya, memolarını okuduğunuzu bildiren\n"
+"bir bildirim memosu gönderildi."
-msgid "A vHost ident must be in the format of a valid ident."
-msgstr "Bir vHost kimliği geçerli bir kimlik biçiminde olmalıdır."
-
-msgid "A vHost must be in the format of a valid hostname."
+msgid "A vhost must be in the format of a valid hostname."
msgstr "Bir vHost, geçerli bir host adı biçiminde olmalıdır."
+msgid "A vident must be in the format of a valid ident."
+msgstr "Bir vIdent kimliği geçerli bir ident biçiminde olmalıdır."
+
msgid "ADD expiry {nick|mask} [reason]"
msgstr "ADD sona-erme {rumuz|maske} [sebep]"
+msgid "ADD message"
+msgstr "ADD mesaj"
+
msgid "ADD oper type"
msgstr "ADD oper tip"
@@ -1735,9 +1733,6 @@ msgstr "ADD [+sona-erme] maske limit sebep"
msgid "ADD [nickname] channel [key]"
msgstr "ADD [rumuz] kanal [anahtar]"
-msgid "ADD [nickname] mask"
-msgstr "ADD [rumuz] maske"
-
msgid "ADD [nickname] [fingerprint]"
msgstr "ADD [rumuz] [parmak-izi]"
@@ -1812,10 +1807,16 @@ msgstr "Hesap"
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
msgstr "%s hesabı zaten maksimum eşzamanlı oturum açma sayısına (%u) ulaştı."
-msgid "Activate security features"
-msgstr "Güvenlik özelliklerini etkinleştirin"
+msgid "Account id"
+msgstr "Hesap ID"
+
+msgid "Account registered"
+msgstr "Hesap kaydedildi"
-msgid "Activate the requested vHost for the given nick."
+msgid "Accounts can not be registered right now. Please try again later."
+msgstr "Hesaplar şu anda kaydedilemiyor. Lütfen daha sonra tekrar deneyiniz."
+
+msgid "Activate the requested vhost for the given nick."
msgstr "Belirtilen rumuz için istenen vHost'u etkinleştirin."
msgid ""
@@ -1876,12 +1877,26 @@ msgstr ""
"SET iznini gerektirir."
msgid ""
+"Additionally, Services Operators with the chanserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
+msgstr ""
+"Ek olarak, nickserv/confirm iznine sahip Servis Operatörleri,\n"
+"doğrulamayı zorlamak için passcode'yi bir kullanıcı rumuzu ile değiştirebilir."
+
+msgid ""
"Additionally, Services Operators with the nickserv/confirm permission can\n"
"replace passcode with a users nick to force validate them."
msgstr ""
"Ek olarak, nickserv/confirm iznine sahip Servis Operatörleri,\n"
"doğrulamayı zorlamak için passcode'yi bir kullanıcı rumuzu ile değiştirebilir."
+msgid ""
+"Additionally, Services Operators with the nickserv/drop/override permission can\n"
+"replace code with OVERRIDE to drop without a confirmation code."
+msgstr ""
+"Ek olarak, nickserv/confirm iznine sahip Servis Operatörleri,\n"
+"doğrulamayı zorlamak için passcode'yi bir kullanıcı rumuzu ile değiştirebilir."
+
#, c-format
msgid ""
"Additionally, if fantasy is enabled fantasy commands\n"
@@ -1906,7 +1921,7 @@ msgstr "%s için tüm kullanılabilir komutlar:"
#, c-format
msgid "All badword entries from %s have been cloned to %s."
-msgstr "%s'deki tüm kötü kelime girişleri %s'ye kopyalandı."
+msgstr "%s'deki tüm küfür girdileri %s'ye kopyalandı."
#, c-format
msgid "All level entries from %s have been cloned into %s."
@@ -1951,35 +1966,31 @@ msgstr "%s'deki tüm kullanıcı modları senkronize edildi."
msgid "All vhosts in the group %s have been set to %s."
msgstr "%s grubundaki tüm vhostlar %s olarak ayarlandı."
-#, c-format
-msgid "All vhosts in the group %s have been set to %s@%s."
-msgstr "%s grubundaki tüm vhostlar %s@%s olarak ayarlandı."
-
-msgid "Allowed to (de)halfop him/herself"
+msgid "Allowed to (de)halfop themself"
msgstr "Kendisini (de)halfop izni var"
msgid "Allowed to (de)halfop users"
msgstr "Kullnıcıları (de)halfop izni var"
-msgid "Allowed to (de)op him/herself"
+msgid "Allowed to (de)op themself"
msgstr "Kendisini (de)op izni var"
msgid "Allowed to (de)op users"
msgstr "Kullanıcıları (de)op izni var"
-msgid "Allowed to (de)owner him/herself"
+msgid "Allowed to (de)owner themself"
msgstr "Kendisini (de)owner izni var"
msgid "Allowed to (de)owner users"
msgstr "Kullanıcıları (de)owner izni var"
-msgid "Allowed to (de)protect him/herself"
+msgid "Allowed to (de)protect themself"
msgstr "Kendisini (de)protect izni var"
msgid "Allowed to (de)protect users"
msgstr "Kullanıcıları (de)protect izni var"
-msgid "Allowed to (de)voice him/herself"
+msgid "Allowed to (de)voice themself"
msgstr "Kendisini (de)voice izni var"
msgid "Allowed to (de)voice users"
@@ -2003,14 +2014,17 @@ msgstr "Kanal kurucularıyla sınırlı komutlar verme izni var"
msgid "Allowed to modify channel badwords list"
msgstr "Kanalın küfür listesini değiştirme izni var"
+msgid "Allowed to modify channel settings"
+msgstr "Kanal ayarlarını yapma izni var"
+
msgid "Allowed to modify the access list"
msgstr "Erişim listesini değiştirme izni var"
msgid "Allowed to read channel memos"
msgstr "Kanal memolarını okuma izni var"
-msgid "Allowed to set channel settings"
-msgstr "Kanal ayarlarını yapma izni var"
+msgid "Allowed to unban themself"
+msgstr "Kendisini unban yapma izni var"
msgid "Allowed to unban users"
msgstr "Kullanıcıları unban yapma izni var"
@@ -2039,14 +2053,6 @@ msgstr "MODE komutunu kullanma izni var"
msgid "Allowed to view the access list"
msgstr "Erişim listesini görüntüleme izni var"
-#, c-format
-msgid ""
-"Allows Administrators to send messages to all users on the\n"
-"network. The message will be sent from the nick %s."
-msgstr ""
-"Yöneticilerin ağdaki tüm kullanıcılara mesaj göndermesine izin verir.\n"
-"Mesaj %s rumuzundan gönderilecektir."
-
msgid ""
"Allows Services Operators to change modes for any channel.\n"
"Parameters are the same as for the standard /MODE command.\n"
@@ -2103,22 +2109,13 @@ msgstr ""
"bu kullanıcı killenecektir."
msgid ""
-"Allows Services Operators to give Operflags to any user.\n"
-"Flags have to be prefixed with a \"+\" or a \"-\". To\n"
-"remove all flags simply type a \"-\" instead of any flags."
-msgstr ""
-"Servis Operatörlerinin herhangi bir kullanıcıya Operflag vermesine izin verir.\n"
-"Bayrakların önüne \"+\" veya \"-\" konulmalıdır. Tüm bayrakları kaldırmak\n"
-"için herhangi bir bayrak yerine \"-\" yazmanız yeterlidir."
-
-msgid ""
-"Allows Services Operators to make Services ignore a nick or mask\n"
+"Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: s for seconds, m for minutes,\n"
"h for hours and d for days.\n"
"Combinations of these units are not permitted.\n"
-"To make Services permanently ignore the user, type 0 as time.\n"
+"To make services permanently ignore the user, type 0 as time.\n"
"When adding a mask, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
@@ -2138,7 +2135,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the AKILL list. If\n"
-"a user matching an AKILL mask attempts to connect, Services\n"
+"a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -2182,7 +2179,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session."
msgstr ""
"Servis Operatörlerinin SNLINE listesini değiştirmesine izin verir.\n"
@@ -2193,7 +2190,7 @@ msgstr ""
msgid ""
"Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
-"connect, Services will not allow them to pursue their IRC\n"
+"connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
@@ -2278,6 +2275,51 @@ msgstr ""
"kullanılabilir. Başlık kilidi ayarlandığında kanal başlığı TOPIC\n"
"ayrıcalığına sahip olmayan kullanıcılar tarafından değiştirilemez."
+msgid ""
+"Allows queueing messages to send to users on the network.\n"
+"\n"
+"The QUEUE ADD command adds the given message to the message queue.\n"
+"The QUEUE CLEAR command clears the message queue.\n"
+"The QUEUE DEL command removes the specified message from the message queue. The\n"
+"message number can be obtained from the output of the QUEUE LIST command.\n"
+"The QUEUE LIST command lists all messages that are currently in the message queue."
+msgstr ""
+"Ağdaki kullanıcılara gönderilecek mesajların sıraya alınmasına izin verir.\n"
+"\n"
+"QUEUE ADD komutu verilen mesajı mesaj kuyruğuna ekler.\n"
+"QUEUE CLEAR komutu mesaj kuyruğunu temizler.\n"
+"QUEUE DEL komutu belirtilen mesajı mesaj kuyruğundan kaldırır.\n"
+"mesaj numarası QUEUE LIST komutunun çıktısından alınabilir.\n"
+"QUEUE LIST komutu, o anda mesaj kuyruğunda bulunan tüm mesajları listeler."
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on a server. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+"Bir sunucudaki tüm kullanıcılara mesaj gönderilmesine izin verir. Mesaj\n"
+"%s kullanıcısından gönderilecek.\n"
+"\n"
+"Bir mesajı parametre olarak belirterek gönderebilir veya önceden kuyruğa alınmış\n"
+"bir mesajı göndermek için hiçbir parametre belirtmeyebilirsiniz.\n"
+
+#, c-format
+msgid ""
+"Allows sending messages to all users on the network. The message will be sent\n"
+"from %s.\n"
+"\n"
+"You can either send a message by specifying it as a parameter or provide no\n"
+"parameters to send a previously queued message.\n"
+msgstr ""
+"Ağdaki tüm kullanıcılara mesaj gönderilmesine izin verir. Mesaj\n"
+"%s kullanıcısından gidecek.\n"
+"\n"
+"Bir mesajı parametre olarak belirterek gönderebilir veya daha önce kuyruğa\n"
+"alınmış bir mesajı göndermek için hiçbir parametre belirtmeyebilirsiniz.\n"
+
#, c-format
msgid ""
"Allows staff to kick a user from any channel.\n"
@@ -2332,8 +2374,8 @@ msgstr ""
" MODIFY nickserv forcemail no"
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"the given user. With MSG set, Services will use messages,\n"
+"Allows you to choose the way services are communicating with\n"
+"the given user. With MSG set, services will use messages,\n"
"else they'll use notices."
msgstr ""
"Servislerin belirli bir kullanıcıyla iletişim kurma şeklini seçmenizi\n"
@@ -2342,8 +2384,8 @@ msgstr ""
#, c-format
msgid ""
-"Allows you to choose the way Services are communicating with\n"
-"you. With %s set, Services will use messages, else they'll\n"
+"Allows you to choose the way services are communicating with\n"
+"you. With %s set, services will use messages, else they'll\n"
"use notices."
msgstr ""
"Servislerin sizinle iletişim kurma şeklini seçmenizi sağlar.\n"
@@ -2374,7 +2416,7 @@ msgstr ""
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on the\n"
-"nick. You can hide the E-mail address (EMAIL), last seen\n"
+"nick. You can hide the email address (EMAIL), last seen\n"
"user@host mask (USERMASK), the services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2392,7 +2434,7 @@ msgstr ""
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on your\n"
-"nick. You can hide your E-mail address (EMAIL), last seen\n"
+"nick. You can hide your email address (EMAIL), last seen\n"
"user@host mask (USERMASK), your services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2431,7 +2473,7 @@ msgstr ""
"Kanal erişim listelerini değiştirmenin alternatif yöntemleri\n"
"mevcuttur."
-msgid "Approve the requested vHost of a user"
+msgid "Approve the requested vhost of a user"
msgstr "Bir kullanıcının istenen vHost'unu onaylayın"
msgid "As a Services Operator, you may drop any nick."
@@ -2461,20 +2503,20 @@ msgstr "Hesabınızla bir URL ilişkilendirin"
msgid "Associate a greet message with your nickname"
msgstr "Bir karşılama mesajını rumuzunuzla ilişkilendirin"
-msgid "Associate an E-mail address with the channel"
-msgstr "Bir E-posta adresini kanalla ilişkilendirme"
+msgid "Associate an email address with the channel"
+msgstr "Bir e-posta adresini kanalla ilişkilendirin"
-msgid "Associate an E-mail address with your nickname"
+msgid "Associate an email address with your nickname"
msgstr "Bir E-posta adresini rumuzunuzla ilişkilendirin"
msgid "Associate oper info with a nick or channel"
msgstr "Bir rumuz veya kanala ilişkin bir \"info\" ekler, bunu operler görür"
-msgid "Associates the given E-mail address with the nickname."
-msgstr "Belirtilen E-posta adresini rumuzla ilişkilendirir."
+msgid "Associates the given email address with the nickname."
+msgstr "Belirtilen e-posta adresini rumuzla ilişkilendirir."
msgid ""
-"Associates the given E-mail address with your nickname.\n"
+"Associates the given email address with your nickname.\n"
"This address will be displayed whenever someone requests\n"
"information on the nickname with the INFO command."
msgstr ""
@@ -2623,15 +2665,15 @@ msgid "Bot bans will no longer automatically expire."
msgstr "Bot banları artık otomatik olarak sona ermeyecek."
#, c-format
-msgid "Bot hosts may only be %d characters long."
-msgstr "Bot hostları yalnızca %d karakter uzunluğunda olabilir."
+msgid "Bot hosts may only be %zu characters long."
+msgstr "Bot hostları yalnızca %zu karakter uzunluğunda olabilir."
msgid "Bot hosts may only contain valid host characters."
msgstr "Bot hostları yalnızca geçerli host karakterlerini içerebilir."
#, c-format
-msgid "Bot idents may only be %d characters long."
-msgstr "Bot identleri yalnızca %d karakter uzunluğunda olabilir."
+msgid "Bot idents may only be %zu characters long."
+msgstr "Bot identleri yalnızca %zu karakter uzunluğunda olabilir."
msgid "Bot idents may only contain valid ident characters."
msgstr "Bot identleri yalnızca geçerli ident karakterlerini içerebilir."
@@ -2647,8 +2689,8 @@ msgid "Bot nick"
msgstr "Bot rumuzu"
#, c-format
-msgid "Bot nicks may only be %d characters long."
-msgstr "Bot rumuzları yalnızca %d karakter uzunluğunda olabilir."
+msgid "Bot nicks may only be %zu characters long."
+msgstr "Bot rumuzları yalnızca %zu karakter uzunluğunda olabilir."
msgid "Bot nicks may only contain valid nick characters."
msgstr "Bot rumuzları yalnızca geçerli rumuz karakterlerini içerebilir."
@@ -2780,7 +2822,7 @@ msgid "Caps kicker"
msgstr "CAPS yazı atma"
msgid ""
-"Causes Services to do an immediate shutdown; databases are\n"
+"Causes services to do an immediate shutdown; databases are\n"
"not saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."
@@ -2791,9 +2833,9 @@ msgstr ""
"bu komut kullanılmamalı ve kaydedilmemelidir."
msgid ""
-"Causes Services to reload the configuration file. Note that\n"
-"some directives still need the restart of the Services to\n"
-"take effect (such as Services' nicknames, activation of the\n"
+"Causes services to reload the configuration file. Note that\n"
+"some directives still need the restart of the services to\n"
+"take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."
msgstr ""
"Servislerin yapılandırma dosyasını yeniden yüklemesini sağlar.\n"
@@ -2802,17 +2844,17 @@ msgstr ""
"rumuzları, oturum sınırlamasının etkinleştirilmesi vb.)."
msgid ""
-"Causes Services to save all databases and then restart\n"
+"Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."
msgstr ""
"Servislerin tüm veritabanlarını kaydetmesini ve ardından yeniden başlatılmasını\n"
"(yani, yürütülebilir dosyadan çıkıp hemen yeniden çalıştırmasına) sağlar."
-msgid "Causes Services to save all databases and then shut down."
+msgid "Causes services to save all databases and then shut down."
msgstr "Servislerin tüm veritabanlarını kaydetmesini ve ardından kapanmasını sağlar."
msgid ""
-"Causes Services to update all database files as soon as you\n"
+"Causes services to update all database files as soon as you\n"
"send the command."
msgstr ""
"Komutu gönderdiğiniz anda Servislerin tüm veritabanı dosyalarını\n"
@@ -2828,7 +2870,7 @@ msgstr "Bu ağda kalıcılığı etkinleştirmek için ChanServ gereklidir."
msgid "Change channel modes"
msgstr "Kanal modlarını değiştir"
-msgid "Change the communication method of Services"
+msgid "Change the communication method of services"
msgstr "Servislerin iletişim yöntemini değiştirme"
msgid "Change user modes"
@@ -2840,14 +2882,14 @@ msgstr "%s kullanıcı modları %s olarak değiştirildi."
msgid ""
"Changes the display used to refer to the nickname group in\n"
-"Services. The new display MUST be a nick of the group."
+"services. The new display MUST be a nick of the group."
msgstr ""
"Servislerdeki rumuz grubuna atıfta bulunmak için kullanılan\n"
"afişi değiştirir. Yeni afiş grubun bir rumuzu OLMALIDIR."
msgid ""
"Changes the display used to refer to your nickname group in\n"
-"Services. The new display MUST be a nick of your group."
+"services. The new display MUST be a nick of your group."
msgstr ""
"Servislerdeki rumuz grubunuza atıfta bulunmak için kullanılan\n"
"afişi değiştirir. Yeni afiş grubunuzun bir rumuzu OLMALIDIR."
@@ -2860,7 +2902,7 @@ msgstr ""
"olması gerekir.."
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"the given user (for example, when responding to a command they send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
@@ -2871,7 +2913,7 @@ msgstr ""
"seçilmelidir:"
msgid ""
-"Changes the language Services uses when sending messages to\n"
+"Changes the language services uses when sending messages to\n"
"you (for example, when responding to a command you send).\n"
"language should be chosen from the following list of\n"
"supported languages:"
@@ -2910,6 +2952,14 @@ msgstr ""
"erişim listesi boşsa\n"
"kanal düşürülür."
+#, c-format
+msgid "Changing your usermodes to %s"
+msgstr "Kullanıcı modlarınız %s olarak değiştiriliyor"
+
+#, c-format
+msgid "Changing your vhost to %s"
+msgstr "Vhostunuz %s olarak değiştiriliyor"
+
msgid "Channel"
msgstr "Kanal"
@@ -3012,8 +3062,8 @@ msgid "Channels that %s has access on:"
msgstr "%s tarafından erişilebilen kanallar:"
#, c-format
-msgid "Channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kanallar: %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Kanallar: %zu girdi, %zu buckets, en uzun zincir %zu"
msgid "Chanstats"
msgstr "Kanal İstatistikleri"
@@ -3043,7 +3093,7 @@ msgid ""
"or changing nick on the network and tells you when and, depending\n"
"on channel or user settings, where it was."
msgstr ""
-"rumuz'un ağa katıldığı, ayrıldığı veya rumuz değiştirdiği\n"
+"Bu ayar, rumuz'un ağa katıldığı, ayrıldığı veya rumuz değiştirdiği\n"
"son zamanı kontrol eder ve bunun ne zaman ve kanal veya kullanıcı\n"
"ayarlarına bağlı olarak nerede olduğunu size bildirir."
@@ -3054,7 +3104,7 @@ msgid ""
"Checks whether the _last_ memo you sent to nick has been read\n"
"or not. Note that this only works with nicks, not with channels."
msgstr ""
-"rumuz'a gönderdiğiniz _son_ memonun okunup okunmadığını kontrol eder\n"
+"Bu ayar, rumuz'a gönderdiğiniz _son_ memonun okunup okunmadığını kontrol eder\n"
"Bunun kanallarla değil, yalnızca rumuzlarla işe yaradığını unutmayın."
#, c-format
@@ -3164,20 +3214,23 @@ msgid "Current module list:"
msgstr "Geçerli modül listesi:"
#, c-format
-msgid "Current number of AKILLs: %d"
-msgstr "Geçerli AKILL sayısı: %d"
+msgid "Current number of AKILLs: %zu"
+msgstr "Geçerli AKILL sayısı: %zu"
#, c-format
-msgid "Current number of SNLINEs: %d"
-msgstr "Geçerli SNLINE sayısı: %d"
+msgid "Current number of SNLINEs: %zu"
+msgstr "Geçerli SNLINE sayısı: %zu"
#, c-format
-msgid "Current number of SQLINEs: %d"
-msgstr "Geçerli SQLINE sayısı: %d"
+msgid "Current number of SQLINEs: %zu"
+msgstr "Geçerli SQLINE sayısı: %zu"
#, c-format
-msgid "Current users: %d (%d ops)"
-msgstr "Geçerli kullanıcılar: %d (%d oper)"
+msgid "Current users: %zu (%d ops)"
+msgstr "Geçerli kullanıcılar: %zu (%d oper)"
+
+msgid "DEL entry-num"
+msgstr "DEL girdi-no"
msgid "DEL oper"
msgstr "DEL oper"
@@ -3191,9 +3244,6 @@ msgstr "DEL [rumuz] kanal"
msgid "DEL [nickname] fingerprint"
msgstr "DEL [rumuz] parmak-izi"
-msgid "DEL [nickname] mask"
-msgstr "DEL [rumuz] maske"
-
msgid "DEL {mask | entry-num | list | id}"
msgstr "DEL {maske | girdi-no | liste | id}"
@@ -3356,6 +3406,10 @@ msgid "Deleted %d entries from the AKILL list."
msgstr "%d girdi AKILL listesinden silindi."
#, c-format
+msgid "Deleted %u entries from your message queue."
+msgstr "%u girdi mesaj kuyruğunuzdan silindi."
+
+#, c-format
msgid "Deleted 1 entry from %s access list."
msgstr "1 girdi %s erişim listesinden silindi."
@@ -3385,6 +3439,9 @@ msgstr "Bilgiler %s'den silindi."
msgid "Deleted one entry from %s %s list."
msgstr "1 girdi %s %s listesinden silindi."
+msgid "Deleted one entry from your message queue."
+msgstr "1 girdi mesaj kuyruğunuzdan silindi."
+
msgid ""
"Deletes the specified memo or memos. You can supply\n"
"multiple memo numbers or ranges of numbers instead of a\n"
@@ -3563,18 +3620,6 @@ msgstr ""
"geçirebilecektir."
#, c-format
-msgid "E-mail address for %s changed to %s."
-msgstr "%s için e-posta adresi %s olarak değiştirildi."
-
-#, c-format
-msgid "E-mail address for %s unset."
-msgstr "%s için e-posta adresi ayarlanmadı."
-
-#, c-format
-msgid "E-mail for %s is invalid."
-msgstr "%s için e-posta geçersiz."
-
-#, c-format
msgid ""
"Edits or displays the list of logon news messages. When a\n"
"user connects to the network, these messages will be sent\n"
@@ -3615,10 +3660,22 @@ msgid "Email address"
msgstr "Eposta adresi"
#, c-format
+msgid "Email address for %s changed to %s."
+msgstr "%s için e-posta adresi %s olarak değiştirildi."
+
+#, c-format
+msgid "Email address for %s unset."
+msgstr "%s için e-posta adresi ayarlanmadı."
+
+#, c-format
+msgid "Email for %s is invalid."
+msgstr "%s için e-posta geçersiz."
+
+#, c-format
msgid "Email matched: %s (%s) to %s."
msgstr "E-posta eşleşti: %s (%s) - %s."
-msgid "Enable fantaisist commands"
+msgid "Enable fantasy commands"
msgstr "Fantezi komutlarını etkinleştir"
msgid "Enable greet messages"
@@ -3668,17 +3725,6 @@ msgstr ""
"ve bir sonraki kimlik doğrulama işleminizde bunları yeniden ayarlamaya çalışacaktır."
msgid ""
-"Enables or disables security features for a\n"
-"channel. When SECURE is set, only users who have\n"
-"identified to services, and are not only recognized, will be\n"
-"given access to channels from account-based access entries."
-msgstr ""
-"Bir kanal için güvenlik özelliklerini etkinleştirir veya devre dışı bırakır.\n"
-"SECURE ayarlandığında, yalnızca servislerle tanımlanan ve yalnızca\n"
-"tanınmayan kullanıcılara, hesap tabanlı erişim girişlerinden kanallara\n"
-"erişim izni verilecektir."
-
-msgid ""
"Enables or disables signed kicks for a\n"
"channel. When SIGNKICK is set, kicks issued with\n"
"the KICK command will have the nick that used the\n"
@@ -3829,8 +3875,8 @@ msgid "End of entry message list."
msgstr "Giriş mesajı listesi sonu."
#, c-format
-msgid "End of forbid list - %d/%d entries shown."
-msgstr "Yasak listesi sonu - %d/%d girdi gösterildi."
+msgid "End of forbid list - %zu/%zu entries shown."
+msgstr "Yasak listesi sonu - %zu/%zu girdi gösterildi."
msgid "End of forbid list."
msgstr "Yasak listesi sonu."
@@ -3883,7 +3929,7 @@ msgstr ""
"kullanıcıları atacaktır."
msgid "English"
-msgstr "İngilizce"
+msgstr "Türkçe"
#, c-format
msgid "Entry message %i for %s deleted."
@@ -3914,12 +3960,12 @@ msgid "Error reloading configuration file: %s"
msgstr "Yapılandırma dosyası yeniden yüklenirken hata oluştu: %s"
#, c-format
-msgid "Error! The vHost ident is too long, please use an ident shorter than %d characters."
-msgstr "Hata! vHost kimliği çok uzun, lütfen %d karakterden daha kısa bir ident kullanın."
+msgid "Error! The vhost is too long, please use a hostname shorter than %zu characters."
+msgstr "Hata! vHost çok uzun, lütfen %zu karakterden kısa bir host adı kullanın."
#, c-format
-msgid "Error! The vHost is too long, please use a hostname shorter than %d characters."
-msgstr "Hata! vHost çok uzun, lütfen %d karakterden kısa bir host adı kullanın."
+msgid "Error! The vident is too long, please use an ident shorter than %zu characters."
+msgstr "Hata! vIdent kimliği çok uzun, lütfen %zu karakterden daha kısa bir ident kullanın."
msgid ""
"Examples:\n"
@@ -4019,7 +4065,7 @@ msgstr "%s üzerinde yasaklama bulunamadı."
msgid "Forbid usage of nicknames, channels, and emails"
msgstr "Rumuzların, kanalların ve e-postaların kullanımını yasaklayın"
-msgid "Force the Services databases to be updated immediately"
+msgid "Force the services databases to be updated immediately"
msgstr "Servislerin veritabanlarının hemen güncelleştirilmesini zorunlu kılın"
msgid "Forcefully change a user's nickname"
@@ -4047,15 +4093,9 @@ msgstr "Kurucu"
msgid "Founder of %s changed to %s."
msgstr "%s kanalının kurucusu %s olarak değiştirildi."
-msgid "GETPASS command unavailable because encryption is in use."
-msgstr "Şifreleme kullanımda olduğundan GETPASS komutu kullanılamıyor."
-
msgid "Ghost with your nick has been killed."
msgstr "Rumuzunuzu taşıyan ghost killendi."
-msgid "Give Operflags to a certain user"
-msgstr "Belirli bir kullanıcıya Operflags (Oper Bayrakları) verin"
-
#, c-format
msgid ""
"Gives %s status to the selected nick on a channel. If nick is\n"
@@ -4160,11 +4200,11 @@ msgid "Info about a loaded module"
msgstr "Yüklü bir modül hakkında bilgi"
#, c-format
-msgid "Information for bot %s:"
+msgid "Information about bot %s:"
msgstr "%s botu ile ilgili bilgiler:"
#, c-format
-msgid "Information for channel %s:"
+msgid "Information about channel %s:"
msgstr "%s kanalı ile ilgili bilgiler:"
#, c-format
@@ -4181,7 +4221,7 @@ msgstr "Geçersiz host maskesi. İstisnalar, rumuzlar veya kullanıcı adlarıyl
msgid "Invalid limit %s, using %d."
msgstr "Geçersiz limit %s, %d kullanılıyor."
-msgid "Invalid passcode has been entered, please check the e-mail again, and retry."
+msgid "Invalid passcode has been entered, please check the email again, and retry."
msgstr "Geçersiz geçiş kodu girildi, lütfen e-postayı tekrar kontrol edin ve tekrar deneyin."
msgid "Invalid passcode."
@@ -4252,8 +4292,8 @@ msgid "LIMIT enforced by "
msgstr "LIMIT uygulandı. Uygulayan: "
#, c-format
-msgid "LIMIT enforced on %s, %d users removed."
-msgstr "%s kanalında LIMIT uygulandı, %d kullanıcı kaldırıldı."
+msgid "LIMIT enforced on %s, %zu users removed."
+msgstr "%s kanalında LIMIT uygulandı, %zu kullanıcı kaldırıldı."
msgid "LIST threshold"
msgstr "LIST eşik"
@@ -4271,7 +4311,7 @@ msgid "LOGONNEWS {ADD|DEL|LIST} [text|num]"
msgstr "LOGONNEWS {ADD|DEL|LIST} [metin|nu.]"
msgid "Language changed to English."
-msgstr "Dil İngilizce olarak değiştirildi."
+msgstr "Dil Türkçe olarak değiştirildi."
#, c-format
msgid "Language for %s changed to %s."
@@ -4745,7 +4785,7 @@ msgid ""
"Maintains the bad words list for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
-"type %s%s HELP KICK %s.\n"
+"type %s HELP KICK %s.\n"
" \n"
"The ADD command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -4757,17 +4797,17 @@ msgid ""
"be issued every time word is said by a user.\n"
" \n"
msgstr ""
-"Bir kanal için kötü kelimeler listesini (küfür) düzenler.\n"
-"Kötü kelimeler listesi, küfür atıcı etkinleştirildiğinde\n"
+"Bir kanal için küfür listesini düzenler.\n"
+"küfür listesi, küfürlü konuşanları atma etkinleştirildiğinde\n"
"hangi kelimelerin atılacağını belirler. Daha fazla bilgi\n"
-"için %s%s HELP KICK %s yazın.\n"
+"için %s HELP KICK %s yazın.\n"
" \n"
-"ADD komutu belirtilen kelimeyi kötü kelimeler\n"
+"ADD komutu belirtilen kelimeyi küfür\n"
"listesine ekler. SINGLE belirtilirse, yalnızca kullanıcı\n"
"kelimenin tamamını söylediğinde atış yapılacaktır. START\n"
-"belirtilirse, kullanıcı word ile başlayan bir\n"
+"belirtilirse, kullanıcı kelime ile başlayan bir\n"
"kelime söylerse atış yapılacaktır. END belirtilirse,\n"
-"kullanıcı word ile biten bir kelime söylerse\n"
+"kullanıcı kelime ile biten bir kelime söylerse\n"
"atış yapılacaktır. Herhangi bir şey belirtmezseniz, kullanıcı\n"
"tarafından kelime her söylendiğinde bir atış yapılır.\n"
" \n"
@@ -4825,6 +4865,9 @@ msgstr "Memo yoksayma listesini yönetin"
msgid "Manage your auto join list"
msgstr "Oto-gir listenizi yönetin"
+msgid "Manages your pending message queue."
+msgstr "Bekleyen mesaj sıranızı yönetir."
+
#, c-format
msgid "Manipulate the %s list"
msgstr "%s listesini düzenleme"
@@ -4841,10 +4884,6 @@ msgstr "Belirtilen kanalın başlığını değiştirin"
msgid "Mask"
msgstr "Maske"
-#, c-format
-msgid "Mask %s already present on %s's access list."
-msgstr "%s maskesi zaten %s'in erişim listesinde mevcut."
-
msgid "Mask must be in the form user@host."
msgstr "Maske ident@host biçiminde olmalıdır."
@@ -4870,6 +4909,10 @@ msgstr "%d memosu, %s (%s) adlı kişiden."
msgid "Memo %d has been deleted."
msgstr "%d memosu silindi."
+#, c-format
+msgid "Memo %zu has been deleted."
+msgstr "%zu memosu silindi."
+
msgid "Memo ignore list is empty."
msgstr "Memo yoksayma listesi boş."
@@ -4906,6 +4949,10 @@ msgstr "Metod"
msgid "Missing parameter for mode %c."
msgstr "%c modu için eksik parametre."
+#, c-format
+msgid "Missing passwords: %zu"
+msgstr "Eksik şifreler: %zu"
+
msgid "Mode"
msgstr "Mod"
@@ -4931,48 +4978,6 @@ msgstr "Modlar"
msgid "Modes cleared on %s and the channel destroyed."
msgstr "%s'de modlar temizlendi ve kanal yok edildi."
-#, c-format
-msgid ""
-"Modifies or displays the access list for your nick. This\n"
-"is the list of addresses which will be automatically\n"
-"recognized by %s as allowed to use the nick. If\n"
-"you want to use the nick from a different address, you\n"
-"need to send an IDENTIFY command to make %s\n"
-"recognize you. Services Operators may provide a nick\n"
-"to modify other users' access lists.\n"
-" \n"
-"Examples:\n"
-" \n"
-" ACCESS ADD anyone@*.bepeg.com\n"
-" Allows access to user anyone from any machine in\n"
-" the bepeg.com domain.\n"
-" \n"
-" ACCESS DEL anyone@*.bepeg.com\n"
-" Reverses the previous command.\n"
-" \n"
-" ACCESS LIST\n"
-" Displays the current access list."
-msgstr ""
-"Rumuzunuzun erişim listesini değiştirir veya görüntüler. Bu,\n"
-"%s tarafından otomatik olarak tanınacak ve rumuzun kullanılmasına\n"
-"izin verilen adreslerin listesidir. Eğer farklı bir adresten rumuzu\n"
-"kullanmak istiyorsanız, %s tarafından tanınmanızı sağlayacak\n"
-"bir IDENTIFY komutu göndermeniz gerekmektedir.\n"
-"Servis Operatörleri, diğer kullanıcıların erişim listelerini\n"
-"değiştirmek için bir rumuz sağlayabilir.\n"
-" \n"
-"Örnekler:\n"
-" \n"
-" ACCESS ADD herkes@*.bepeg.com\n"
-" bepeg.com etki alanındaki herhangi bir makineden\n"
-" herkes kullanıcısına erişim sağlar.\n"
-" \n"
-" ACCESS DEL herkes@*.bepeg.com\n"
-" Önceki komutu tersine çevirir.\n"
-" \n"
-" ACCESS LIST\n"
-" Geçerli erişim listesini görüntüler."
-
msgid ""
"Modifies or displays the certificate list for your nick.\n"
"If you connect to IRC and provide a client certificate with a\n"
@@ -4988,22 +4993,19 @@ msgstr ""
"sertifika listelerini değiştirmek için bir rumuz sağlayabilir.\n"
" \n"
-msgid "Modify the Services ignore list"
-msgstr "Servislerin yoksayma listesini değiştirin"
-
#, c-format
msgid "Modify the list of %s users"
msgstr "%s kullanıcı listesini değiştirin"
-msgid "Modify the list of authorized addresses"
-msgstr "Yetkili adresler listesini değiştirin"
-
msgid "Modify the list of privileged users"
msgstr "Ayrıcalıklı kullanıcıların listesini değiştirin"
msgid "Modify the nickname client certificate list"
msgstr "Rumuz istemci sertifikası listesini değiştirin"
+msgid "Modify the services ignore list"
+msgstr "Servislerin yoksayma listesini değiştirin"
+
msgid "Modify the session-limit exception list"
msgstr "Oturum sınırı istisna listesini değiştirin"
@@ -5054,6 +5056,9 @@ msgstr "%s için ağ istatistikleri:"
msgid "Never"
msgstr "Hiç"
+msgid "Never-op"
+msgstr "Hiç"
+
msgid "Nick"
msgstr "Rumuz"
@@ -5102,8 +5107,8 @@ msgid "Nick %s isn't registered."
msgstr "%s rumuzu kayıtlı değil."
#, c-format
-msgid "Nick %s was truncated to %d characters."
-msgstr "%s rumuzu, %d karaktere kısaltıldı."
+msgid "Nick %s was truncated to %zu characters."
+msgstr "%s rumuzu, %zu karaktere kısaltıldı."
#, c-format
msgid "Nick %s will expire."
@@ -5145,9 +5150,12 @@ msgstr "%s rumuzu şuan serbest bırakıldı."
msgid "Nick %s is now suspended."
msgstr "%s rumuzu askıya alınmış."
+msgid "Nick registered"
+msgstr "Rumuz kaydedildi"
+
#, c-format
-msgid "Nick too long, max length is %u characters."
-msgstr "Rumuz çok uzun, maks uzunluk %u karakterdir."
+msgid "Nick too long, max length is %zu characters."
+msgstr "Rumuz çok uzun, maks uzunluk %zu karakterdir."
#, c-format
msgid "Nickname %s has been dropped."
@@ -5162,10 +5170,6 @@ msgid "Nickname %s may not be registered."
msgstr "%s kayıtlı olmayabilir."
#, c-format
-msgid "Nickname %s registered under your user@host-mask: %s"
-msgstr "%s rumuzu ident@host-maskeniz'e kayıtlı: %s"
-
-#, c-format
msgid "Nickname %s registered."
msgstr "%s rumuzu kayıtlı."
@@ -5197,6 +5201,9 @@ msgstr "Silinecek oturum açma haberi yok!"
msgid "No matches for %s found."
msgstr "%s için eşleşme bulunamadı."
+msgid "No matching entries in your message queue."
+msgstr "Mesaj kuyruğunuzda eşleşen girdi yok."
+
#, c-format
msgid "No matching entries on %s %s list."
msgstr "%s %s listesinde eşleşen girdi yok."
@@ -5340,14 +5347,6 @@ msgid "Oper type %s has not been configured."
msgstr "Oper türü %s yapılandırılmadı."
#, c-format
-msgid "Operflags %s have been added for %s."
-msgstr "%s oper bayrakları, %s için eklendi."
-
-#, c-format
-msgid "Operflags %s have been removed from %s."
-msgstr "%s oper bayrakları, %s'den kaldırıldı."
-
-#, c-format
msgid "Opertype %s has no allowed commands."
msgstr "%s oper türünde izin verilen komut yok."
@@ -5378,17 +5377,9 @@ msgid "Password accepted."
msgstr "Şifre kabul edildi."
#, c-format
-msgid "Password for %s changed to %s."
-msgstr "%s şifresi, %s olarak değiştirildi."
-
-#, c-format
msgid "Password for %s changed."
msgstr "%s şifresi değiştirildi."
-#, c-format
-msgid "Password for %s is %s."
-msgstr "%s şifresi %s'dir."
-
msgid "Password incorrect."
msgstr "Şifre doğru değil."
@@ -5396,6 +5387,13 @@ msgstr "Şifre doğru değil."
msgid "Password reset email for %s has been sent."
msgstr "%s için şifre sıfırlama e-postası gönderildi."
+msgid "Passwords can not be changed right now. Please try again later."
+msgstr "Şifreler şu anda değiştirilemez. Lütfen daha sonra tekrar deneyiniz."
+
+#, c-format
+msgid "Passwords encrypted with %s: %zu"
+msgstr "%s ile şifrelenen şifreler: %zu"
+
msgid "Peace"
msgstr "Barış"
@@ -5410,17 +5408,21 @@ msgstr "%s için barış seçeneği artık on açık."
msgid "Persistent"
msgstr "Kalıcı"
-msgid "Please contact an Operator to get a vHost assigned to this nick."
+#, c-format
+msgid "Please confirm that you want to drop %s with %s DROP %s %s"
+msgstr "Lütfen %s rumuzunu droplamak isteğinizi %s DROP %s %s ile onaylayın"
+
+msgid "Please contact an Operator to get a vhost assigned to this nick."
msgstr "Bu rumuza atanan bir vHost almak için lütfen bir operle iletişime geçin."
msgid ""
-"Please try again with a more obscure password. Passwords should be at least\n"
-"five characters long, should not be something easily guessed\n"
-"(e.g. your real name or your nick), and cannot contain the space or tab characters."
+"Please try again with a more obscure password. Passwords should not be\n"
+"something that could be easily guessed (e.g. your real name or your nick) and\n"
+"cannot contain the space or tab characters.\n"
msgstr ""
"Lütfen daha belirsiz bir şifreyle tekrar deneyin. Şifreler en az beş karakter\n"
"uzunluğunda olmalı, kolay tahmin edilebilir olmamalı (örneğin gerçek adınız \n"
-"veya rumuzunuz) ve boşluk veya sekme karakterlerini içermemelidir."
+"veya rumuzunuz) ve boşluk veya sekme karakterlerini içermemelidir.\n"
msgid "Please use a valid server name when juping."
msgstr "Lütfen atlama yaparken geçerli bir sunucu adı kullanın."
@@ -5429,24 +5431,24 @@ msgid "Please use the symbol of # when attempting to register."
msgstr "Lütfen kaydolmaya çalışırken # sembolünü kullanın."
#, c-format
-msgid "Please wait %d seconds and retry."
-msgstr "Lütfen %d saniye bekleyip yeniden deneyin."
+msgid "Please wait %lu seconds and retry."
+msgstr "Lütfen %lu saniye bekleyip yeniden deneyin."
#, c-format
-msgid "Please wait %d seconds before requesting a new vHost."
-msgstr "Yeni bir vHost istemeden önce lütfen %d saniye bekleyin."
+msgid "Please wait %lu seconds before requesting a new vhost."
+msgstr "Yeni bir vHost istemeden önce lütfen %lu saniye bekleyin."
#, c-format
-msgid "Please wait %d seconds before using the %s command again."
-msgstr "Lütfen %d saniye bekleyin (%s komutunu tekrar kullanmadan önce)."
+msgid "Please wait %lu seconds before using the %s command again."
+msgstr "Lütfen %lu saniye bekleyin (%s komutunu tekrar kullanmadan önce)."
#, c-format
-msgid "Please wait %d seconds before using the GROUP command again."
-msgstr "GROUP komutunu tekrar kullanmadan önce lütfen %d saniye bekleyin."
+msgid "Please wait %lu seconds before using the GROUP command again."
+msgstr "GROUP komutunu tekrar kullanmadan önce lütfen %lu saniye bekleyin."
#, c-format
-msgid "Please wait %d seconds before using the REGISTER command again."
-msgstr "REGISTER komutunu tekrar kullanmadan önce lütfen %d saniye bekleyin."
+msgid "Please wait %lu seconds before using the REGISTER command again."
+msgstr "REGISTER komutunu tekrar kullanmadan önce lütfen %lu saniye bekleyin."
#, c-format
msgid "Pooled %s."
@@ -5476,7 +5478,7 @@ msgstr "Rumuzun LIST komutunda görünmesini önleyin"
msgid "Prevent the nickname from expiring"
msgstr "Rumuzun süresinin dolmasını önleyin"
-msgid "Prevents users being kicked by Services"
+msgid "Prevents users being kicked by services"
msgstr "Kullanıcıların Servisler tarafından atılmasını önler"
msgid "Private"
@@ -5634,16 +5636,16 @@ msgid "Registered"
msgstr "Kayıt Tarihi"
#, c-format
-msgid "Registered channels: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kayıtlı kanallar: %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Registered channels: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Kayıtlı kanallar: %zu girdi, %zu buckets, en uzun zincir %zu"
#, c-format
-msgid "Registered nick groups: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kayıtlı rumuz grupları: %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Kayıtlı rumuz grupları: %zu girdi, %zu buckets, en uzun zincir %zu"
#, c-format
-msgid "Registered nicknames: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kayıtlı rumuzlar: %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Kayıtlı rumuzlar: %zu girdi, %zu buckets, en uzun zincir %zu"
#, c-format
msgid "Registered only enforced on %s."
@@ -5692,7 +5694,7 @@ msgid ""
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
-"you should choose a password at least 5 characters long.\n"
+"you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."
msgstr ""
"Rumuzunuzu %s veritabanına kaydedin. Rumuzunuz kaydedildikten\n"
@@ -5709,7 +5711,7 @@ msgstr ""
"gerçek adınızı şifre olarak kullanmak kötü bir fikirdir.\n"
"Rumuzunuzu şifre olarak kullanmak çok daha kötü bir fikir ;)\n"
"ve aslında %s buna izin vermeyecektir. Ayrıca kısa şifreler\n"
-"deneme yanılma yoluyla aranmaya açık olduğundan en az 5\n"
+"deneme yanılma yoluyla aranmaya açık olduğundan en az %u\n"
"karakter uzunluğunda bir şifre seçmelisiniz. Son\n"
"olarak boşluk karakteri şifrelerde kullanılamaz."
@@ -5719,11 +5721,11 @@ msgstr "Kayıt şu anda devre dışı."
msgid "Regulate the use of critical commands"
msgstr "Kritik komutların kullanımını düzenleyin"
-msgid "Reject the requested vHost for the given nick."
+msgid "Reject the requested vhost for the given nick."
msgstr "Belirtilen rumuz için istenen vHost'u reddedin."
-msgid "Reject the requested vHost of a user"
-msgstr "Bir kullanıcının talep edilen vhostunu reddeder"
+msgid "Reject the requested vhost of a user"
+msgstr "Bir kullanıcının talep edilen vHostunu reddeder"
msgid "Releases a suspended channel"
msgstr "Suspend edilmiş bir kanalı serbest bırakır"
@@ -5793,11 +5795,11 @@ msgstr "%s kaldırılıyor (%s kapsadığı için)."
msgid "Repeat kicker"
msgstr "Tekrar yazı atma"
-msgid "Request a vHost for your nick"
+msgid "Request a vhost for your nick"
msgstr "Rumuzunuz için bir vhost talep edin"
msgid ""
-"Request the given vHost to be activated for your nick by the\n"
+"Request the given vhost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."
msgstr ""
@@ -5820,7 +5822,7 @@ msgstr "%s için kısıtlı erişim seçeneği artık off (kapalı)."
#, c-format
msgid "Restricted access option for %s is now on."
-msgstr "%s için kısıtlı erişim seçeneği artık "
+msgstr "%s için kısıtlı erişim seçeneği artık on (açık)."
#, c-format
msgid "Restricted enforced on %s."
@@ -5832,9 +5834,6 @@ msgstr "Kanal kullanılmadığında modları koruma"
msgid "Retain topic when channel is not in use"
msgstr "Kanal kullanılmadığında başlığı koruma"
-msgid "Retrieve the password for a nickname"
-msgstr "Bir rumuzun şifresini alın"
-
msgid "Retrieves the vhost requests"
msgstr "Vhost taleplerini alır"
@@ -5847,55 +5846,6 @@ msgstr "Belirtilen kanalın anahtarını gösterir."
msgid "Returns the matching accounts that used given email."
msgstr "Belirtilen e-postayı kullanan eşleşen hesapları gösterir."
-msgid "Returns the owner status of the given nickname"
-msgstr "Belirtilen rumuzun sahiplik durumunu gösterir"
-
-msgid ""
-"Returns the password for the given nickname. Note that\n"
-"whenever this command is used, a message including the\n"
-"person who issued the command and the nickname it was used\n"
-"on will be logged and sent out as a WALLOPS/GLOBOPS."
-msgstr ""
-"Belirtilen rumuzun şifresini döndürür. Not Bu komut her\n"
-"kullanıldığında, komutu veren kişiyi ve komutun kullanıldığı\n"
-"rumuzu içeren bir mesajın günlüğe kaydedileceğini ve\n"
-"WALLOPS/GLOBOPS olarak gönderileceğini unutmayın."
-
-msgid ""
-"Returns whether the user using the given nickname is\n"
-"recognized as the owner of the nickname. The response has\n"
-"this format:\n"
-" \n"
-" nickname status-code account\n"
-" \n"
-"where nickname is the nickname sent with the command,\n"
-"status-code is one of the following, and account\n"
-"is the account they are logged in as.\n"
-" \n"
-" 0 - no such user online or nickname not registered\n"
-" 1 - user not recognized as nickname's owner\n"
-" 2 - user recognized as owner via access list only\n"
-" 3 - user recognized as owner via password identification\n"
-" \n"
-"If no nickname is given, your status will be returned."
-msgstr ""
-"Belirtilen rumuzu kullanan kullanıcının, rumuzun sahibi\n"
-"olarak tanınıp tanınmadığını döndürür. Yanıt şu\n"
-"formattadır:\n"
-" \n"
-" rumuz durum-kodu hesap\n"
-" \n"
-"burada rumuz komutla gönderilen rumuzdur, durum-kodu\n"
-"aşağıdakilerden biridir ve hesap oturum\n"
-"açtıkları hesaptır.\n"
-" \n"
-" 0 - böyle bir çevrimiçi kullanıcı yokveya rumuzu kayıtlı değil\n"
-" 1 - kullanıcı rumuzun sahibi olarak tanınmadı\n"
-" 2 - kullanıcı yalnızca erişim listesi aracılığıyla sahip olarak tanındı\n"
-" 3 - kullanıcı, şifre tanımlama yoluyla sahip olarak tanındı\n"
-" \n"
-"Rumuz belirtilmezse kendi durumunuzu geri döndürecektir."
-
msgid "Reverses kicker"
msgstr "Reverse yazı atma"
@@ -5922,7 +5872,7 @@ msgstr "SSL yalnızca %s üzerinde uygulandı."
msgid "SSLONLY enforced by "
msgstr "SSLONLY, uygulayan: "
-msgid "Save databases and restart Services"
+msgid "Save databases and restart services"
msgstr "Veritabanlarını kaydedin ve Servisleri yeniden başlatın"
msgid "Searches logs for a matching pattern"
@@ -5951,42 +5901,23 @@ msgid "Secure ops option for %s is now on."
msgstr "%s için OPları koruma seçeneği artık on (açık)."
#, c-format
-msgid "Secure option for %s is now off."
-msgstr "%s için Güvenlik seçeneği artık off (kapalı)."
-
-#, c-format
-msgid "Secure option for %s is now on."
-msgstr "%s için Güvenlik seçeneği artık on (açık)."
-
-#, c-format
-msgid "Secure option is now off for %s."
-msgstr "%s için Güvenlik seçeneği artık off (kapalı)."
-
-#, c-format
-msgid "Secure option is now on for %s."
-msgstr "%s için Güvenlik seçeneği artık on (açık)."
-
-#, c-format
msgid "Secureops enforced on %s."
msgstr "OPları koruma %s'de uygulandı."
-msgid "Security"
-msgstr "Güvenlik"
-
#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the access list."
msgstr ""
-"Erişim listesi hakkında detaylı bilgi için %s%s HELP %s\n"
+"Erişim listesi hakkında detaylı bilgi için %s HELP %s\n"
"komut çıktısına bakın."
#, c-format
msgid ""
-"See %s%s HELP %s for more information\n"
+"See %s HELP %s for more information\n"
"about the flags system."
msgstr ""
-"Bayrak sistemi hakkında detaylı bilgi için %s%s HELP %s\n"
+"Bayrak sistemi hakkında detaylı bilgi için %s HELP %s\n"
"komut çıktısına bakın."
msgid "Send a memo to a nick or channel"
@@ -6001,6 +5932,9 @@ msgstr "Kayıtlı tüm kullanıcılara bir memo gönderin"
msgid "Send a message to all users"
msgstr "Tüm kullanıcılara bir mesaj gönderin"
+msgid "Send a message to all users on a server"
+msgstr "Sunucudaki tüm kullanıcılara bir mesaj gönderin"
+
msgid "Sender"
msgstr "Gönderen"
@@ -6075,6 +6009,10 @@ msgid "Server"
msgstr "Sunucu"
#, c-format
+msgid "Server %s is not linked to the network."
+msgstr "%s sunucusu ağa bağlı değil."
+
+#, c-format
msgid "Server %s added to zone %s."
msgstr "%s sunucusu %s bölgesine eklendi."
@@ -6138,9 +6076,6 @@ msgstr "Servis Operatörü komutları"
msgid "Services are in DefCon mode, please try again later."
msgstr "Servisler DefCon modunda, lütfen daha sonra tekrar deneyin."
-msgid "Services are in read-only mode!"
-msgstr "Servisler salt okunur modunda!"
-
#, c-format
msgid "Services are now at DEFCON %d."
msgstr "Servisler artık DEFCON %d modunda."
@@ -6167,6 +6102,9 @@ msgstr "Servisler artık salt-okunur modundadır."
msgid "Services are now in read-write mode."
msgstr "Servisler artık okunur-yazılır modunda."
+msgid "Services are temporarily in read-only mode."
+msgstr "Servisler artık salt-okunur modundadır."
+
msgid "Services have been configured to not send mail."
msgstr "Servisler posta göndermeyecek şekilde yapılandırıldı."
@@ -6218,8 +6156,8 @@ msgid "Session limiting is disabled."
msgstr "Oturum limitleme devre dışı."
#, c-format
-msgid "Sessions: %lu entries, %lu buckets, longest chain is %d"
-msgstr "Oturumlar: %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Sessions: %zu entries, %zu buckets, longest chain is %zu"
+msgstr "Oturumlar: %zu girdi, %zu buckets, en uzun zincir %zu"
msgid "Set SET-options on another nickname"
msgstr "Başka bir rumuzda SET-seçeneklerini ayarlayın"
@@ -6227,7 +6165,7 @@ msgstr "Başka bir rumuzda SET-seçeneklerini ayarlayın"
msgid "Set channel options and information"
msgstr "Kanal seçeneklerini ve bilgilerini ayarlayın"
-msgid "Set how Services make bans on the channel"
+msgid "Set how services make bans on the channel"
msgstr "Servislerin kanalda nasıl banlama yapacağını ayarlayın"
msgid "Set options related to memos"
@@ -6242,13 +6180,13 @@ msgstr "Kanalı kalıcı olarak ayarla"
msgid "Set the channel description"
msgstr "Kanal açıklamasını ayarlayın"
-msgid "Set the display of your group in Services"
+msgid "Set the display of your group in services"
msgstr "Servislerde grubunuzun afişini ayarlayın"
msgid "Set the founder of a channel"
msgstr "Kanalın founderını (kurucusunu )ayarlama"
-msgid "Set the language Services will use when messaging you"
+msgid "Set the language services will use when messaging you"
msgstr "Servislerin size mesaj gönderirken kullanacağı dili ayarlayın"
msgid "Set the nickname password"
@@ -6263,7 +6201,7 @@ msgstr "Bir gruptaki tüm rumuzların vhostunu ayarlayın"
msgid "Set the vhost of another user"
msgstr "Başka bir kullanıcının vhostunu ayarlayın"
-msgid "Set various global Services options"
+msgid "Set various global services options"
msgstr "Çeşitli genel Servis seçeneklerini ayarlama"
msgid "Set your nickname password"
@@ -6293,7 +6231,7 @@ msgid ""
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
-"BADWORDS command. Type %s%s HELP BADWORDS for\n"
+"BADWORDS command. Type %s HELP BADWORDS for\n"
"more information.\n"
" \n"
"ttb is the number of times a user can be kicked\n"
@@ -6305,7 +6243,7 @@ msgstr ""
"söyleyen kullanıcıları atmasını söyler.\n"
"BADWORDS komutunu kullanarak kanalınıza küfür\n"
"tanımlayabilirsiniz. Daha fazla bilgi için\n"
-"%s%s HELP BADWORDS yazın.\n"
+"%s HELP BADWORDS yazın.\n"
" \n"
"ttb, bir kullanıcının banlanmadan önce atılabileceği\n"
"sayıdır. Ban sistemini aktif hale getirdikten sonra devre dışı\n"
@@ -6480,7 +6418,7 @@ msgstr ""
msgid ""
"Sets the vhost for all nicks in the same group as that\n"
-"of the given nick. If your IRCD supports vIdents, then\n"
+"of the given nick. If your IRCD supports vidents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
@@ -6495,7 +6433,7 @@ msgstr ""
msgid ""
"Sets the vhost for the given nick to that of the given\n"
-"hostmask. If your IRCD supports vIdents, then using\n"
+"hostmask. If your IRCD supports vidents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."
msgstr ""
@@ -6505,7 +6443,7 @@ msgstr ""
"hem de vhostlar için identleri ayarlayın."
msgid ""
-"Sets various global Services options. Option names\n"
+"Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -6530,7 +6468,7 @@ msgid ""
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
"Çeşitli memo seçeneklerini ayarlar. seçenek şunlardan biri olabilir:\n"
@@ -6541,7 +6479,7 @@ msgstr ""
" ayarlar\n"
" \n"
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
-"%s%s HELP %s seçenek yazın."
+"%s HELP %s seçenek yazın."
msgid "Sets various nickname options. option can be one of:"
msgstr "Çeşitli rumuz seçeneklerini ayarlar. seçenek şunlardan biri olabilir:"
@@ -6556,6 +6494,9 @@ msgstr ""
"Belirtilen kanalın süresinin dolup dolmayacağını ayarlar. Bunu ON \n"
"(AÇIK) olarak ayarlamak kanalın süresinin dolmasını önler."
+msgid "Sets whether the given nickname can be added to a channel access list."
+msgstr "Belirtilen rumuzun kanal erişim listesine eklenip eklenemeyeceğini ayarlar."
+
#, c-format
msgid ""
"Sets whether the given nickname will be given its status modes\n"
@@ -6577,6 +6518,9 @@ msgstr ""
"Belirtilen rumuzun süresinin dolup dolmayacağını ayarlar. Bunu ON\n"
"(AÇIK) olarak ayarlamak rumuzun süresinin dolmasını önler."
+msgid "Sets whether you can be added to a channel access list."
+msgstr "Bir kanalı, onun kendi erişim listesine ekleyemezsiniz."
+
#, c-format
msgid ""
"Sets whether you will be given your channel status modes automatically.\n"
@@ -6590,8 +6534,8 @@ msgstr ""
"modların otomatik olarak ayarlanamayacağını unutmayın."
#, c-format
-msgid "Setting %s not known. Type %s%s HELP LEVELS for a list of valid settings."
-msgstr "%s ayarı bilinmiyor. Geçerli ayarların listesi için %s%s HELP LEVELS yazın."
+msgid "Setting %s not known. Type %s HELP LEVELS for a list of valid settings."
+msgstr "%s ayarı bilinmiyor. Geçerli ayarların listesi için %s HELP LEVELS yazın."
msgid "Setting for DEBUG must be ON, OFF, or a positive number."
msgstr "DEBUG ayarı ON, OFF veya pozitif bir sayı olmalıdır."
@@ -6608,12 +6552,12 @@ msgstr "Super Admin ayarı ON veya OFF olmalıdır."
msgid "Should services automatically give status to users"
msgstr "Servisler kullanıcılara otomatik olarak durum vermeli mi"
-msgid "Show status of Services and network"
+msgid "Show status of services and network"
msgstr "Servislerin ve ağın durumunu göster"
#, c-format
-msgid "Showed %d/%d matches for %s."
-msgstr "%d/%d eşleşme (%s için) gösteriliyor."
+msgid "Showed %zu/%zu matches for %s."
+msgstr "%zu/%zu eşleşme (%s için) gösteriliyor."
msgid "Sign kicks that are done with the KICK command"
msgstr "KICK komutuyla yapılan atmaları işaretleme"
@@ -6642,61 +6586,12 @@ msgid "Sorry, %s currently has too many memos and cannot receive more."
msgstr "Üzgünüz, %s'de şu anda çok fazla memo var ve daha fazlasını alamıyor."
#, c-format
-msgid "Sorry, I have not seen %s."
-msgstr "Üzgünüz, %s'i görmedim."
-
-msgid "Sorry, bad words list modification is temporarily disabled."
-msgstr "Üzgünüz, küdür listesi değişikliği geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, bot assignment is temporarily disabled."
-msgstr "Üzgünüz, bot ataması geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, bot modification is temporarily disabled."
-msgstr "Üzgünüz, bot düzenleme geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, bot option setting is temporarily disabled."
-msgstr "Üzgünüz, bot seçeneği ayarı geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, changing bot options is temporarily disabled."
-msgstr "Üzgünüz, bot seçeneklerini değiştirmek geçici olarak devre dışı bırakıldı."
+msgid "Sorry, %s is temporarily unavailable."
+msgstr "Üzgünüz, %s geçici olarak devre dışı bırakıldı."
#, c-format
-msgid "Sorry, channel %s list modification is temporarily disabled."
-msgstr "Üzgünüz, %s kanalının liste değişikliği geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, channel access list modification is temporarily disabled."
-msgstr "Üzgünüz, kanal erişim listesi değişikliği geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, channel autokick list modification is temporarily disabled."
-msgstr "Üzgünüz, kanal oto-at listesi değişikliği geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, channel de-registration is temporarily disabled."
-msgstr "Üzgünüz, kanal kaydının silinmesi geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, channel registration is temporarily disabled."
-msgstr "Üzgünüz, kanal kaydetme geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, kicker configuration is temporarily disabled."
-msgstr "Üzgünüz, kicker (atma) yapılandırması geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, memo option setting is temporarily disabled."
-msgstr "Üzgünüz, memo seçeneği ayarı geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, memo sending is temporarily disabled."
-msgstr "Üzgünüz, memo gönderimi geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, nickname de-registration is temporarily disabled."
-msgstr "Üzgünüz, rumuz kaydının silinmesi geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, nickname grouping is temporarily disabled."
-msgstr "Üzgünüz, rumuz gruplaması geçici olarak devre dışı bırakıldı."
-
-msgid "Sorry, nickname registration is temporarily disabled."
-msgstr "Üzgünüz, rumuz kaydetme geçici olarak devre dışı bırakıldı."
-
-#, c-format
-msgid "Sorry, the maximum of %d access entries has been reached."
-msgstr "Üzgünüz, maksimum %d erişim girdisine ulaşıldı."
+msgid "Sorry, I have not seen %s."
+msgstr "Üzgünüz, %s'i görmedim."
#, c-format
msgid "Sorry, the maximum of %d auto join entries has been reached."
@@ -6986,13 +6881,13 @@ msgid ""
"Syntax: READONLY {ON | OFF}\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
-"users will not be allowed to modify any Services data,\n"
-"including channel and nickname access lists, etc. IRCops\n"
-"with sufficient Services privileges will be able to modify\n"
+"users will not be allowed to modify any services data,\n"
+"including channel access lists, etc. Server operators\n"
+"with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
-"unless read-only mode is deactivated before Services are\n"
+"unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
@@ -7077,8 +6972,8 @@ msgstr ""
"sahip olanlarla sınırlıdır."
msgid ""
-"Tells Services to jupiter a server -- that is, to create\n"
-"a fake \"server\" connected to Services which prevents\n"
+"Tells services to jupiter a server -- that is, to create\n"
+"a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard SQUIT. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -7098,7 +6993,7 @@ msgstr ""
msgid "Tells you about the last time a user was seen"
msgstr "Bir kullanıcının en son ne zaman görüldüğünü size bildirir"
-msgid "Terminate Services WITHOUT saving"
+msgid "Terminate services WITHOUT saving"
msgstr "Servisleri KAYDETMEDEN sonlandırın"
msgid "Terminate services with save"
@@ -7328,15 +7223,11 @@ msgstr "STATS komutu, depolanan rumuzlar ve hafıza kullanımıyla ilgili ista
msgid ""
"The email parameter is optional and will set the email\n"
-"for your nick immediately.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person. You may also wish to SET HIDE it\n"
+"for your nick immediately. You may also wish to SET HIDE it\n"
"after registering if it isn't the default setting already."
msgstr ""
-"email parametresi isteğe bağlıdır ve rumuzunuzun e-postasını\n"
-"hemen ayarlayacaktır.\n"
-"Gizliliğinize saygı duyulur; bu e-posta hiçbir üçüncü tarafa\n"
-"verilmeyecektir. Zaten varsayılan ayar değilse, kayıttan sonra\n"
+"Bu email parametresi isteğe bağlıdır ve rumuzunuzun e-postasını\n"
+"hemen ayarlayacaktır. Zaten varsayılan ayar değilse, kayıttan sonra\n"
"bunu SET HIDE yapmak da isteyebilirsiniz."
#, c-format
@@ -7396,14 +7287,6 @@ msgstr "AKILL listesi temizlendi."
msgid "The Defcon level is now at: %d"
msgstr "Defcon seviyesi şu anda: %d"
-#, c-format
-msgid "The E-mail address of %s will now be hidden from %s INFO displays."
-msgstr "%s e-posta adresi artık %s BİLGİ ekranlarında gizlenecek."
-
-#, c-format
-msgid "The E-mail address of %s will now be shown in %s INFO displays."
-msgstr "%s e-posta adresi artık %s BİLGİ ekranlarında gösterilecektir."
-
msgid "The available flags are:"
msgstr "Mevcut bayraklar şunlardır:"
@@ -7425,6 +7308,14 @@ msgid "The email address %s has reached its usage limit of 1 user."
msgstr "%s e-posta adresi 1 kullanıcılık kullanım sınırına ulaştı."
#, c-format
+msgid "The email address of %s will now be hidden from %s INFO displays."
+msgstr "%s e-posta adresi artık %s BİLGİ ekranlarında gizlenecek."
+
+#, c-format
+msgid "The email address of %s will now be shown in %s INFO displays."
+msgstr "%s e-posta adresi artık %s BİLGİ ekranlarında gösterilecektir."
+
+#, c-format
msgid "The entry message list for %s is full."
msgstr "%s için giriş mesajı listesi dolu."
@@ -7523,8 +7414,8 @@ msgstr ""
"üzerindeki beklemesini kaldırmak için bu komutu tekrar kullanın."
#, c-format
-msgid "There are %d memos on channel %s."
-msgstr "%d memo (%s kanalında) var."
+msgid "There are %zu memos on channel %s."
+msgstr "%zu memo (%s kanalında) var."
msgid ""
"There are no bots available at this time.\n"
@@ -7548,16 +7439,16 @@ msgid "There currently are no logging configurations for %s."
msgstr "Şu anda %s için günlük kaydı yapılandırması yok."
#, c-format
-msgid "There is %d memo on channel %s."
-msgstr "%d memo (%s kanalında) var."
+msgid "There is %zu memo on channel %s."
+msgstr "%zu memo (%s kanalında) var."
#, c-format
msgid ""
"There is a new memo on channel %s.\n"
-"Type %s%s READ %s %d to read it."
+"Type %s READ %s %zu to read it."
msgstr ""
"%s kanalında yeni bir memo var. Okumak için\n"
-"%s%s READ %s %d yazın."
+"%s READ %s %zu yazın."
#, c-format
msgid "There is no bot assigned to %s anymore."
@@ -7773,7 +7664,7 @@ msgid "This command retrieves the vhost requests."
msgstr "Bu komut, vhost isteklerini alır."
msgid ""
-"This command searches the Services logfiles for messages\n"
+"This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -7830,14 +7721,6 @@ msgid "This command will resend you the registration confirmation email."
msgstr "Bu komut size kayıt onay e-postasını tekrar gönderecektir."
#, c-format
-msgid ""
-"This nick is owned by someone else. Please choose another.\n"
-"(If this is your nick, type %s%s IDENTIFY password.)"
-msgstr ""
-"Bu rumuz başkasına aittir. Lütfen başka bir tane seçin.\n"
-"(Eğer bu rumuz sizinse, %s%s IDENTIFY password yazıp kendinizi tanıtın.)"
-
-#, c-format
msgid "This nickname has been forbidden: %s"
msgstr "Bu rumuz yasaklandı: %s"
@@ -7862,20 +7745,20 @@ msgstr "Bu rumuz askıya alındı."
#, c-format
msgid ""
"This nickname is registered and protected. If it is your\n"
-"nick, type %s%s IDENTIFY password. Otherwise,\n"
+"nick, type %s IDENTIFY password. Otherwise,\n"
"please choose a different nick."
msgstr ""
"Bu rumuz kayıtlı ve korumalıdır. Eğer sizin\n"
-"rumuzunuzsa, %s%s IDENTIFY şifreniz yazın. Aksi halde,\n"
+"rumuzunuzsa, %s IDENTIFY şifreniz yazın. Aksi halde,\n"
"kendinize başka bir rumuz seçin."
#, c-format
-msgid "To delete, type: %s%s %s %d"
-msgstr "Silmek için şunu yazın: %s%s %s %d"
+msgid "To delete, type: %s %s %d"
+msgstr "Silmek için şunu yazın: %s %s %d"
#, c-format
-msgid "To delete, type: %s%s %s %s %d"
-msgstr "Silmek için şunu yazın: %s%s %s %s %d"
+msgid "To delete, type: %s %s %s %d"
+msgstr "Silmek için şunu yazın: %s%s %s %d"
msgid "To protect ops against bot kicks"
msgstr "Opları bot atmalarına karşı korumak için"
@@ -7932,9 +7815,6 @@ msgstr "Büyük harf kilidini KAPALI konuma getirin!"
msgid "Turn chanstats statistics on or off"
msgstr "Chanstats istatistiklerini açma veya kapatma"
-msgid "Turn nickname security on or off"
-msgstr "Rumuz güvenliğini açma veya kapatma"
-
msgid "Turn protection on or off"
msgstr "Korumayı açma veya kapatma"
@@ -7966,24 +7846,6 @@ msgstr ""
"bilen herkes INFO komutunu kullanarak yine de onun\n"
"hakkında bilgi alabilir.)"
-#, c-format
-msgid ""
-"Turns %s's security features on or off for your\n"
-"nick. With SECURE set, you must enter your password\n"
-"before you will be recognized as the owner of the nick,\n"
-"regardless of whether your address is on the access\n"
-"list. However, if you are on the access list, %s\n"
-"will not auto-kill you regardless of the setting of the\n"
-"KILL option."
-msgstr ""
-"Nickiniz için %s'in güvenlik özelliklerini açar veya kapatır.\n"
-"SECURE ayarlandığında, adresinizin erişim listesinde\n"
-"olup olmadığına bakılmaksızın, rumuzun sahibi olarak tanınmadan\n"
-"önce şifrenizi girmelisiniz. Ancak erişim listesindeyseniz,\n"
-"KILL seçeneğinin ayarına bakılmaksızın\n"
-"%s sizi otomatik olarak\n"
-"killemez."
-
msgid "Turns chanstats channel statistics ON or OFF for this user."
msgstr "Bu kullanıcı için kanal istatistiklerini AÇIK veya KAPALI duruma getirir."
@@ -8051,52 +7913,46 @@ msgstr "Türü"
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option."
msgstr ""
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
-"%s%s HELP %s seçenek yazın."
+"%s HELP %s seçenek yazın."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
"level SET."
msgstr ""
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
-"%s%s HELP %s seçenek yazın. \n"
+"%s HELP %s seçenek yazın. \n"
"Not: Bu komuta erişim SET seviyesi tarafından\n"
"kontrol edilir."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information\n"
+"Type %s HELP %s option for more information\n"
"on a specific option. The options will be set on the given\n"
"nickname."
msgstr ""
"Belirli bir seçenek hakkında daha fazla bilgi için\n"
-"%s%s HELP %s seçenek yazın. Seçenekler belirtilen\n"
+"%s HELP %s seçenek yazın. Seçenekler belirtilen\n"
"rumuz'a göre ayarlanacaktır."
#, c-format
msgid ""
-"Type %s%s HELP %s option for more information on a\n"
+"Type %s HELP %s option for more information on a\n"
"particular option."
msgstr ""
-"Belirli bir seçenek hakkında daha fazla bilgi için\n"
-"%s%s HELP %s seçenek yazın."
+"Özel bir seçenek hakkında daha fazla bilgi için\n"
+"%s HELP %s seçenek yazın."
#, c-format
-msgid ""
-"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
-"Your privacy is respected; this e-mail won't be given to\n"
-"any third-party person."
-msgstr ""
-"E-postanızı ayarlamak için %s%s SET EMAIL e-posta yazın.\n"
-"Gizliliğinize saygı duyulur; Bu e-posta hiçbir üçüncü tarafa\n"
-"verilmeyecektir."
+msgid "Type %s SET EMAIL email in order to set your email."
+msgstr "E-Postanızı ayarlamak için %s SET EMAIL e-posta yazın."
msgid "Un-Load a module"
msgstr "Bir modülün yüklemesini kaldır"
@@ -8144,8 +8000,16 @@ msgid "Unknown command %s."
msgstr "Bilinmeyen komut %s."
#, c-format
-msgid "Unknown command %s. \"%s%s HELP\" for help."
-msgstr "Bilinmeyen komut %s. Yardım için: \"%s%s HELP\"."
+msgid "Unknown command %s. \"%s HELP\" for help."
+msgstr "Bilinmeyen komut %s. Yardım için: \"%s HELP\"."
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s?"
+msgstr "Bilinmeyen komut %s. %s mi demek istediniz?"
+
+#, c-format
+msgid "Unknown command %s. Did you mean %s? \"%s HELP\" for help."
+msgstr "Bilinmeyen komut %s. %s mi demek istediniz? Yardım için: \"%s HELP\"."
#, c-format
msgid "Unknown mode character %c ignored."
@@ -8155,6 +8019,10 @@ msgstr "Bilinmeyen mod karakteri %c yok sayıldı."
msgid "Unknown parameter: %s"
msgstr "Bilinmeyen parametre: %s"
+#, c-format
+msgid "Unknown passwords: %zu"
+msgstr "Bilinmeyen parametre: %zu"
+
msgid "Unpooled"
msgstr "Havuzdan çıkarılmış"
@@ -8229,6 +8097,10 @@ msgstr "Ayrıcalıklı kullanıcıların listesini yönetmek için kullanılır"
msgid "Used to modify the channel status of you or other users"
msgstr "Sizin veya diğer kullanıcıların kanal durumunu değiştirmek için kullanılır"
+#, c-format
+msgid "User %s isn't currently logged in to an account."
+msgstr "%s kullanıcısı şuan hesabına giriş yapmış değil."
+
msgid "User has been banned from the channel"
msgstr "Kullanıcı kanaldan banlandı"
@@ -8244,12 +8116,12 @@ msgid "Users"
msgstr "Kullanıcılar"
#, c-format
-msgid "Users (nick): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kullanıcılar (rumuz): %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Users (nick): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Kullanıcılar (rumuz): %lu girdi, %lu buckets, en uzun zincir %zu"
#, c-format
-msgid "Users (uid): %lu entries, %lu buckets, longest chain is %d"
-msgstr "Kullanıcılar (uid): %lu girdi, %lu buckets, en uzun zincir %d"
+msgid "Users (uid): %lu entries, %lu buckets, longest chain is %zu"
+msgstr "Kullanıcılar (uid): %lu girdi, %lu buckets, en uzun zincir %zu"
msgid "Users list:"
msgstr "Kullanıcı listesi:"
@@ -8258,20 +8130,28 @@ msgid "VHost"
msgstr "VHost"
#, c-format
+msgid "VHost for %s removed."
+msgstr "%s için olan vHost kaldırıldı."
+
+#, c-format
msgid "VHost for %s set to %s."
msgstr "%s için vHost, %s olarak ayarlandı."
#, c-format
-msgid "VHost for %s set to %s@%s."
-msgstr "%s için vHost, %s@%s olarak ayarlandı."
+msgid "VHost for %s has been activated."
+msgstr "%s için olan vHost etkinleştirildi."
+
+#, c-format
+msgid "VHost for %s has been rejected."
+msgstr "%s için olan vHost reddedildi."
#, c-format
msgid "VHost for group %s set to %s."
msgstr "%s grubu için vHost, %s olarak ayarlandı."
#, c-format
-msgid "VHost for group %s set to %s@%s."
-msgstr "%s grubu için vHost, %s@%s olarak ayarlandı."
+msgid "VHosts for group %s have been removed."
+msgstr "%s grubunun vHostları kaldırıldı."
msgid "VIEW host"
msgstr "VIEW host"
@@ -8289,13 +8169,6 @@ msgstr "Değer"
msgid "Value of %s:%s changed to %s"
msgstr "%s:%s'in değeri %s olarak değiştirildi"
-msgid "Vhost"
-msgstr "Vhost"
-
-#, c-format
-msgid "Vhost for %s removed."
-msgstr "%s için olan vhost kaldırıldı."
-
msgid "View and change Services Operators"
msgstr "Servis Operatörlerini görüntüleme ve değiştirme"
@@ -8349,7 +8222,7 @@ msgid ""
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
-"specify REVALIDATE as well, Services will ask the given nick\n"
+"specify REVALIDATE as well, services will ask the given nick\n"
"to re-identify. This is limited to Services Operators."
msgstr ""
"Parametre olmadan IDENTIFY komutunun etkisini tersine çevirir,\n"
@@ -8363,8 +8236,8 @@ msgstr ""
msgid ""
"Without any option, shows the current number of users online,\n"
-"and the highest number of users online since Services was\n"
-"started, and the length of time Services has been running.\n"
+"and the highest number of users online since services was\n"
+"started, and the length of time services has been running.\n"
" \n"
"With the AKILL option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -8372,6 +8245,9 @@ msgid ""
"The RESET option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
+"The PASSWORD option displays the encryption algorithms used\n"
+"for user passwords.\n"
+" \n"
"The UPLINK option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
" \n"
@@ -8389,6 +8265,9 @@ msgstr ""
"RESET seçeneği şu anda maksimum kullanıcı sayısını ağda\n"
"o anda mevcut olan kullanıcı sayısına sıfırlamaktadır.\n"
" \n"
+"PASSWORD seçeneği, kullanıcı şifreleri için kullanılan şifreleme\n"
+"algoritmalarını görüntüler.\n"
+"\n"
"UPLINK seçeneği, Anope'nin ağa uplink olarak bağlandığı\n"
"geçerli sunucu hakkındaki bilgileri görüntüler.\n"
" \n"
@@ -8428,9 +8307,6 @@ msgstr "İstemci sertifikası kullanmıyorsunuz."
msgid "You are now a super admin."
msgstr "Şuan bir süper adminsiniz."
-msgid "You are now an IRC Operator."
-msgstr "Şuan bir IRC Operatörsünüz."
-
msgid "You are now identified for your nick. Change your password now."
msgstr "Artık rumuzunuz ile tanınıyorsunuz. Şimdi şifrenizi değiştirin."
@@ -8442,7 +8318,7 @@ msgstr "Artık %s grubundasınız."
msgid "You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."
msgstr "Maksimum memo sayınızı (%d) aştınız. Mevcut memolarınızdan bazılarını silene kadar yeni memo alamayacaksınız."
-msgid "You can not NOOP Services."
+msgid "You can not NOOP services."
msgstr "NOOP Servislerini kullanamazsınız."
msgid "You can not disable the founder privilege because it would be impossible to re-enable it at a later time."
@@ -8451,9 +8327,12 @@ msgstr "Founder ayrıcalığını devre dışı bırakamazsınız çünkü daha
msgid "You can not jupe an already juped server."
msgstr "Zaten atlanmış bir sunucuyu jupe edemezsiniz."
-msgid "You can not jupe your Services' pseudoserver or your uplink server."
+msgid "You can not jupe your services' pseudoserver or your uplink server."
msgstr "Servislerinizin sahte sunucusunu veya uplink sunucunuzu çalıştıramazsınız."
+msgid "You can not queue any more messages."
+msgstr "Daha fazla mesajı sıraya koyamazsınız."
+
#, c-format
msgid "You can not reload this module directly, instead reload %s."
msgstr "Bu modülü doğrudan yeniden yükleyemezsiniz, bunun yerine %s dosyasını yeniden yükleyin."
@@ -8461,6 +8340,9 @@ msgstr "Bu modülü doğrudan yeniden yükleyemezsiniz, bunun yerine %s dosyası
msgid "You can not request a receipt when sending a memo to yourself."
msgstr "Kendinize memo gönderirken makbuz talep edemezsiniz."
+msgid "You can not send a single message while you have messages queued."
+msgstr "Sıraya alınmış mesajlarınız varken tek bir mesaj gönderemezsiniz."
+
#, c-format
msgid "You can't %s yourself!"
msgstr "Kendinizi %s yapamazsınız!"
@@ -8473,10 +8355,6 @@ msgid "You can't logout %s, they are a Services Operator."
msgstr "%s oturumunu kapatamazsınız, o bir Servis Operatörü."
#, c-format
-msgid "You cannot %s on this network."
-msgstr "Bu ağda %s yapamazsınız."
-
-#, c-format
msgid "You cannot set the %c flag."
msgstr "%c bayrağını ayarlayamazsınız."
@@ -8491,27 +8369,27 @@ msgstr "Memo sınırınızı %d'den daha yükseğe ayarlayamazsınız."
msgid "You cannot unassign bots while persist is set on the channel."
msgstr "Kanalda kalıcılık ayarı ayarlanmışken botların atamasını kaldıramazsınız."
-msgid "You cannot unset the e-mail on this network."
-msgstr "Bu ağda e-posta ayarını kaldıramazsınız."
+msgid "You cannot unset the email on this network."
+msgstr "Bu ağdaki e-postanın ayarını kaldıramazsınız."
msgid "You cannot use this command."
msgstr "Bu komutu kullanamazsınız."
#, c-format
-msgid "You currently have %d memos, of which %d are unread."
-msgstr "Şu anda %d memonuz var ve bunların %d tanesi okunmamış."
+msgid "You currently have %zu memos, of which %zu are unread."
+msgstr "Şu anda %zu memonuz var ve bunların %zu tanesi okunmamış."
#, c-format
-msgid "You currently have %d memos, of which 1 is unread."
-msgstr "Şu anda %d memonuz var ve bunların 1 tanesi okunmamış."
+msgid "You currently have %zu memos, of which 1 is unread."
+msgstr "Şu anda %zu memonuz var ve bunların 1 tanesi okunmamış."
#, c-format
-msgid "You currently have %d memos."
-msgstr "Şu anda %d memonuz var."
+msgid "You currently have %zu memos."
+msgstr "Şu anda %zu memonuz var."
#, c-format
-msgid "You currently have %d memos; all of them are unread."
-msgstr "Şu anda %d memonuz var; hepsi okunmamış."
+msgid "You currently have %zu memos; all of them are unread."
+msgstr "Şu anda %zu memonuz var; hepsi okunmamış."
msgid "You currently have 1 memo, and it has not yet been read."
msgstr "Şu anda 1 memonuz var ve henüz okunmadı."
@@ -8526,6 +8404,12 @@ msgstr "Şu anda herhangi bir memonuz yok."
msgid "You do not have access to set mode %c."
msgstr "%c modunu ayarlama erişiminiz yok."
+msgid "You do not have any messages queued and did not specify a message to send."
+msgstr "Sıraya alınmış herhangi bir mesajınız yok ve gönderilecek mesajı belirtmediniz."
+
+msgid "You do not have any queued messages."
+msgstr "Sıraya alınmış mesajınız yok."
+
#, c-format
msgid "You do not have the access to change %s's modes."
msgstr "%s'in modlarını değiştirme erişiminiz yok."
@@ -8544,10 +8428,10 @@ msgstr "1 yeni memonuz var."
#, c-format
msgid ""
"You have a new memo from %s.\n"
-"Type %s%s READ %d to read it."
+"Type %s READ %zu to read it."
msgstr ""
"%s size yeni bir memo gönderdi.\n"
-"okumak için %s%s READ %d yazın."
+"okumak için %s READ %zu yazın."
#, c-format
msgid "You have been invited to %s by %s."
@@ -8578,6 +8462,9 @@ msgstr "Saklayabileceğiniz memo sayısında herhangi bir sınırlama yoktur."
msgid "You have no memos."
msgstr "Hiç memonuz yok."
+msgid "You have no messages queued."
+msgstr "Sıraya alınmış mesajınız yok."
+
msgid "You have no new memos."
msgstr "Yeni memonuz yok."
@@ -8596,27 +8483,25 @@ msgstr "Grubunuzdaki herhangi bir rumuzu bırakabilirsiniz."
msgid "You may not (un)lock mode %c."
msgstr "%c modunun kilidini açamaz/kapatamazsınız."
-msgid "You may not change the e-mail of other Services Operators."
-msgstr "Diğer Servis Operatörlerinin e-postasını değiştiremezsiniz."
-
msgid "You may not change the email of an unconfirmed account."
msgstr "Onaylanmamış bir hesabın e-postasını değiştiremezsiniz."
+msgid "You may not change the email of other Services Operators."
+msgstr "Diğer Servis Operatörlerinin e-postasını değiştiremezsiniz."
+
msgid "You may not change the password of other Services Operators."
msgstr "Diğer Servis Operatörlerinin şifresini değiştiremezsiniz."
+#, c-format
+msgid "You may not drop %s as it is the display nick for the account."
+msgstr "Hesabın görüntülenen rumuzu olduğu için %s rumuzunu droplayamazsınız."
+
msgid "You may not drop other Services Operators' nicknames."
msgstr "Diğer Servis Operatörlerinin rumuzlarını düşüremezsiniz."
-msgid "You may not get the password of other Services Operators."
-msgstr "Diğer Servis Operatörlerinin şifresini alamazsınız."
-
msgid "You may not suspend other Services Operators' nicknames."
msgstr "Diğer Servis Operatörlerinin rumuzlarını askıya alamazsınız."
-msgid "You may view but not modify the access list of other Services Operators."
-msgstr "Diğer Servis Operatörlerinin erişim listesini görüntüleyebilir ancak değiştiremezsiniz."
-
msgid "You may view but not modify the certificate list of other Services Operators."
msgstr "Diğer Servis Operatörlerinin sertifika listesini görüntüleyebilir ancak değiştiremezsiniz."
@@ -8647,20 +8532,16 @@ msgid "You must confirm your account before you may send a memo."
msgstr "Not göndermeden önce hesabınızı onaylamanız gerekir."
#, c-format
-msgid "You must enter the channel name twice as a confirmation that you wish to drop %s."
-msgstr "%s'yi düşürmek istediğinizi onaylamak için kanal adını iki kez girmelisiniz."
-
-#, c-format
-msgid "You must have been using this nick for at least %d seconds to register."
-msgstr "Kayıt olabilmek için bu rumuzu en az %d saniyedir kullanıyor olmanız gerekmektedir."
+msgid "You must have been using this nick for at least %lu seconds to register."
+msgstr "Kayıt olmak için bu rumuzu en az %lu saniyedir kullanıyor olmalısınız."
#, c-format
msgid "You must have the %s(ME) privilege on the channel to use this command."
msgstr "Bu komutu kullanmak için kanalda %s(ME) ayrıcalığına sahip olmanız gerekir."
msgid ""
-"You must now supply an e-mail for your nick.\n"
-"This e-mail will allow you to retrieve your password in\n"
+"You must now supply an email for your nick.\n"
+"This email will allow you to retrieve your password in\n"
"case you forget it."
msgstr ""
"Şimdi rumuzunuz için bir e-posta girmelisiniz.\n"
@@ -8709,8 +8590,12 @@ msgstr "IRCd'niz SVSNICK'i desteklemiyor."
msgid "Your IRCd does not support SVSPART."
msgstr "IRCd'niz SVSPART'ı desteklemiyor."
-msgid "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
-msgstr "IRCd'niz vIdent'i desteklemiyor, eğer bu yanlışsa lütfen bunu olası bir hata olarak bildirin"
+msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
+msgstr "IRCd'niz vIdent'i desteklemiyor, eğer bu yanlışsa lütfen bunu olası bir hata olarak bildirin."
+
+#, c-format
+msgid "Your SSL certificate fingerprint %s has been automatically added to your certificate list."
+msgstr "SSL sertifika parmak iziniz %s otomatik olarak sertifika listenize eklendi."
#, c-format
msgid "Your account %s has been successfully created."
@@ -8766,6 +8651,12 @@ msgstr "Memo sınırınız 0; yeni memo almayacaksınız."
msgid "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
msgstr "Memo sınırınız 0; yeni memo almayacaksınız. Bu limiti değiştiremezsiniz."
+msgid "Your message has been queued."
+msgstr "Mesajınız sıraya alındı."
+
+msgid "Your message queue has been cleared."
+msgstr "Mesaj kuyruğunuz temizlendi."
+
msgid "Your nick has been logged out."
msgstr "Rumuzunuzun çıkışı yapıldı."
@@ -8790,27 +8681,23 @@ msgid "Your passcode has been re-sent to %s."
msgstr "Şifreniz %s adresine yeniden gönderildi."
#, c-format
-msgid "Your password is %s - remember this for later use."
-msgstr "Şifreniz %s - bunu daha sonra kullanacaksınız, unutmayın."
+msgid "Your password is too long. It must be shorter than %u characters."
+msgstr "Şifreniz çok uzun. %u karakteri geçmemelidir."
#, c-format
-msgid "Your password is too long. It must not exceed %u characters."
-msgstr "Şifreniz çok uzun. %u karakteri geçmemelidir."
+msgid "Your password is too short. It must be longer than %u characters."
+msgstr "Şifreniz çok kısa. %u karakterden uzun olmalıdır."
msgid "Your password reset request has expired."
msgstr "Şifre sıfırlama isteğinizin süresi doldu."
-msgid "Your vHost has been requested."
+msgid "Your vhost has been requested."
msgstr "VHost'unuz talep edildi."
#, c-format
msgid "Your vhost of %s is now activated."
msgstr "%s vhostunuz artık etkinleştirildi."
-#, c-format
-msgid "Your vhost of %s@%s is now activated."
-msgstr "%s@%s vhostunuz artık etkinleştirildi."
-
msgid "Your vhost was removed and the normal cloaking restored."
msgstr "Vhostunuz kaldırıldı ve normal gizleme geri getirildi."
@@ -8874,6 +8761,9 @@ msgstr "[kanal] {num | liste | LAST | NEW | ALL}"
msgid "[key|#X-Y]"
msgstr "[anahtar|#X-Y]"
+msgid "[message]"
+msgstr "[mesaj]"
+
msgid "[nick | channel]"
msgstr "[rumuz | kanal]"
@@ -8904,20 +8794,20 @@ msgstr "[Askıya alındı]"
msgid "[Unconfirmed]"
msgstr "[Onaylanmadı]"
-msgid "[auto memo] Your requested vHost has been approved."
+#, c-format
+msgid "[auto memo] VHost %s has been requested by %s."
+msgstr "[oto-memo] %s vHostu, %s tarafından talep edildi."
+
+msgid "[auto memo] Your requested vhost has been approved."
msgstr "[oto-memo] Talep ettiğiniz vHost kabul edildi."
-msgid "[auto memo] Your requested vHost has been rejected."
+msgid "[auto memo] Your requested vhost has been rejected."
msgstr "[oto-memo] Talep ettiğiniz vHost reddedildi."
#, c-format
-msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
+msgid "[auto memo] Your requested vhost has been rejected. Reason: %s"
msgstr "[oto-memo] Talep ettiğiniz vHost reddedildi. Sebep: %s"
-#, c-format
-msgid "[auto memo] vHost %s has been requested by %s."
-msgstr "[auto memo] vHost %s has been requested by %s."
-
msgid "[{pattern | channel} [INVISIBLE]]"
msgstr "[{şablon | kanal} [INVISIBLE]]"
@@ -8993,21 +8883,9 @@ msgstr "saniye"
msgid "seconds"
msgstr "saniye"
-#, c-format
-msgid "vHost for %s has been activated."
-msgstr "%s için olan vHost etkinleştirildi."
-
-#, c-format
-msgid "vHost for %s has been rejected."
-msgstr "%s için olan vHost reddedildi."
-
msgid "vhost"
msgstr "vhost"
-#, c-format
-msgid "vhosts for group %s have been removed."
-msgstr "%s grubunun vhostu kaldırıldı."
-
msgid "year"
msgstr "yıl"
diff --git a/language/update.sh b/language/update.sh
index 27a6a1ef8..20a0abc5b 100755
--- a/language/update.sh
+++ b/language/update.sh
@@ -21,7 +21,6 @@ find ../ \
\) \
-exec \
xgettext \
- --escape \
--language=C++ \
--sort-output \
--default-domain=Anope \
@@ -30,6 +29,7 @@ find ../ \
--from-code=utf-8 \
--keyword \
--keyword=_ \
+ --keyword=N_:1,2 \
{} +
for f in *.po
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index 460c7b18a..777f080f0 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -1,7 +1,7 @@
# If using Windows, add the MODULE_COMPILE define
if(WIN32)
add_definitions(-DMODULE_COMPILE)
-endif(WIN32)
+endif()
# enable extra modules if conan is used
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../conanbuildinfo.cmake")
@@ -19,18 +19,13 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../conanbuildinfo.cmake")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/extra/${NAME}.cpp" DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}")
endfunction()
- enable_extra("m_mysql" "LIBMYSQLCLIENT")
- enable_extra("m_regex_pcre2" "PCRE2")
- enable_extra("m_sqlite" "SQLITE3")
- enable_extra("m_ssl_openssl" "OPENSSL")
+ enable_extra("enc_argon2" "ARGON2")
+ enable_extra("mysql" "LIBMYSQLCLIENT")
+ enable_extra("regex_pcre2" "PCRE2")
+ enable_extra("sqlite" "SQLITE3")
+ enable_extra("ssl_openssl" "OPENSSL")
# this uses Wldap so should always be available
- copy_extra("m_ldap")
- # these don't actually have extra dependencies, but require a module which does
- copy_extra("m_sql_authentication")
- copy_extra("m_sql_log")
- copy_extra("m_sql_oper")
- copy_extra("m_ldap_authentication")
- copy_extra("m_ldap_oper")
+ copy_extra("ldap")
# Package extra dlls
file(GLOB EXTRA_DLLS "${Anope_SOURCE_DIR}/extradll/bin/*.dll" "${Anope_SOURCE_DIR}/extradll/lib/*.dll")
@@ -40,164 +35,145 @@ endif()
macro(build_modules SRC)
if(NOT ${SRC} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR} AND EXISTS "${SRC}/CMakeLists.txt")
add_subdirectory("${SRC}")
- else(NOT ${SRC} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR} AND EXISTS "${SRC}/CMakeLists.txt")
+ else()
file(GLOB MODULES_SRCS "${SRC}/*")
foreach(MODULE_SRC ${MODULES_SRCS})
if(IS_DIRECTORY "${MODULE_SRC}")
build_modules("${MODULE_SRC}")
- else(IS_DIRECTORY "${MODULE_SRC}")
+ else()
string(REGEX MATCH "\\.c$" ANOPE18MODULE ${MODULE_SRC})
if(ANOPE18MODULE)
message(FATAL_ERROR "Anope 1 modules are not compatible with Anope 2!\nOffending module: ${MODULE_SRC}")
- endif(ANOPE18MODULE)
+ endif()
string(REGEX MATCH "\\.cpp$" CPP ${MODULE_SRC})
if(CPP)
set_source_files_properties(${MODULE_SRC} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
file(RELATIVE_PATH FNAME ${SRC} ${MODULE_SRC})
- # Convert the real source file extension to have a .so extension
- string(REGEX REPLACE "\\.cpp$" ".so" SO ${FNAME})
- # Temporary variable for the current source's include directories
- set(TEMP_INCLUDES)
- # Calculate the header file dependencies for the given source file
- calculate_depends(${MODULE_SRC} TEMP_INCLUDES)
- # If there were some extra include directories, add them to the list
- if(TEMP_INCLUDES)
- append_to_list(EXTRA_INCLUDES ${TEMP_INCLUDES})
- endif(TEMP_INCLUDES)
-
+ # Convert the real source file extension to have a library extension
+ string(REGEX REPLACE "\\.cpp$" "${CMAKE_SHARED_LIBRARY_SUFFIX}" SO ${FNAME})
# Reset linker flags
set(TEMP_LDFLAGS)
# Reset extra dependencies
set(TEMP_DEPENDENCIES)
# Calculate the library dependencies for the given source file
calculate_libraries(${MODULE_SRC} TEMP_LDFLAGS TEMP_DEPENDENCIES)
- # Reset has_function
- set(HAS_FUNCTION)
- # Check the function dependencies for the given source file
- check_functions(${MODULE_SRC} HAS_FUNCTION)
- # Only continue if this module has all of the required functions
- if(HAS_FUNCTION)
- # For Visual Studio only, include win32_memory static library, required to override Visual Studio's overrides of the new/delete operators
- if(MSVC)
- set(WIN32_MEMORY win32_memory)
- else(MSVC)
- set(WIN32_MEMORY)
- endif(MSVC)
- # Generate the module and set its linker flags, also set it to depend on the main Anope executable to be built beforehand
- add_library(${SO} MODULE ${MODULE_SRC})
- # Windows requires this because it's weird
- if(WIN32)
- set(WIN32_NO_LIBS "/nodefaultlib:\"libcmt.lib\" /OPT:NOREF")
- else(WIN32)
- set(WIN32_NO_LIBS)
- endif(WIN32)
- set_target_properties(${SO} PROPERTIES LINKER_LANGUAGE CXX PREFIX "" SUFFIX "" LINK_FLAGS "${TEMP_LDFLAGS} ${WIN32_NO_LIBS}" INSTALL_RPATH_USE_LINK_PATH ON BUILD_WITH_INSTALL_RPATH ON)
- add_dependencies(${SO} ${PROGRAM_NAME})
- if(GETTEXT_FOUND)
- add_dependencies(${SO} module_language)
- endif(GETTEXT_FOUND)
- target_link_libraries(${SO} ${TEMP_DEPENDENCIES})
- # For Windows only, have the module link to the export library of Anope as well as wsock32 and Ws2_32 libraries (most of the modules probably don't need this, but this is to be on the safe side), also set its version
- if(WIN32)
- target_link_libraries(${SO} ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
- set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
- else(WIN32)
- if(APPLE)
- target_link_libraries(${SO} ${PROGRAM_NAME})
- endif(APPLE)
- endif(WIN32)
- # Set the module to be installed to the module directory under the data directory
- install(TARGETS ${SO} DESTINATION ${LIB_DIR}/modules)
- endif(HAS_FUNCTION)
- endif(CPP)
- endif(IS_DIRECTORY "${MODULE_SRC}")
- endforeach(MODULE_SRC ${MODULES_SRCS})
- endif(NOT ${SRC} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR} AND EXISTS "${SRC}/CMakeLists.txt")
-endmacro(build_modules)
+ # For Visual Studio only, include win32_memory static library, required to override Visual Studio's overrides of the new/delete operators
+ if(MSVC)
+ set(WIN32_MEMORY win32_memory)
+ else()
+ set(WIN32_MEMORY)
+ endif()
+ # Generate the module and set its linker flags, also set it to depend on the main Anope executable to be built beforehand
+ add_library(${SO} MODULE ${MODULE_SRC})
+ # Windows requires this because it's weird
+ if(WIN32)
+ set(WIN32_NO_LIBS "/nodefaultlib:\"libcmt.lib\" /OPT:NOREF")
+ else()
+ set(WIN32_NO_LIBS)
+ endif()
+ set_target_properties(${SO} PROPERTIES
+ BUILD_WITH_INSTALL_RPATH ON
+ FOLDER "Modules"
+ INSTALL_RPATH_USE_LINK_PATH ON
+ LINKER_LANGUAGE CXX
+ LINK_FLAGS "${TEMP_LDFLAGS} ${WIN32_NO_LIBS}"
+ PREFIX ""
+ SUFFIX ""
+ )
+ add_dependencies(${SO} ${PROGRAM_NAME})
+ if(HAVE_LOCALIZATION)
+ add_dependencies(${SO} module_language)
+ endif()
+ target_link_libraries(${SO} ${TEMP_DEPENDENCIES})
+ # For Windows only, have the module link to the export library of Anope as well as wsock32 and Ws2_32 libraries (most of the modules probably don't need this, but this is to be on the safe side), also set its version
+ if(WIN32)
+ target_link_libraries(${SO} ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
+ set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
+ elseif(APPLE)
+ target_link_libraries(${SO} ${PROGRAM_NAME})
+ endif()
+ # Set the module to be installed to the module directory under the data directory
+ install(TARGETS ${SO}
+ DESTINATION ${MODULE_DIR}
+ LIBRARY)
+ endif()
+ endif()
+ endforeach()
+ endif()
+endmacro()
macro(build_subdir)
file(GLOB_RECURSE MODULES_SUBDIR_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
- sort_list(MODULES_SUBDIR_SRCS)
+ list(SORT MODULES_SUBDIR_SRCS)
GET_FILENAME_COMPONENT(FOLDER_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
- set(SO "${FOLDER_NAME}.so")
+ set(SO "${FOLDER_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}")
# Set all the files to use C++ as well as set their compile flags (use the module-specific compile flags, though)
set_source_files_properties(${MODULES_SUBDIR_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
- set(HAS_FUNCTION TRUE)
-
# Iterate through the source files in the subdirectory
foreach(SRC ${MODULES_SUBDIR_SRCS})
- if(HAS_FUNCTION)
- # Temporary variable for the current source's include directories
- set(TEMP_INCLUDES)
- # Calculate the header file dependencies for the given source file
- calculate_depends(${SRC} TEMP_INCLUDES)
- # If there were some extra include directories, add them to the list
- if(TEMP_INCLUDES)
- include_directories(${TEMP_INCLUDES})
- endif(TEMP_INCLUDES)
-
- # Reset linker flags
- set(TEMP_LDFLAGS)
- # Reset extra dependencies
- set(TEMP_DEPENDENCIES)
- # Calculate the library dependencies for the given source file
- calculate_libraries(${SRC} SKIP_LIBRARIES MODULE TEMP_LDFLAGS TEMP_DEPENDENCIES)
- # Check the function dependencies for the given source file
- check_functions(${SRC} HAS_FUNCTION)
-
- # Append this source file's linker flags to the subdirectoy's linker flags, if there are any to append
- if(TEMP_DEPENDENCIES)
- append_to_list(SUBDIR_EXTRA_DEPENDS ${TEMP_DEPENDENCIES})
- endif(TEMP_DEPENDENCIES)
- endif(HAS_FUNCTION)
- endforeach(SRC ${MODULES_SUBDIR_SRCS})
-
- # Continue if library and function requirements are met
- if(HAS_FUNCTION)
- # Remove duplicates from the linker flags
- if(SUBDIR_LDFLAGS)
- remove_list_duplicates(SUBDIR_LDFLAGS)
- endif(SUBDIR_LDFLAGS)
-
- # Remove duplicates from the extra dependencies
- if(SUBDIR_EXTRA_DEPENDS)
- remove_list_duplicates(SUBDIR_EXTRA_DEPENDS)
- endif(SUBDIR_EXTRA_DEPENDS)
-
- # For Visual Studio only, include win32_memory static library, required to override Visual Studio's overrides of the new/delete operators
- if(MSVC)
- set(WIN32_MEMORY win32_memory)
- else(MSVC)
- set(WIN32_MEMORY)
- endif(MSVC)
-
- # Generate the module and set it's linker flags, also set it to depend on the main Anope executable to be built beforehand
- add_library(${SO} MODULE ${MODULES_SUBDIR_SRCS})
- set_target_properties(${SO} PROPERTIES LINKER_LANGUAGE CXX PREFIX "" SUFFIX "" LINK_FLAGS "${SUBDIR_LDFLAGS}" INSTALL_RPATH_USE_LINK_PATH ON BUILD_WITH_INSTALL_RPATH ON)
- add_dependencies(${SO} ${PROGRAM_NAME})
- if(GETTEXT_FOUND)
- add_dependencies(${SO} module_language)
- endif(GETTEXT_FOUND)
- target_link_libraries(${SO} ${SUBDIR_EXTRA_DEPENDS})
- # For Windows only, have the module link to the export library of Anope as well as wsock32 and Ws2_32 libraries (most of the modules probably don't need this, but this is to be on the safe side), also set it's version
- if(WIN32)
- target_link_libraries(${SO} ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
- set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
- else(WIN32)
- if(APPLE)
- target_link_libraries(${SO} ${PROGRAM_NAME})
- endif(APPLE)
- endif(WIN32)
-
- # Set the module to be installed to the module directory under the data directory
- install(TARGETS ${SO} DESTINATION ${LIB_DIR}/modules)
-
- endif(HAS_FUNCTION)
-endmacro(build_subdir)
+ # Reset linker flags
+ set(TEMP_LDFLAGS)
+ # Reset extra dependencies
+ set(TEMP_DEPENDENCIES)
+ # Calculate the library dependencies for the given source file
+ calculate_libraries(${SRC} SKIP_LIBRARIES MODULE TEMP_LDFLAGS TEMP_DEPENDENCIES)
+
+ # Append this source file's linker flags to the subdirectoy's linker flags, if there are any to append
+ if(TEMP_DEPENDENCIES)
+ list(APPEND SUBDIR_EXTRA_DEPENDS ${TEMP_DEPENDENCIES})
+ endif()
+ endforeach()
+
+ # Remove duplicates from the linker flags
+ if(SUBDIR_LDFLAGS)
+ list(REMOVE_DUPLICATES SUBDIR_LDFLAGS)
+ endif()
+
+ # Remove duplicates from the extra dependencies
+ if(SUBDIR_EXTRA_DEPENDS)
+ list(REMOVE_DUPLICATES SUBDIR_EXTRA_DEPENDS)
+ endif()
+
+ # For Visual Studio only, include win32_memory static library, required to override Visual Studio's overrides of the new/delete operators
+ if(MSVC)
+ set(WIN32_MEMORY win32_memory)
+ else()
+ set(WIN32_MEMORY)
+ endif()
+
+ # Generate the module and set it's linker flags, also set it to depend on the main Anope executable to be built beforehand
+ add_library(${SO} MODULE ${MODULES_SUBDIR_SRCS})
+ set_target_properties(${SO} PROPERTIES
+ BUILD_WITH_INSTALL_RPATH ON
+ FOLDER "Modules"
+ INSTALL_RPATH_USE_LINK_PATH ON
+ LINKER_LANGUAGE CXX
+ LINK_FLAGS "${SUBDIR_LDFLAGS}"
+ PREFIX ""
+ SUFFIX ""
+ )
+ add_dependencies(${SO} ${PROGRAM_NAME})
+ if(HAVE_LOCALIZATION)
+ add_dependencies(${SO} module_language)
+ endif()
+ target_link_libraries(${SO} ${SUBDIR_EXTRA_DEPENDS})
+ # For Windows only, have the module link to the export library of Anope as well as wsock32 and Ws2_32 libraries (most of the modules probably don't need this, but this is to be on the safe side), also set it's version
+ if(WIN32)
+ target_link_libraries(${SO} ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
+ set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
+ elseif(APPLE)
+ target_link_libraries(${SO} ${PROGRAM_NAME})
+ endif()
+
+ # Set the module to be installed to the module directory under the data directory
+ install(TARGETS ${SO}
+ DESTINATION ${MODULE_DIR}
+ LIBRARY)
+endmacro()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
build_modules(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/modules/pseudoclients/botserv.cpp b/modules/botserv/botserv.cpp
index ba70978c9..0646668be 100644
--- a/modules/pseudoclients/botserv.cpp
+++ b/modules/botserv/botserv.cpp
@@ -11,35 +11,36 @@
#include "module.h"
-class BotServCore : public Module
+class BotServCore final
+ : public Module
{
Reference<BotInfo> BotServ;
ExtensibleRef<bool> persist, inhabit;
- public:
+public:
BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
persist("PERSIST"), inhabit("inhabit")
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
const Anope::string &bsnick = conf->GetModule(this)->Get<const Anope::string>("client");
BotServ = BotInfo::Find(bsnick, true);
}
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override
+ void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) override
{
/* Do not allow removing bot modes on our service bots */
if (chan->ci && chan->ci->bi == user)
{
const Anope::string &botmodes = Config->GetModule(this)->Get<const Anope::string>("botmodes");
- for (unsigned i = 0; i < botmodes.length(); ++i)
- chan->SetMode(chan->ci->bi, ModeManager::FindChannelModeByChar(botmodes[i]), chan->ci->bi->GetUID());
+ for (auto botmode : botmodes)
+ chan->SetMode(chan->ci->bi, ModeManager::FindChannelModeByChar(botmode), chan->ci->bi->GetUID());
}
}
- void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) anope_override
+ void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) override
{
if (ci->c && ci->c->users.size() >= Config->GetModule(this)->Get<unsigned>("minusers"))
{
@@ -48,7 +49,7 @@ class BotServCore : public Module
}
}
- void OnJoinChannel(User *user, Channel *c) anope_override
+ void OnJoinChannel(User *user, Channel *c) override
{
if (!Config || !IRCD)
return;
@@ -56,31 +57,34 @@ class BotServCore : public Module
BotInfo *bi = user->server == Me ? dynamic_cast<BotInfo *>(user) : NULL;
if (bi && Config->GetModule(this)->Get<bool>("smartjoin"))
{
- std::vector<Anope::string> bans = c->GetModeList("BAN");
-
- /* We check for bans */
- for (unsigned int i = 0; i < bans.size(); ++i)
+ if (IRCD->CanClearBans)
+ {
+ // We can ask the IRCd to clear bans.
+ IRCD->SendClearBans(bi, c, bi);
+ }
+ else
{
- Entry ban("BAN", bans[i]);
- if (ban.Matches(user))
- c->RemoveMode(NULL, "BAN", ban.GetMask());
+ // We have to check for bans.
+ for (const auto &entry : c->GetModeList("BAN"))
+ {
+ Entry ban("BAN", entry);
+ if (ban.Matches(user))
+ c->RemoveMode(NULL, "BAN", ban.GetMask());
+ }
}
Anope::string Limit;
unsigned limit = 0;
- try
- {
- if (c->GetParam("LIMIT", Limit))
- limit = convertTo<unsigned>(Limit);
- }
- catch (const ConvertException &) { }
+ if (c->GetParam("LIMIT", Limit))
+ limit = Anope::Convert<unsigned>(Limit, limit);
/* Should we be invited? */
if (c->HasMode("INVITE") || (limit && c->users.size() >= limit))
{
ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
char symbol = cm ? anope_dynamic_static_cast<ChannelModeStatus *>(cm)->symbol : 0;
- IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, "%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
+ const auto message = Anope::printf("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
+ IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, message);
}
ModeManager::ProcessModes();
@@ -103,7 +107,7 @@ class BotServCore : public Module
}
}
- void OnLeaveChannel(User *u, Channel *c) anope_override
+ void OnLeaveChannel(User *u, Channel *c) override
{
/* Channel is persistent, it shouldn't be deleted and the service bot should stay */
if (c->ci && persist && persist->HasExt(c->ci))
@@ -124,7 +128,7 @@ class BotServCore : public Module
c->ci->bi->Part(c->ci->c);
}
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty())
return EVENT_CONTINUE;
@@ -149,17 +153,17 @@ class BotServCore : public Module
"It has been created for users that can't host or\n"
"configure a bot, or for use on networks that don't\n"
"allow user bots. Available commands are listed\n"
- "below; to use them, type \002%s%s \037command\037\002. For\n"
+ "below; to use them, type \002%s \037command\037\002. For\n"
"more information on a specific command, type\n"
- "\002%s%s %s \037command\037\002.\n"),
- BotServ->nick.c_str(), Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(),
- Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(), source.command.c_str());
+ "\002%s %s \037command\037\002.\n"),
+ BotServ->nick.c_str(), BotServ->GetQueryCommand().c_str(),
+ BotServ->GetQueryCommand().c_str(), source.command.c_str());
}
return EVENT_CONTINUE;
}
- void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *BotServ)
return;
@@ -174,7 +178,7 @@ class BotServCore : public Module
"one of the following characters: %s"), fantasycharacters.c_str());
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &param) 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))
{
@@ -188,7 +192,7 @@ class BotServCore : public Module
return EVENT_CONTINUE;
}
- void OnCreateChan(ChannelInfo *ci) anope_override
+ void OnCreateChan(ChannelInfo *ci) override
{
/* Set default bot flags */
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("defaults", "greet fantasy"));
@@ -196,7 +200,7 @@ class BotServCore : public Module
ci->Extend<bool>("BS_" + token.upper());
}
- void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) anope_override
+ void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) override
{
BotInfo *bi = BotInfo::Find(target->GetUID());
if (bi)
@@ -204,7 +208,7 @@ class BotServCore : public Module
bi->Join(channel, &status);
}
- void OnCreateBot(BotInfo *bi) anope_override
+ void OnCreateBot(BotInfo *bi) override
{
if (bi->botmodes.empty())
bi->botmodes = Config->GetModule(this)->Get<const Anope::string>("botumodes");
diff --git a/modules/commands/bs_assign.cpp b/modules/botserv/bs_assign.cpp
index 1c9696f18..f80e9c17e 100644
--- a/modules/commands/bs_assign.cpp
+++ b/modules/botserv/bs_assign.cpp
@@ -11,23 +11,24 @@
#include "module.h"
-class CommandBSAssign : public Command
+class CommandBSAssign final
+ : public Command
{
- public:
+public:
CommandBSAssign(Module *creator) : Command(creator, "botserv/assign", 2, 2)
{
this->SetDesc(_("Assigns a bot to a channel"));
this->SetSyntax(_("\037channel\037 \037nick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
const Anope::string &nick = params[1];
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot assignment is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -71,7 +72,7 @@ class CommandBSAssign : public Command
source.Reply(_("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), ci->name.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -82,20 +83,21 @@ class CommandBSAssign : public Command
}
};
-class CommandBSUnassign : public Command
+class CommandBSUnassign final
+ : public Command
{
- public:
+public:
CommandBSUnassign(Module *creator) : Command(creator, "botserv/unassign", 1, 1)
{
this->SetDesc(_("Unassigns a bot from a channel"));
this->SetSyntax(_("\037channel\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot assignment is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -132,7 +134,7 @@ class CommandBSUnassign : public Command
source.Reply(_("There is no bot assigned to %s anymore."), ci->name.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -145,23 +147,24 @@ class CommandBSUnassign : public Command
}
};
-class CommandBSSetNoBot : public Command
+class CommandBSSetNoBot final
+ : public Command
{
- public:
+public:
CommandBSSetNoBot(Module *creator, const Anope::string &sname = "botserv/set/nobot") : Command(creator, sname, 2, 2)
{
this->SetDesc(_("Prevent a bot from being assigned to a channel"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
const Anope::string &value = params[1];
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot modification is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -191,7 +194,7 @@ class CommandBSSetNoBot : public Command
this->OnSyntaxError(source, source.command);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -202,7 +205,8 @@ class CommandBSSetNoBot : public Command
}
};
-class BSAssign : public Module
+class BSAssign final
+ : public Module
{
ExtensibleItem<bool> nobot;
@@ -210,14 +214,14 @@ class BSAssign : public Module
CommandBSUnassign commandbsunassign;
CommandBSSetNoBot commandbssetnobot;
- public:
+public:
BSAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
nobot(this, "BS_NOBOT"),
commandbsassign(this), commandbsunassign(this), commandbssetnobot(this)
{
}
- void OnInvite(User *source, Channel *c, User *targ) anope_override
+ void OnInvite(User *source, Channel *c, User *targ) override
{
BotInfo *bi;
if (Anope::ReadOnly || !c->ci || targ->server != Me || !(bi = dynamic_cast<BotInfo *>(targ)))
@@ -246,7 +250,7 @@ class BSAssign : public Module
targ->SendMessage(bi, _("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), c->name.c_str());
}
- void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) override
{
if (nobot.HasExt(ci))
info.AddOption(_("No bot"));
diff --git a/modules/bs_autoassign.cpp b/modules/botserv/bs_autoassign.cpp
index e6484d478..e988540fe 100644
--- a/modules/bs_autoassign.cpp
+++ b/modules/botserv/bs_autoassign.cpp
@@ -9,14 +9,15 @@
#include "module.h"
-class BSAutoAssign : public Module
+class BSAutoAssign final
+ : public Module
{
- public:
+public:
BSAutoAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
{
}
- void OnChanRegistered(ChannelInfo *ci) anope_override
+ void OnChanRegistered(ChannelInfo *ci) override
{
const Anope::string &bot = Config->GetModule(this)->Get<const Anope::string>("bot");
if (bot.empty())
diff --git a/modules/commands/bs_badwords.cpp b/modules/botserv/bs_badwords.cpp
index 753326e91..5301fd042 100644
--- a/modules/commands/bs_badwords.cpp
+++ b/modules/botserv/bs_badwords.cpp
@@ -12,22 +12,25 @@
#include "module.h"
#include "modules/bs_badwords.h"
-struct BadWordImpl : BadWord, Serializable
+struct BadWordImpl final
+ : BadWord
+ , Serializable
{
BadWordImpl() : Serializable("BadWord") { }
- ~BadWordImpl();
+ ~BadWordImpl() override;
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["ci"] << this->chan;
- data["word"] << this->word;
- data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
+ data.Store("ci", this->chan);
+ data.Store("word", this->word);
+ data.Store("type", this->type);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
};
-struct BadWordsImpl : BadWords
+struct BadWordsImpl final
+ : BadWords
{
Serialize::Reference<ChannelInfo> ci;
typedef std::vector<BadWordImpl *> list;
@@ -35,11 +38,11 @@ struct BadWordsImpl : BadWords
BadWordsImpl(Extensible *obj) : ci(anope_dynamic_static_cast<ChannelInfo *>(obj)), badwords("BadWord") { }
- ~BadWordsImpl();
+ ~BadWordsImpl() override;
- BadWord* AddBadWord(const Anope::string &word, BadWordType type) anope_override
+ BadWord *AddBadWord(const Anope::string &word, BadWordType type) override
{
- BadWordImpl *bw = new BadWordImpl();
+ auto *bw = new BadWordImpl();
bw->chan = ci->name;
bw->word = word;
bw->type = type;
@@ -51,7 +54,7 @@ struct BadWordsImpl : BadWords
return bw;
}
- BadWord* GetBadWord(unsigned index) const anope_override
+ BadWord *GetBadWord(unsigned index) const override
{
if (this->badwords->empty() || index >= this->badwords->size())
return NULL;
@@ -61,12 +64,12 @@ struct BadWordsImpl : BadWords
return bw;
}
- unsigned GetBadWordCount() const anope_override
+ unsigned GetBadWordCount() const override
{
return this->badwords->size();
}
- void EraseBadWord(unsigned index) anope_override
+ void EraseBadWord(unsigned index) override
{
if (this->badwords->empty() || index >= this->badwords->size())
return;
@@ -76,13 +79,13 @@ struct BadWordsImpl : BadWords
delete this->badwords->at(index);
}
- void ClearBadWords() anope_override
+ void ClearBadWords() override
{
while (!this->badwords->empty())
delete this->badwords->back();
}
- void Check() anope_override
+ void Check() override
{
if (this->badwords->empty())
ci->Shrink<BadWords>("badwords");
@@ -114,7 +117,7 @@ BadWordImpl::~BadWordImpl()
}
}
-Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sci, sword;
@@ -144,23 +147,24 @@ Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
return bw;
}
-class BadwordsDelCallback : public NumberList
+class BadwordsDelCallback final
+ : public NumberList
{
CommandSource &source;
ChannelInfo *ci;
BadWords *bw;
Command *c;
- unsigned deleted;
- bool override;
- public:
- BadwordsDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), deleted(0), override(false)
+ unsigned deleted = 0;
+ bool override = false;
+public:
+ BadwordsDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c)
{
if (!source.AccessFor(ci).HasPriv("BADWORDS") && source.HasPriv("botserv/administration"))
this->override = true;
bw = ci->Require<BadWords>("badwords");
}
- ~BadwordsDelCallback()
+ ~BadwordsDelCallback() override
{
if (!deleted)
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
@@ -170,7 +174,7 @@ class BadwordsDelCallback : public NumberList
source.Reply(_("Deleted %d entries from %s bad words list."), deleted, ci->name.c_str());
}
- void HandleNumber(unsigned Number) anope_override
+ void HandleNumber(unsigned Number) override
{
if (!bw || !Number || Number > bw->GetBadWordCount())
return;
@@ -181,9 +185,10 @@ class BadwordsDelCallback : public NumberList
}
};
-class CommandBSBadwords : public Command
+class CommandBSBadwords final
+ : public Command
{
- private:
+private:
void DoList(CommandSource &source, ChannelInfo *ci, const Anope::string &word)
{
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
@@ -200,23 +205,24 @@ class CommandBSBadwords : public Command
}
else if (!word.empty() && word.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class BadwordsListCallback : public NumberList
+ class BadwordsListCallback final
+ : public NumberList
{
ListFormatter &list;
BadWords *bw;
- public:
+ public:
BadwordsListCallback(ListFormatter &_list, BadWords *_bw, const Anope::string &numlist) : NumberList(numlist, false), list(_list), bw(_bw)
{
}
- void HandleNumber(unsigned Number) anope_override
+ void HandleNumber(unsigned Number) override
{
if (!Number || Number > bw->GetBadWordCount())
return;
const BadWord *b = bw->GetBadWord(Number - 1);
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(Number);
+ 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)" : ""));
this->list.AddEntry(entry);
@@ -235,7 +241,7 @@ class CommandBSBadwords : public Command
continue;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ 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)" : ""));
list.AddEntry(entry);
@@ -251,8 +257,8 @@ class CommandBSBadwords : public Command
source.Reply(_("Bad words list for %s:"), ci->name.c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of bad words list."));
}
@@ -364,7 +370,7 @@ class CommandBSBadwords : public Command
source.Reply(_("Bad words list is now empty."));
}
- public:
+public:
CommandBSBadwords(Module *creator) : Command(creator, "botserv/badwords", 2, 3)
{
this->SetDesc(_("Maintains the bad words list"));
@@ -374,7 +380,7 @@ class CommandBSBadwords : public Command
this->SetSyntax(_("\037channel\037 CLEAR"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[1];
const Anope::string &word = params.size() > 2 ? params[2] : "";
@@ -401,7 +407,7 @@ class CommandBSBadwords : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bad words list modification is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -417,14 +423,14 @@ class CommandBSBadwords : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Maintains the \002bad words list\002 for a channel. The bad\n"
"words list determines which words are to be kicked\n"
"when the bad words kicker is enabled. For more information,\n"
- "type \002%s%s HELP KICK %s\002.\n"
+ "type \002%s HELP KICK %s\002.\n"
" \n"
"The \002ADD\002 command adds the given word to the\n"
"bad words list. If SINGLE is specified, a kick will be\n"
@@ -434,7 +440,7 @@ class CommandBSBadwords : public Command
"will be done if a user says a word that ends with\n"
"\037word\037. If you don't specify anything, a kick will\n"
"be issued every time \037word\037 is said by a user.\n"
- " \n"), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
+ " \n"), source.service->GetQueryCommand().c_str(), source.command.c_str());
source.Reply(_("The \002DEL\002 command removes the given word from the\n"
"bad words list. If a list of entry numbers is given, those\n"
"entries are deleted. (See the example for LIST below.)\n"
@@ -453,13 +459,14 @@ class CommandBSBadwords : public Command
}
};
-class BSBadwords : public Module
+class BSBadwords final
+ : public Module
{
CommandBSBadwords commandbsbadwords;
ExtensibleItem<BadWordsImpl> badwords;
Serialize::Type badword_type;
- public:
+public:
BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandbsbadwords(this), badwords(this, "badwords"), badword_type("BadWord", BadWordImpl::Unserialize)
{
diff --git a/modules/commands/bs_bot.cpp b/modules/botserv/bs_bot.cpp
index fcef1feb8..fcb1e92f4 100644
--- a/modules/commands/bs_bot.cpp
+++ b/modules/botserv/bs_bot.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandBSBot : public Command
+class CommandBSBot final
+ : public Command
{
- private:
+private:
void DoAdd(CommandSource &source, const std::vector<Anope::string> &params)
{
const Anope::string &nick = params[1];
@@ -27,23 +28,21 @@ class CommandBSBot : public Command
return;
}
- Configuration::Block *networkinfo = Config->GetBlock("networkinfo");
-
- if (nick.length() > networkinfo->Get<unsigned>("nicklen"))
+ if (nick.length() > IRCD->MaxNick)
{
- source.Reply(_("Bot nicks may only be %d characters long."), networkinfo->Get<unsigned>("nicklen"));
+ source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->MaxNick);
return;
}
- if (user.length() > networkinfo->Get<unsigned>("userlen"))
+ if (user.length() > IRCD->MaxUser)
{
- source.Reply(_("Bot idents may only be %d characters long."), networkinfo->Get<unsigned>("userlen"));
+ source.Reply(_("Bot idents may only be %zu characters long."), IRCD->MaxUser);
return;
}
- if (host.length() > networkinfo->Get<unsigned>("hostlen"))
+ if (host.length() > IRCD->MaxHost)
{
- source.Reply(_("Bot hosts may only be %d characters long."), networkinfo->Get<unsigned>("hostlen"));
+ source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->MaxHost);
return;
}
@@ -82,7 +81,7 @@ class CommandBSBot : public Command
return;
}
- BotInfo *bi = new BotInfo(nick, user, host, real);
+ auto *bi = new BotInfo(nick, user, host, real);
Log(LOG_ADMIN, source, this) << "ADD " << bi->GetMask() << " " << bi->realname;
@@ -119,23 +118,22 @@ class CommandBSBot : public Command
return;
}
- Configuration::Block *networkinfo = Config->GetBlock("networkinfo");
-
- if (nick.length() > networkinfo->Get<unsigned>("nicklen"))
+ if (nick.length() > IRCD->MaxNick)
{
- source.Reply(_("Bot nicks may only be %d characters long."), networkinfo->Get<unsigned>("nicklen"));
+ source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->MaxNick);
return;
}
- if (user.length() > networkinfo->Get<unsigned>("userlen"))
+ if (user.length() > IRCD->MaxUser)
{
- source.Reply(_("Bot idents may only be %d characters long."), networkinfo->Get<unsigned>("userlen"));
+ source.Reply(_("Bot idents may only be %zu characters long."), IRCD->MaxUser);
return;
}
- if (host.length() > networkinfo->Get<unsigned>("hostlen"))
+ if (host.length() > IRCD->MaxHost)
{
- source.Reply(_("Bot hosts may only be %d characters long."), networkinfo->Get<unsigned>("hostlen"));
+ source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->MaxHost
+ );
return;
}
@@ -263,7 +261,7 @@ class CommandBSBot : public Command
delete bi;
return;
}
- public:
+public:
CommandBSBot(Module *creator) : Command(creator, "botserv/bot", 1, 6)
{
this->SetDesc(_("Maintains network bot list"));
@@ -272,13 +270,13 @@ class CommandBSBot : public Command
this->SetSyntax(_("\002DEL \037nick\037\002"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot modification is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -345,7 +343,7 @@ class CommandBSBot : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -370,11 +368,12 @@ class CommandBSBot : public Command
}
};
-class BSBot : public Module
+class BSBot final
+ : public Module
{
CommandBSBot commandbsbot;
- public:
+public:
BSBot(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandbsbot(this)
{
diff --git a/modules/botserv/bs_botlist.cpp b/modules/botserv/bs_botlist.cpp
new file mode 100644
index 000000000..dbb92a999
--- /dev/null
+++ b/modules/botserv/bs_botlist.cpp
@@ -0,0 +1,116 @@
+/* BotServ core functions
+ *
+ * (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"
+
+class CommandBSBotList final
+ : public Command
+{
+public:
+ CommandBSBotList(Module *creator) : Command(creator, "botserv/botlist", 0, 1)
+ {
+ this->SetDesc(_("Lists available bots"));
+ this->SetSyntax("[OPERONLY] [UNUSED] [VANITY]");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ const bool is_admin = source.HasCommand("botserv/administration");
+ auto operonly = false;
+ auto unused = false;
+ auto vanity = false;
+ if (is_admin && !params.empty())
+ {
+ spacesepstream keywords(params[0]);
+ for (Anope::string keyword; keywords.GetToken(keyword); )
+ {
+ if (keyword.equals_ci("OPERONLY"))
+ operonly = true;
+ if (keyword.equals_ci("UNUSED"))
+ unused = true;
+ if (keyword.equals_ci("VANITY"))
+ vanity = true;
+ }
+ }
+
+ unsigned count = 0;
+ ListFormatter list(source.GetAccount());
+
+ list.AddColumn(_("Nick")).AddColumn(_("Mask")).AddColumn(_("Real name"));
+
+ for (const auto &[_, bi] : *BotListByNick)
+ {
+ if (is_admin || !bi->oper_only)
+ {
+ if (operonly && !bi->oper_only)
+ continue;
+ if (unused && bi->GetChannelCount())
+ continue;
+ if (vanity && bi->conf)
+ continue;
+
+ ++count;
+ ListFormatter::ListEntry entry;
+ entry["Nick"] = bi->nick;
+ entry["Mask"] = bi->GetIdent() + "@" + bi->host;
+ entry["Real name"] = bi->realname;
+ list.AddEntry(entry);
+ }
+ }
+
+ std::vector<Anope::string> replies;
+ list.Process(replies);
+
+ if (!count)
+ source.Reply(_("There are no bots available at this time.\n"
+ "Ask a Services Operator to create one!"));
+ else
+ {
+ source.Reply(_("Bot list:"));
+
+ for (const auto &reply : replies)
+ source.Reply(reply);
+
+ source.Reply(_("%d bots available."), count);
+ }
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Lists all available bots on this network.\n"
+ "\n"
+ "If the OPERONLY, UNUSED or VANITY options are given only\n"
+ "bots which, respectively, are oper-only, unused or were\n"
+ "added at runtime will be displayed. If multiple options are\n"
+ "given, all nicks matching at least one option will be\n"
+ "displayed.\n"
+ "\n"
+ "Note that these options are limited to \037Services Operators\037."));
+ return true;
+ }
+};
+
+class BSBotList final
+ : public Module
+{
+ CommandBSBotList commandbsbotlist;
+
+public:
+ BSBotList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ commandbsbotlist(this)
+ {
+
+ }
+};
+
+MODULE_INIT(BSBotList)
diff --git a/modules/commands/bs_control.cpp b/modules/botserv/bs_control.cpp
index e6847d5d9..2ea81a45b 100644
--- a/modules/commands/bs_control.cpp
+++ b/modules/botserv/bs_control.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandBSSay : public Command
+class CommandBSSay final
+ : public Command
{
- public:
+public:
CommandBSSay(Module *creator) : Command(creator, "botserv/say", 2, 2)
{
this->SetDesc(_("Makes the bot say the specified text on the specified channel"));
this->SetSyntax(_("\037channel\037 \037text\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &text = params[1];
@@ -55,14 +56,14 @@ class CommandBSSay : public Command
return;
}
- IRCD->SendPrivmsg(*ci->bi, ci->name, "%s", text.c_str());
+ IRCD->SendPrivmsg(*ci->bi, ci->name, text);
ci->bi->lastmsg = Anope::CurTime;
bool override = !source.AccessFor(ci).HasPriv("SAY");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to say: " << text;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -71,16 +72,17 @@ class CommandBSSay : public Command
}
};
-class CommandBSAct : public Command
+class CommandBSAct final
+ : public Command
{
- public:
+public:
CommandBSAct(Module *creator) : Command(creator, "botserv/act", 2, 2)
{
this->SetDesc(_("Makes the bot do the equivalent of a \"/me\" command"));
this->SetSyntax(_("\037channel\037 \037text\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string message = params[1];
@@ -109,18 +111,14 @@ class CommandBSAct : public Command
return;
}
- message = message.replace_all_cs("\1", "");
- if (message.empty())
- return;
-
- IRCD->SendAction(*ci->bi, ci->name, "%s", message.c_str());
+ IRCD->SendPrivmsg(*ci->bi, ci->name, Anope::FormatCTCP("ACTION", message));
ci->bi->lastmsg = Anope::CurTime;
bool override = !source.AccessFor(ci).HasPriv("SAY");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to say: " << message;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -130,12 +128,13 @@ class CommandBSAct : public Command
}
};
-class BSControl : public Module
+class BSControl final
+ : public Module
{
CommandBSSay commandbssay;
CommandBSAct commandbsact;
- public:
+public:
BSControl(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandbssay(this), commandbsact(this)
{
diff --git a/modules/commands/bs_info.cpp b/modules/botserv/bs_info.cpp
index e7523b4e0..ae4af76cf 100644
--- a/modules/commands/bs_info.cpp
+++ b/modules/botserv/bs_info.cpp
@@ -11,16 +11,15 @@
#include "module.h"
-class CommandBSInfo : public Command
+class CommandBSInfo final
+ : public Command
{
- private:
- void send_bot_channels(std::vector<Anope::string> &buffers, const BotInfo *bi)
+private:
+ static void send_bot_channels(std::vector<Anope::string> &buffers, const BotInfo *bi)
{
Anope::string buf;
- for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
+ for (const auto &[_, ci] : *RegisteredChannelList)
{
- const ChannelInfo *ci = it->second;
-
if (ci->bi == bi)
{
buf += " " + ci->name + " ";
@@ -35,13 +34,13 @@ class CommandBSInfo : public Command
buffers.push_back(buf);
}
- public:
+public:
CommandBSInfo(Module *creator) : Command(creator, "botserv/info", 1, 1)
{
this->SetSyntax(_("{\037channel\037 | \037nickname\037}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &query = params[0];
@@ -51,27 +50,27 @@ class CommandBSInfo : public Command
if (bi)
{
- source.Reply(_("Information for bot \002%s\002:"), bi->nick.c_str());
+ source.Reply(_("Information about bot \002%s\002:"), bi->nick.c_str());
info[_("Mask")] = bi->GetIdent() + "@" + bi->host;
info[_("Real name")] = bi->realname;
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
- info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";
+ info[_("Used on")] = Anope::printf(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 (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
if (source.HasPriv("botserv/administration"))
{
std::vector<Anope::string> buf;
this->send_bot_channels(buf, bi);
- for (unsigned i = 0; i < buf.size(); ++i)
- source.Reply(buf[i]);
+ for (const auto &line : buf)
+ source.Reply(line);
}
}
@@ -94,14 +93,14 @@ class CommandBSInfo : public Command
std::vector<Anope::string> replies;
info.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
else
source.Reply(_("\002%s\002 is not a valid bot or registered channel."), query.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -113,17 +112,18 @@ class CommandBSInfo : public Command
return true;
}
- const Anope::string GetDesc(CommandSource &source) const anope_override
+ 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());
}
};
-class BSInfo : public Module
+class BSInfo final
+ : public Module
{
CommandBSInfo commandbsinfo;
- public:
+public:
BSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandbsinfo(this)
{
diff --git a/modules/commands/bs_kick.cpp b/modules/botserv/bs_kick.cpp
index 7351a5461..caaa51b01 100644
--- a/modules/commands/bs_kick.cpp
+++ b/modules/botserv/bs_kick.cpp
@@ -15,13 +15,14 @@
static Module *me;
-struct KickerDataImpl : KickerData
+struct KickerDataImpl final
+ : KickerData
{
KickerDataImpl(Extensible *obj)
{
amsgs = badwords = bolds = caps = colors = flood = italics = repeat = reverses = underlines = false;
- for (int16_t i = 0; i < TTB_SIZE; ++i)
- ttb[i] = 0;
+ for (auto &ttbtype : ttb)
+ ttbtype = 0;
capsmin = capspercent = 0;
floodlines = floodsecs = 0;
repeattimes = 0;
@@ -29,7 +30,7 @@ struct KickerDataImpl : KickerData
dontkickops = dontkickvoices = false;
}
- void Check(ChannelInfo *ci) anope_override
+ void Check(ChannelInfo *ci) override
{
if (amsgs || badwords || bolds || caps || colors || flood || italics || repeat || reverses || underlines || dontkickops || dontkickvoices)
return;
@@ -37,11 +38,12 @@ struct KickerDataImpl : KickerData
ci->Shrink<KickerData>("kickerdata");
}
- struct ExtensibleItem : ::ExtensibleItem<KickerDataImpl>
+ struct ExtensibleItem final
+ : ::ExtensibleItem<KickerDataImpl>
{
ExtensibleItem(Module *m, const Anope::string &ename) : ::ExtensibleItem<KickerDataImpl>(m, ename) { }
- void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
if (s->GetSerializableType()->GetName() != "ChannelInfo")
return;
@@ -51,28 +53,31 @@ struct KickerDataImpl : KickerData
if (kd == NULL)
return;
- data.SetType("kickerdata:amsgs", Serialize::Data::DT_INT); data["kickerdata:amsgs"] << kd->amsgs;
- data.SetType("kickerdata:badwords", Serialize::Data::DT_INT); data["kickerdata:badwords"] << kd->badwords;
- data.SetType("kickerdata:bolds", Serialize::Data::DT_INT); data["kickerdata:bolds"] << kd->bolds;
- data.SetType("kickerdata:caps", Serialize::Data::DT_INT); data["kickerdata:caps"] << kd->caps;
- data.SetType("kickerdata:colors", Serialize::Data::DT_INT); data["kickerdata:colors"] << kd->colors;
- data.SetType("kickerdata:flood", Serialize::Data::DT_INT); data["kickerdata:flood"] << kd->flood;
- data.SetType("kickerdata:italics", Serialize::Data::DT_INT); data["kickerdata:italics"] << kd->italics;
- data.SetType("kickerdata:repeat", Serialize::Data::DT_INT); data["kickerdata:repeat"] << kd->repeat;
- data.SetType("kickerdata:reverses", Serialize::Data::DT_INT); data["kickerdata:reverses"] << kd->reverses;
- data.SetType("kickerdata:underlines", Serialize::Data::DT_INT); data["kickerdata:underlines"] << kd->underlines;
- data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << kd->capsmin;
- data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << kd->capspercent;
- data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << kd->floodlines;
- data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << kd->floodsecs;
- data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << kd->repeattimes;
- data.SetType("dontkickops", Serialize::Data::DT_INT); data["dontkickops"] << kd->dontkickops;
- data.SetType("dontkickvoices", Serialize::Data::DT_INT); data["dontkickvoices"] << kd->dontkickvoices;
- for (int16_t i = 0; i < TTB_SIZE; ++i)
- data["ttb"] << kd->ttb[i] << " ";
+ data.Store("kickerdata:amsgs", kd->amsgs);
+ data.Store("kickerdata:badwords", kd->badwords);
+ data.Store("kickerdata:bolds", kd->bolds);
+ data.Store("kickerdata:caps", kd->caps);
+ data.Store("kickerdata:colors", kd->colors);
+ data.Store("kickerdata:flood", kd->flood);
+ data.Store("kickerdata:italics", kd->italics);
+ data.Store("kickerdata:repeat", kd->repeat);
+ data.Store("kickerdata:reverses", kd->reverses);
+ data.Store("kickerdata:underlines", kd->underlines);
+ data.Store("capsmin", kd->capsmin);
+ data.Store("capspercent", kd->capspercent);
+ data.Store("floodlines", kd->floodlines);
+ data.Store("floodsecs", kd->floodsecs);
+ data.Store("repeattimes", kd->repeattimes);
+ data.Store("dontkickops", kd->dontkickops);
+ data.Store("dontkickvoices", kd->dontkickvoices);
+
+ std::ostringstream oss;
+ for (auto ttbtype : kd->ttb)
+ oss << ttbtype << " ";
+ data.Store("ttb", oss.str());
}
- void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
{
if (s->GetSerializableType()->GetName() != "ChannelInfo")
return;
@@ -103,43 +108,40 @@ struct KickerDataImpl : KickerData
data["ttb"] >> ttb;
spacesepstream sep(ttb);
for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
- try
- {
- kd->ttb[i] = convertTo<int16_t>(tok);
- }
- catch (const ConvertException &) { }
+ {
+ if (auto n = Anope::TryConvert<int16_t>(tok))
+ kd->ttb[i] = n.value();
+ }
kd->Check(ci);
}
};
};
-class CommandBSKick : public Command
+class CommandBSKick final
+ : public Command
{
- public:
+public:
CommandBSKick(Module *creator) : Command(creator, "botserv/kick", 0)
{
this->SetDesc(_("Configures kickers"));
this->SetSyntax(_("\037option\037 \037channel\037 {\037ON|OFF\037} [\037settings\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Configures bot kickers. \037option\037 can be one of:"));
Anope::string this_name = source.command;
- for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
+ for (const auto &[c_name, info] : source.service->commands)
{
- const Anope::string &c_name = it->first;
- const CommandInfo &info = it->second;
-
if (c_name.find_ci(this_name + " ") == 0)
{
ServiceReference<Command> command("Command", info.name);
@@ -151,29 +153,30 @@ class CommandBSKick : public Command
}
}
- source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
+ source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
"on a specific option.\n"
" \n"
"Note: access to this command is controlled by the\n"
- "level SET."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
+ "level SET."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
};
-class CommandBSKickBase : public Command
+class CommandBSKickBase
+ : public Command
{
- public:
+public:
CommandBSKickBase(Module *creator, const Anope::string &cname, int minarg, int maxarg) : Command(creator, cname, minarg, maxarg)
{
}
- virtual void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override = 0;
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override = 0;
- virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override = 0;
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override = 0;
- protected:
- bool CheckArguments(CommandSource &source, const std::vector<Anope::string> &params, ChannelInfo* &ci)
+protected:
+ bool CheckArguments(CommandSource &source, const std::vector<Anope::string> &params, ChannelInfo *&ci)
{
const Anope::string &chan = params[0];
const Anope::string &option = params[1];
@@ -181,7 +184,7 @@ class CommandBSKickBase : public Command
ci = ChannelInfo::Find(chan);
if (Anope::ReadOnly)
- source.Reply(_("Sorry, kicker configuration is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
else if (ci == NULL)
source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
else if (option.empty())
@@ -204,21 +207,13 @@ class CommandBSKickBase : public Command
{
if (!ttb.empty())
{
- int16_t i;
-
- try
- {
- i = convertTo<int16_t>(ttb);
- if (i < 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
+ kd->ttb[ttb_idx] = Anope::Convert<int16_t>(ttb, -1);
+ if (kd->ttb[ttb_idx] < 0)
{
+ kd->ttb[ttb_idx] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
-
- kd->ttb[ttb_idx] = i;
}
else
kd->ttb[ttb_idx] = 0;
@@ -246,16 +241,17 @@ class CommandBSKickBase : public Command
}
};
-class CommandBSKickAMSG : public CommandBSKickBase
+class CommandBSKickAMSG final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickAMSG(Module *creator) : CommandBSKickBase(creator, "botserv/kick/amsg", 2, 3)
{
this->SetDesc(_("Configures AMSG kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -266,7 +262,7 @@ class CommandBSKickAMSG : public CommandBSKickBase
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -282,16 +278,17 @@ class CommandBSKickAMSG : public CommandBSKickBase
}
};
-class CommandBSKickBadwords : public CommandBSKickBase
+class CommandBSKickBadwords final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickBadwords(Module *creator) : CommandBSKickBase(creator, "botserv/kick/badwords", 2, 3)
{
this->SetDesc(_("Configures badwords kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -303,7 +300,7 @@ class CommandBSKickBadwords : public CommandBSKickBase
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -311,26 +308,27 @@ class CommandBSKickBadwords : public CommandBSKickBase
"option tells the bot to kick users who say certain words\n"
"on the channels.\n"
"You can define bad words for your channel using the\n"
- "\002BADWORDS\002 command. Type \002%s%s HELP BADWORDS\002 for\n"
+ "\002BADWORDS\002 command. Type \002%s HELP BADWORDS\002 for\n"
"more information.\n"
" \n"
"\037ttb\037 is the number of times a user can be kicked\n"
"before it gets banned. Don't give ttb to disable\n"
- "the ban system once activated."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ "the ban system once activated."), source.service->GetQueryCommand().c_str());
return true;
}
};
-class CommandBSKickBolds : public CommandBSKickBase
+class CommandBSKickBolds final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickBolds(Module *creator) : CommandBSKickBase(creator, "botserv/kick/bolds", 2, 3)
{
this->SetDesc(_("Configures bolds kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -341,7 +339,7 @@ class CommandBSKickBolds : public CommandBSKickBase
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -355,16 +353,17 @@ class CommandBSKickBolds : public CommandBSKickBase
}
};
-class CommandBSKickCaps : public CommandBSKickBase
+class CommandBSKickCaps final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickCaps(Module *creator) : CommandBSKickBase(creator, "botserv/kick/caps", 2, 5)
{
this->SetDesc(_("Configures caps kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037min\037 [\037percent\037]]]\002"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (!CheckArguments(source, params, ci))
@@ -380,13 +379,8 @@ class CommandBSKickCaps : public CommandBSKickBase
if (!ttb.empty())
{
- try
- {
- kd->ttb[TTB_CAPS] = convertTo<int16_t>(ttb);
- if (kd->ttb[TTB_CAPS] < 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
+ kd->ttb[TTB_CAPS] = Anope::Convert<int16_t>(ttb, -1);
+ if (kd->ttb[TTB_CAPS] < 0)
{
kd->ttb[TTB_CAPS] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
@@ -396,21 +390,11 @@ class CommandBSKickCaps : public CommandBSKickBase
else
kd->ttb[TTB_CAPS] = 0;
- kd->capsmin = 10;
- try
- {
- kd->capsmin = convertTo<int16_t>(min);
- }
- catch (const ConvertException &) { }
+ kd->capsmin = Anope::Convert(min, 0);
if (kd->capsmin < 1)
kd->capsmin = 10;
- kd->capspercent = 25;
- try
- {
- kd->capspercent = convertTo<int16_t>(percent);
- }
- catch (const ConvertException &) { }
+ kd->capspercent = Anope::Convert(percent, 0);
if (kd->capspercent < 1 || kd->capspercent > 100)
kd->capspercent = 25;
@@ -432,7 +416,7 @@ class CommandBSKickCaps : public CommandBSKickBase
kd->Check(ci);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -451,16 +435,17 @@ class CommandBSKickCaps : public CommandBSKickBase
}
};
-class CommandBSKickColors : public CommandBSKickBase
+class CommandBSKickColors final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickColors(Module *creator) : CommandBSKickBase(creator, "botserv/kick/colors", 2, 3)
{
this->SetDesc(_("Configures color kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -471,7 +456,7 @@ class CommandBSKickColors : public CommandBSKickBase
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -485,16 +470,17 @@ class CommandBSKickColors : public CommandBSKickBase
}
};
-class CommandBSKickFlood : public CommandBSKickBase
+class CommandBSKickFlood final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickFlood(Module *creator) : CommandBSKickBase(creator, "botserv/kick/flood", 2, 5)
{
this->SetDesc(_("Configures flood kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037ln\037 [\037secs\037]]]\002"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (!CheckArguments(source, params, ci))
@@ -510,42 +496,25 @@ class CommandBSKickFlood : public CommandBSKickBase
if (!ttb.empty())
{
- int16_t i;
-
- try
- {
- i = convertTo<int16_t>(ttb);
- if (i < 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
+ kd->ttb[TTB_FLOOD] = Anope::Convert<int16_t>(ttb, -1);
+ if (kd->ttb[TTB_FLOOD] < 0)
{
+ kd->ttb[TTB_FLOOD] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
-
- kd->ttb[TTB_FLOOD] = i;
}
else
kd->ttb[TTB_FLOOD] = 0;
- kd->floodlines = 6;
- try
- {
- kd->floodlines = convertTo<int16_t>(lines);
- }
- catch (const ConvertException &) { }
+ kd->floodlines = Anope::Convert(lines, -1);
if (kd->floodlines < 2)
kd->floodlines = 6;
- kd->floodsecs = 10;
- try
- {
- kd->floodsecs = convertTo<int16_t>(secs);
- }
- catch (const ConvertException &) { }
+ kd->floodsecs = Anope::Convert(secs, -1);
if (kd->floodsecs < 1)
kd->floodsecs = 10;
+
if (kd->floodsecs > Config->GetModule(me)->Get<time_t>("keepdata"))
kd->floodsecs = Config->GetModule(me)->Get<time_t>("keepdata");
@@ -567,7 +536,7 @@ class CommandBSKickFlood : public CommandBSKickBase
kd->Check(ci);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -583,16 +552,17 @@ class CommandBSKickFlood : public CommandBSKickBase
}
};
-class CommandBSKickItalics : public CommandBSKickBase
+class CommandBSKickItalics final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickItalics(Module *creator) : CommandBSKickBase(creator, "botserv/kick/italics", 2, 3)
{
this->SetDesc(_("Configures italics kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -603,7 +573,7 @@ class CommandBSKickItalics : public CommandBSKickBase
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -617,16 +587,17 @@ class CommandBSKickItalics : public CommandBSKickBase
}
};
-class CommandBSKickRepeat : public CommandBSKickBase
+class CommandBSKickRepeat final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickRepeat(Module *creator) : CommandBSKickBase(creator, "botserv/kick/repeat", 2, 4)
{
this->SetDesc(_("Configures repeat kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037num\037]]\002"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (!CheckArguments(source, params, ci))
@@ -641,31 +612,18 @@ class CommandBSKickRepeat : public CommandBSKickBase
if (!ttb.empty())
{
- int16_t i;
-
- try
- {
- i = convertTo<int16_t>(ttb);
- if (i < 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
+ kd->ttb[TTB_REPEAT] = Anope::Convert(ttb, -1);
+ if (kd->ttb[TTB_REPEAT] < 0)
{
+ kd->ttb[TTB_REPEAT] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
-
- kd->ttb[TTB_REPEAT] = i;
}
else
kd->ttb[TTB_REPEAT] = 0;
- kd->repeattimes = 3;
- try
- {
- kd->repeattimes = convertTo<int16_t>(times);
- }
- catch (const ConvertException &) { }
+ kd->repeattimes = Anope::Convert<int16_t>(times, -1);
if (kd->repeattimes < 1)
kd->repeattimes = 3;
@@ -702,7 +660,7 @@ class CommandBSKickRepeat : public CommandBSKickBase
kd->Check(ci);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -718,16 +676,17 @@ class CommandBSKickRepeat : public CommandBSKickBase
}
};
-class CommandBSKickReverses : public CommandBSKickBase
+class CommandBSKickReverses final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickReverses(Module *creator) : CommandBSKickBase(creator, "botserv/kick/reverses", 2, 3)
{
this->SetDesc(_("Configures reverses kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -738,7 +697,7 @@ class CommandBSKickReverses : public CommandBSKickBase
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -752,16 +711,17 @@ class CommandBSKickReverses : public CommandBSKickBase
}
};
-class CommandBSKickUnderlines : public CommandBSKickBase
+class CommandBSKickUnderlines final
+ : public CommandBSKickBase
{
- public:
+public:
CommandBSKickUnderlines(Module *creator) : CommandBSKickBase(creator, "botserv/kick/underlines", 2, 3)
{
this->SetDesc(_("Configures underlines kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
@@ -772,7 +732,7 @@ class CommandBSKickUnderlines : public CommandBSKickBase
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -786,16 +746,17 @@ class CommandBSKickUnderlines : public CommandBSKickBase
}
};
-class CommandBSSetDontKickOps : public Command
+class CommandBSSetDontKickOps final
+ : public Command
{
- public:
+public:
CommandBSSetDontKickOps(Module *creator, const Anope::string &sname = "botserv/set/dontkickops") : Command(creator, sname, 2, 2)
{
this->SetDesc(_("To protect ops against bot kicks"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (ci == NULL)
@@ -813,7 +774,7 @@ class CommandBSSetDontKickOps : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -840,7 +801,7 @@ class CommandBSSetDontKickOps : public Command
kd->Check(ci);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -851,16 +812,17 @@ class CommandBSSetDontKickOps : public Command
}
};
-class CommandBSSetDontKickVoices : public Command
+class CommandBSSetDontKickVoices final
+ : public Command
{
- public:
+public:
CommandBSSetDontKickVoices(Module *creator, const Anope::string &sname = "botserv/set/dontkickvoices") : Command(creator, sname, 2, 2)
{
this->SetDesc(_("To protect voices against bot kicks"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (ci == NULL)
@@ -878,7 +840,7 @@ class CommandBSSetDontKickVoices : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -905,7 +867,7 @@ class CommandBSSetDontKickVoices : public Command
kd->Check(ci);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -916,9 +878,9 @@ class CommandBSSetDontKickVoices : public Command
}
};
-struct BanData
+struct BanData final
{
- struct Data
+ struct Data final
{
Anope::string mask;
time_t last_use;
@@ -927,16 +889,16 @@ struct BanData
Data()
{
last_use = 0;
- for (int i = 0; i < TTB_SIZE; ++i)
- this->ttb[i] = 0;
+ for (auto &ttbtype : this->ttb)
+ ttbtype = 0;
}
};
- private:
+private:
typedef Anope::map<Data> data_type;
data_type data_map;
- public:
+public:
BanData(Extensible *) { }
Data &get(const Anope::string &key)
@@ -964,7 +926,7 @@ struct BanData
}
};
-struct UserData
+struct UserData final
{
UserData(Extensible *)
{
@@ -987,19 +949,21 @@ struct UserData
Anope::string lastline;
};
-class BanDataPurger : public Timer
+class BanDataPurger final
+ : public Timer
{
- public:
- BanDataPurger(Module *o) : Timer(o, 300, Anope::CurTime, true) { }
+public:
+ BanDataPurger(Module *o)
+ : Timer(o, 300, true)
+ {
+ }
- void Tick(time_t) anope_override
+ void Tick() override
{
Log(LOG_DEBUG) << "bs_main: Running bandata purger";
- for (channel_map::iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
+ for (auto &[_, c] : ChannelList)
{
- Channel *c = it->second;
-
BanData *bd = c->GetExt<BanData>("bandata");
if (bd != NULL)
{
@@ -1011,7 +975,8 @@ class BanDataPurger : public Timer
}
};
-class BSKick : public Module
+class BSKick final
+ : public Module
{
ExtensibleItem<BanData> bandata;
ExtensibleItem<UserData> userdata;
@@ -1048,7 +1013,7 @@ class BSKick : public Module
UserData *ud = userdata.Require(uc);
return ud;
- }
+ }
void check_ban(ChannelInfo *ci, User *u, KickerData *kd, int ttbtype)
{
@@ -1074,7 +1039,7 @@ class BSKick : public Module
}
}
- void bot_kick(ChannelInfo *ci, User *u, const char *message, ...)
+ static void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) ATTR_FORMAT(3, 4)
{
va_list args;
char buf[1024];
@@ -1087,10 +1052,10 @@ class BSKick : public Module
vsnprintf(buf, sizeof(buf), fmt.c_str(), args);
va_end(args);
- ci->c->Kick(ci->bi, u, "%s", buf);
+ ci->c->Kick(ci->bi, u, Anope::string(buf));
}
- public:
+public:
BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
bandata(this, "bandata"),
userdata(this, "userdata"),
@@ -1109,7 +1074,7 @@ class BSKick : public Module
}
- void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) override
{
if (!ci)
return;
@@ -1224,7 +1189,7 @@ class BSKick : public Module
info.AddOption(_("Voices protection"));
}
- void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
+ void OnPrivmsg(User *u, Channel *c, Anope::string &msg, const Anope::map<Anope::string> &tags) override
{
/* Now we can make kicker stuff. We try to order the checks
* from the fastest one to the slowest one, since there's
@@ -1253,11 +1218,9 @@ class BSKick : public Module
/* If it's a /me, cut the CTCP part because the ACTION will cause
* problems with the caps or badwords kicker
*/
- if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1')
- {
- realbuf.erase(0, 8);
- realbuf.erase(realbuf.length() - 1);
- }
+ Anope::string ctcpname, ctcpbody;
+ if (Anope::ParseCTCP(msg, ctcpname, ctcpbody) && ctcpname.equals_ci("ACTION"))
+ realbuf = ctcpbody;
if (realbuf.empty())
return;
@@ -1307,11 +1270,11 @@ class BSKick : public Module
{
int i = 0, l = 0;
- for (unsigned j = 0, end = realbuf.length(); j < end; ++j)
+ for (auto chr : realbuf)
{
- if (isupper(realbuf[j]))
+ if (isupper(chr))
++i;
- else if (islower(realbuf[j]))
+ else if (islower(chr))
++l;
}
diff --git a/modules/commands/bs_set.cpp b/modules/botserv/bs_set.cpp
index c6ad14959..1ab00205d 100644
--- a/modules/commands/bs_set.cpp
+++ b/modules/botserv/bs_set.cpp
@@ -11,21 +11,22 @@
#include "module.h"
-class CommandBSSet : public Command
+class CommandBSSet final
+ : public Command
{
- public:
+public:
CommandBSSet(Module *creator) : Command(creator, "botserv/set", 3, 3)
{
this->SetDesc(_("Configures bot options"));
this->SetSyntax(_("\037option\037 \037(channel | bot)\037 \037settings\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -35,10 +36,8 @@ class CommandBSSet : public Command
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
Anope::string this_name = source.command;
- for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
+ for (const auto &[c_name, info] : source.service->commands)
{
- const Anope::string &c_name = it->first;
- const CommandInfo &info = it->second;
if (c_name.find_ci(this_name + " ") == 0)
{
if (info.hide)
@@ -54,30 +53,37 @@ class CommandBSSet : public Command
if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
continue;
- source.command = it->first;
+ source.command = c_name;
command->OnServHelp(source);
}
}
}
- source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
- "particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
+ source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information on a\n"
+ "particular option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
};
-class CommandBSSetBanExpire : public Command
+class CommandBSSetBanExpire final
+ : public Command
{
- public:
- class UnbanTimer : public Timer
+public:
+ class UnbanTimer final
+ : public Timer
{
Anope::string chname;
Anope::string mask;
- public:
- UnbanTimer(Module *creator, const Anope::string &ch, const Anope::string &bmask, time_t t) : Timer(creator, t), chname(ch), mask(bmask) { }
+ public:
+ UnbanTimer(Module *creator, const Anope::string &ch, const Anope::string &bmask, time_t t)
+ : Timer(creator, t)
+ , chname(ch)
+ , mask(bmask)
+ {
+ }
- void Tick(time_t) anope_override
+ void Tick() override
{
Channel *c = Channel::Find(chname);
if (c)
@@ -91,7 +97,7 @@ class CommandBSSetBanExpire : public Command
this->SetSyntax(_("\037channel\037 \037time\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
const Anope::string &arg = params[1];
@@ -112,7 +118,7 @@ class CommandBSSetBanExpire : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, changing bot options is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -141,7 +147,7 @@ class CommandBSSetBanExpire : public Command
source.Reply(_("Bot bans will automatically expire after %s."), Anope::Duration(ci->banexpire, source.GetAccount()).c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -153,16 +159,17 @@ class CommandBSSetBanExpire : public Command
}
};
-class CommandBSSetPrivate : public Command
+class CommandBSSetPrivate final
+ : public Command
{
- public:
+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->SetSyntax(_("\037botname\037 {\037ON|OFF\037}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
BotInfo *bi = BotInfo::Find(params[0], true);
const Anope::string &value = params[1];
@@ -193,7 +200,7 @@ class CommandBSSetPrivate : public Command
this->OnSyntaxError(source, source.command);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -203,20 +210,21 @@ class CommandBSSetPrivate : public Command
}
};
-class BSSet : public Module
+class BSSet final
+ : public Module
{
CommandBSSet commandbsset;
CommandBSSetBanExpire commandbssetbanexpire;
CommandBSSetPrivate commandbssetprivate;
- public:
+public:
BSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandbsset(this), commandbssetbanexpire(this),
commandbssetprivate(this)
{
}
- void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) anope_override
+ void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) override
{
if (!ci->banexpire)
return;
diff --git a/modules/pseudoclients/chanserv.cpp b/modules/chanserv/chanserv.cpp
index 9e7d8d592..f4ba4c007 100644
--- a/modules/pseudoclients/chanserv.cpp
+++ b/modules/chanserv/chanserv.cpp
@@ -19,36 +19,43 @@ inline static Anope::string BotModes()
);
}
-class ChanServCore : public Module, public ChanServService
+class ChanServCore final
+ : public Module
+ , public ChanServService
{
Reference<BotInfo> ChanServ;
std::vector<Anope::string> defaults;
ExtensibleItem<bool> inhabit;
ExtensibleRef<bool> persist;
- bool always_lower;
+ bool always_lower = false;
- public:
+public:
ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- ChanServService(this), inhabit(this, "inhabit"), persist("PERSIST"), always_lower(false)
+ ChanServService(this), inhabit(this, "inhabit"), persist("PERSIST")
{
}
- void Hold(Channel *c) anope_override
+ void Hold(Channel *c) override
{
/** A timer used to keep the BotServ bot/ChanServ in the channel
* after kicking the last user in a channel
*/
- class ChanServTimer : public Timer
+ class ChanServTimer final
+ : public Timer
{
Reference<BotInfo> &ChanServ;
ExtensibleItem<bool> &inhabit;
Reference<Channel> c;
- public:
+ public:
/** Constructor
* @param chan The channel
*/
- ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), ChanServ(cs), inhabit(i), c(chan)
+ ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan)
+ : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "1m"))
+ , ChanServ(cs)
+ , inhabit(i)
+ , c(chan)
{
if (!ChanServ || !c)
return;
@@ -68,7 +75,7 @@ class ChanServCore : public Module, public ChanServService
/** Called when the delay is up
* @param The current time
*/
- void Tick(time_t) anope_override
+ void Tick() override
{
if (!c)
return;
@@ -96,7 +103,7 @@ class ChanServCore : public Module, public ChanServService
new ChanServTimer(ChanServ, inhabit, this->owner, c);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
const Anope::string &channick = conf->GetModule(this)->Get<const Anope::string>("client");
@@ -109,14 +116,13 @@ class ChanServCore : public Module, public ChanServService
ChanServ = bi;
- spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace cs_secure securefounder signkick")).GetTokens(defaults);
+ spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace securefounder signkick")).GetTokens(defaults);
if (defaults.empty())
{
- defaults.push_back("KEEPTOPIC");
- defaults.push_back("PEACE");
- defaults.push_back("CS_SECURE");
- defaults.push_back("SECUREFOUNDER");
- defaults.push_back("SIGNKICK");
+ defaults.emplace_back("KEEPTOPIC");
+ defaults.emplace_back("PEACE");
+ defaults.emplace_back("SECUREFOUNDER");
+ defaults.emplace_back("SIGNKICK");
}
else if (defaults[0].equals_ci("none"))
defaults.clear();
@@ -124,13 +130,13 @@ class ChanServCore : public Module, public ChanServService
always_lower = conf->GetModule(this)->Get<bool>("always_lower_ts");
}
- void OnBotDelete(BotInfo *bi) anope_override
+ void OnBotDelete(BotInfo *bi) override
{
if (bi == ChanServ)
ChanServ = NULL;
}
- EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override
+ EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override
{
if (bi == ChanServ && Config->GetModule(this)->Get<bool>("opersonly") && !u->HasMode("OPER"))
{
@@ -141,16 +147,14 @@ class ChanServCore : public Module, public ChanServService
return EVENT_CONTINUE;
}
- void OnDelCore(NickCore *nc) anope_override
+ void OnDelCore(NickCore *nc) override
{
std::deque<ChannelInfo *> chans;
nc->GetChannelReferences(chans);
int max_reg = Config->GetModule(this)->Get<int>("maxregistered");
- for (unsigned i = 0; i < chans.size(); ++i)
+ for (auto *ci : chans)
{
- ChannelInfo *ci = chans[i];
-
if (ci->GetFounder() == nc)
{
NickCore *newowner = NULL;
@@ -214,16 +218,16 @@ class ChanServCore : public Module, public ChanServService
}
}
- void OnDelChan(ChannelInfo *ci) anope_override
+ void OnDelChan(ChannelInfo *ci) override
{
/* remove access entries that are this channel */
std::deque<Anope::string> chans;
ci->GetChannelReferences(chans);
- for (unsigned i = 0; i < chans.size(); ++i)
+ for (const auto &chan : chans)
{
- ChannelInfo *c = ChannelInfo::Find(chans[i]);
+ ChannelInfo *c = ChannelInfo::Find(chan);
if (!c)
continue;
@@ -249,7 +253,7 @@ class ChanServCore : public Module, public ChanServService
}
}
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *ChanServ)
return EVENT_CONTINUE;
@@ -258,22 +262,22 @@ class ChanServCore : public Module, public ChanServService
"malicious users from \"taking over\" channels by limiting\n"
"who is allowed channel operator privileges. Available\n"
"commands are listed below; to use them, type\n"
- "\002%s%s \037command\037\002. For more information on a\n"
- "specific command, type \002%s%s HELP \037command\037\002.\n"),
- ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), ChanServ->nick.c_str(), source.command.c_str());
+ "\002%s \037command\037\002. For more information on a\n"
+ "specific command, type \002%s HELP \037command\037\002.\n"),
+ ChanServ->nick.c_str(), ChanServ->nick.c_str(), ChanServ->GetQueryCommand().c_str(), ChanServ->GetQueryCommand().c_str());
return EVENT_CONTINUE;
}
- void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *ChanServ)
return;
- time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "14d");
+ time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
if (chanserv_expire >= 86400)
source.Reply(_(" \n"
- "Note that any channel which is not used for %d days\n"
+ "Note that any channel which is not used for %lu days\n"
"(i.e. which no user on the channel's access list enters\n"
- "for that period of time) will be automatically dropped."), chanserv_expire / 86400);
+ "for that period of time) will be automatically dropped."), (unsigned long)chanserv_expire / 86400);
if (source.IsServicesOper())
source.Reply(_(" \n"
"Services Operators can also, depending on their access drop\n"
@@ -281,7 +285,7 @@ class ChanServCore : public Module, public ChanServService
"lists and settings for any channel."));
}
- void OnCheckModes(Reference<Channel> &c) anope_override
+ void OnCheckModes(Reference<Channel> &c) override
{
if (!c)
return;
@@ -301,14 +305,14 @@ class ChanServCore : public Module, public ChanServService
}
}
- void OnCreateChan(ChannelInfo *ci) anope_override
+ void OnCreateChan(ChannelInfo *ci) override
{
/* Set default chan flags */
- for (unsigned i = 0; i < defaults.size(); ++i)
- ci->Extend<bool>(defaults[i].upper());
+ for (const auto &def : defaults)
+ ci->Extend<bool>(def.upper());
}
- EventReturn OnCanSet(User *u, const ChannelMode *cm) anope_override
+ EventReturn OnCanSet(User *u, 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)
@@ -316,7 +320,7 @@ class ChanServCore : public Module, public ChanServService
return EVENT_CONTINUE;
}
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
bool perm = c->HasMode("PERM") || (c->ci && persist && persist->HasExt(c->ci));
if (!perm && !c->botchannel && (c->users.empty() || (c->users.size() == 1 && c->users.begin()->second->user->server == Me)))
@@ -325,15 +329,15 @@ class ChanServCore : public Module, public ChanServService
}
}
- void OnLog(Log *l) anope_override
+ void OnLog(Log *l) override
{
if (l->type == LOG_CHANNEL)
l->bi = ChanServ;
}
- void OnExpireTick() anope_override
+ void OnExpireTick() override
{
- time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "14d");
+ time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
if (!chanserv_expire || Anope::NoExpire || Anope::ReadOnly)
return;
@@ -369,7 +373,7 @@ class ChanServCore : public Module, public ChanServService
}
}
- EventReturn OnCheckDelete(Channel *c) anope_override
+ EventReturn OnCheckDelete(Channel *c) override
{
/* Do not delete this channel if ChanServ/a BotServ bot is inhabiting it */
if (inhabit.HasExt(c))
@@ -378,7 +382,7 @@ class ChanServCore : public Module, public ChanServService
return EVENT_CONTINUE;
}
- void OnUplinkSync(Server* s) anope_override
+ void OnUplinkSync(Server* s) override
{
// We need to do this when the uplink is synced as we may not know if
// the mode exists before then on some IRCds (e.g. InspIRCd).
@@ -389,9 +393,8 @@ class ChanServCore : public Module, public ChanServService
ChannelMode *perm = ModeManager::FindChannelModeByName("PERM");
/* Find all persistent channels and create them, as we are about to finish burst to our uplink */
- for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
+ for (const auto &[_, ci] : *RegisteredChannelList)
{
- ChannelInfo *ci = it->second;
if (!persist->HasExt(ci))
continue;
@@ -417,7 +420,7 @@ class ChanServCore : public Module, public ChanServService
}
- void OnChanRegistered(ChannelInfo *ci) anope_override
+ void OnChanRegistered(ChannelInfo *ci) override
{
if (!persist || !ci->c)
return;
@@ -429,7 +432,7 @@ class ChanServCore : public Module, public ChanServService
ci->c->SetMode(NULL, "PERM");
}
- void OnJoinChannel(User *u, Channel *c) anope_override
+ void OnJoinChannel(User *u, Channel *c) override
{
if (always_lower && c->ci && c->creation_time > c->ci->time_registered)
{
@@ -440,7 +443,7 @@ class ChanServCore : public Module, public ChanServService
}
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override
{
if (!always_lower && Anope::CurTime == c->creation_time && c->ci && setter.GetUser() && !setter.GetUser()->server->IsULined())
{
@@ -459,17 +462,17 @@ class ChanServCore : public Module, public ChanServService
return EVENT_CONTINUE;
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) override
{
if (!show_all)
return;
- time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "14d");
+ time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
if (!ci->HasExt("CS_NO_EXPIRE") && chanserv_expire && !Anope::NoExpire && ci->last_used != Anope::CurTime)
info[_("Expires")] = Anope::strftime(ci->last_used + chanserv_expire, source.GetAccount());
}
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override
+ void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) override
{
if (always_lower)
// Since we always lower the TS, the other side will remove the modes if the channel ts lowers, so we don't
diff --git a/modules/commands/cs_access.cpp b/modules/chanserv/cs_access.cpp
index 4fc4c48a5..dcae83ae7 100644
--- a/modules/commands/cs_access.cpp
+++ b/modules/chanserv/cs_access.cpp
@@ -16,41 +16,37 @@ static std::map<Anope::string, int16_t, ci::less> defaultLevels;
static inline void reset_levels(ChannelInfo *ci)
{
ci->ClearLevels();
- for (std::map<Anope::string, int16_t, ci::less>::iterator it = defaultLevels.begin(), it_end = defaultLevels.end(); it != it_end; ++it)
- ci->SetLevel(it->first, it->second);
+ for (auto &[priv, level] : defaultLevels)
+ ci->SetLevel(priv, level);
}
-class AccessChanAccess : public ChanAccess
+class AccessChanAccess final
+ : public ChanAccess
{
- public:
- int level;
+public:
+ int level = 0;
- AccessChanAccess(AccessProvider *p) : ChanAccess(p), level(0)
+ AccessChanAccess(AccessProvider *p) : ChanAccess(p)
{
}
- bool HasPriv(const Anope::string &name) const anope_override
+ bool HasPriv(const Anope::string &name) const override
{
return this->ci->GetLevel(name) != ACCESS_INVALID && this->level >= this->ci->GetLevel(name);
}
- Anope::string AccessSerialize() const anope_override
+ Anope::string AccessSerialize() const override
{
- return stringify(this->level);
+ return Anope::ToString(this->level);
}
- void AccessUnserialize(const Anope::string &data) anope_override
+ void AccessUnserialize(const Anope::string &data) override
{
- try
- {
- this->level = convertTo<int>(data);
- }
- catch (const ConvertException &)
- {
- }
+ if (auto l = Anope::TryConvert<int>(data))
+ this->level = l.value();
}
- bool operator>(const ChanAccess &other) const anope_override
+ bool operator>(const ChanAccess &other) const override
{
if (this->provider != other.provider)
return ChanAccess::operator>(other);
@@ -58,7 +54,7 @@ class AccessChanAccess : public ChanAccess
return this->level > anope_dynamic_static_cast<const AccessChanAccess *>(&other)->level;
}
- bool operator<(const ChanAccess &other) const anope_override
+ bool operator<(const ChanAccess &other) const override
{
if (this->provider != other.provider)
return ChanAccess::operator<(other);
@@ -67,9 +63,10 @@ class AccessChanAccess : public ChanAccess
}
};
-class AccessAccessProvider : public AccessProvider
+class AccessAccessProvider final
+ : public AccessProvider
{
- public:
+public:
static AccessAccessProvider *me;
AccessAccessProvider(Module *o) : AccessProvider(o, "access/access")
@@ -77,26 +74,26 @@ class AccessAccessProvider : public AccessProvider
me = this;
}
- ChanAccess *Create() anope_override
+ ChanAccess *Create() override
{
return new AccessChanAccess(this);
}
};
-AccessAccessProvider* AccessAccessProvider::me;
+AccessAccessProvider *AccessAccessProvider::me;
-class CommandCSAccess : public Command
+class CommandCSAccess final
+ : public Command
{
void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
Anope::string mask = params[2];
+ Anope::string description = params.size() > 4 ? params[4] : "";
Privilege *p = NULL;
int level = ACCESS_INVALID;
- try
- {
- level = convertTo<int>(params[3]);
- }
- catch (const ConvertException &)
+ if (auto lvl = Anope::TryConvert<int>(params[3]))
+ level = lvl.value();
+ else
{
p = PrivilegeManager::FindPrivilege(params[3]);
if (p != NULL && defaultLevels[p->name])
@@ -166,11 +163,21 @@ class CommandCSAccess : public Command
source.Reply(_("Masks and unregistered users may not be on access lists."));
return;
}
+ else if (na && na->nc->HasExt("NEVEROP"))
+ {
+ source.Reply(_("\002%s\002 does not wish to be added to channel access lists."),
+ na->nc->display.c_str());
+ return;
+ }
else if (mask.find_first_of("!*@") == Anope::string::npos && !na)
{
User *targ = User::Find(mask, true);
if (targ != NULL)
+ {
mask = "*!*@" + targ->GetDisplayedHost();
+ if (description.empty())
+ description = targ->nick;
+ }
else
{
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
@@ -198,7 +205,7 @@ class CommandCSAccess : public Command
}
}
- unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
+ unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
if (access_max && ci->GetDeepAccessCount() >= access_max)
{
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
@@ -214,6 +221,7 @@ class CommandCSAccess : public Command
access->level = level;
access->last_seen = 0;
access->created = Anope::CurTime;
+ access->description = description;
ci->AddAccess(access);
FOREACH_MOD(OnAccessAdd, (ci, source, access));
@@ -250,23 +258,24 @@ class CommandCSAccess : public Command
source.Reply(_("%s access list is empty."), ci->name.c_str());
else if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class AccessDelCallback : public NumberList
+ class AccessDelCallback final
+ : public NumberList
{
CommandSource &source;
ChannelInfo *ci;
Command *c;
- unsigned deleted;
+ unsigned deleted = 0;
Anope::string Nicks;
- bool denied;
- bool override;
- public:
- AccessDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), denied(false), override(false)
+ bool denied = false;
+ bool override = false;
+ public:
+ AccessDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c)
{
if (!source.AccessFor(ci).HasPriv("ACCESS_CHANGE") && source.HasPriv("chanserv/access/modify"))
this->override = true;
}
- ~AccessDelCallback()
+ ~AccessDelCallback() override
{
if (denied && !deleted)
source.Reply(ACCESS_DENIED);
@@ -283,7 +292,7 @@ class CommandCSAccess : public Command
}
}
- void HandleNumber(unsigned Number) anope_override
+ void HandleNumber(unsigned Number) override
{
if (!Number || Number > ci->GetAccessCount())
return;
@@ -354,17 +363,18 @@ class CommandCSAccess : public Command
source.Reply(_("%s access list is empty."), ci->name.c_str());
else if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class AccessListCallback : public NumberList
+ class AccessListCallback final
+ : public NumberList
{
ListFormatter &list;
ChannelInfo *ci;
- public:
+ public:
AccessListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci)
{
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > ci->GetAccessCount())
return;
@@ -373,12 +383,14 @@ class CommandCSAccess : public Command
Anope::string timebuf;
if (ci->c)
- for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit)
+ {
+ for (const auto &[_, cuc] : ci->c->users)
{
ChannelInfo *p;
- if (access->Matches(cit->second->user, cit->second->user->Account(), p))
+ if (access->Matches(cuc->user, cuc->user->Account(), p))
timebuf = "Now";
}
+ }
if (timebuf.empty())
{
if (access->last_seen == 0)
@@ -388,11 +400,12 @@ class CommandCSAccess : public Command
}
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(number);
+ entry["Number"] = Anope::ToString(number);
entry["Level"] = access->AccessSerialize();
entry["Mask"] = access->Mask();
entry["By"] = access->creator;
entry["Last seen"] = timebuf;
+ entry["Description"] = access->description;
this->list.AddEntry(entry);
}
}
@@ -410,12 +423,14 @@ class CommandCSAccess : public Command
Anope::string timebuf;
if (ci->c)
- for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit)
+ {
+ for (auto &[_, cuc] : ci->c->users)
{
ChannelInfo *p;
- if (access->Matches(cit->second->user, cit->second->user->Account(), p))
+ if (access->Matches(cuc->user, cuc->user->Account(), p))
timebuf = "Now";
}
+ }
if (timebuf.empty())
{
if (access->last_seen == 0)
@@ -425,11 +440,12 @@ class CommandCSAccess : public Command
}
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Level"] = access->AccessSerialize();
entry["Mask"] = access->Mask();
entry["By"] = access->creator;
entry["Last seen"] = timebuf;
+ entry["Description"] = access->description;
list.AddEntry(entry);
}
}
@@ -443,8 +459,8 @@ class CommandCSAccess : public Command
source.Reply(_("Access list for %s:"), ci->name.c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of access list"));
}
@@ -461,7 +477,7 @@ class CommandCSAccess : public Command
}
ListFormatter list(source.GetAccount());
- list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask"));
+ list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("Description"));
this->ProcessList(source, ci, params, list);
}
@@ -474,7 +490,7 @@ class CommandCSAccess : public Command
}
ListFormatter list(source.GetAccount());
- list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Last seen"));
+ list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Last seen")).AddColumn(_("Description"));
this->ProcessList(source, ci, params, list);
}
@@ -497,18 +513,18 @@ class CommandCSAccess : public Command
return;
}
- public:
- CommandCSAccess(Module *creator) : Command(creator, "chanserv/access", 2, 4)
+public:
+ CommandCSAccess(Module *creator) : Command(creator, "chanserv/access", 2, 5)
{
this->SetDesc(_("Modify the list of privileged users"));
- this->SetSyntax(_("\037channel\037 ADD \037mask\037 \037level\037"));
+ this->SetSyntax(_("\037channel\037 ADD \037mask\037 \037level\037 [\037description\037]"));
this->SetSyntax(_("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}"));
this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]"));
this->SetSyntax(_("\037channel\037 VIEW [\037mask\037 | \037list\037]"));
this->SetSyntax(_("\037channel\037 CLEAR"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[1];
const Anope::string &nick = params.size() > 2 ? params[2] : "";
@@ -549,7 +565,7 @@ class CommandCSAccess : public Command
else if (!has_access)
source.Reply(ACCESS_DENIED);
else if (Anope::ReadOnly && !is_list)
- source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
else if (cmd.equals_ci("ADD"))
this->DoAdd(source, ci, params);
else if (cmd.equals_ci("DEL"))
@@ -566,7 +582,7 @@ class CommandCSAccess : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -614,13 +630,14 @@ class CommandCSAccess : public Command
Anope::string cmd;
if (Command::FindCommandFromService("chanserv/levels", bi, cmd))
source.Reply(_("\002User access levels\002 can be seen by using the\n"
- "\002%s\002 command; type \002%s%s HELP LEVELS\002 for\n"
- "information."), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str());
+ "\002%s\002 command; type \002%s HELP LEVELS\002 for\n"
+ "information."), cmd.c_str(), bi->GetQueryCommand().c_str());
return true;
}
};
-class CommandCSLevels : public Command
+class CommandCSLevels final
+ : public Command
{
void DoSet(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
@@ -633,11 +650,9 @@ class CommandCSLevels : public Command
level = ACCESS_FOUNDER;
else
{
- try
- {
- level = convertTo<int>(lev);
- }
- catch (const ConvertException &)
+ if (auto lvl = Anope::TryConvert<int>(lev))
+ level = lvl.value();
+ else
{
this->OnSyntaxError(source, "SET");
return;
@@ -650,7 +665,10 @@ class CommandCSLevels : public Command
{
Privilege *p = PrivilegeManager::FindPrivilege(what);
if (p == NULL)
- source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ {
+ source.Reply(_("Setting \002%s\002 not known. Type \002%s HELP LEVELS\002 for a list of valid settings."),
+ what.c_str(), source.service->GetQueryCommand().c_str());
+ }
else
{
bool override = !source.AccessFor(ci).HasPriv("FOUNDER");
@@ -691,10 +709,11 @@ class CommandCSLevels : public Command
return;
}
- source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ source.Reply(_("Setting \002%s\002 not known. Type \002%s HELP LEVELS\002 for a list of valid settings."),
+ what.c_str(), source.service->GetQueryCommand().c_str());
}
- void DoList(CommandSource &source, ChannelInfo *ci)
+ static void DoList(CommandSource &source, ChannelInfo *ci)
{
source.Reply(_("Access level settings for channel %s:"), ci->name.c_str());
@@ -703,9 +722,8 @@ class CommandCSLevels : public Command
const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = 0; i < privs.size(); ++i)
+ for (const auto &p : privs)
{
- const Privilege &p = privs[i];
int16_t j = ci->GetLevel(p.name);
ListFormatter::ListEntry entry;
@@ -716,7 +734,7 @@ class CommandCSLevels : public Command
else if (j == ACCESS_FOUNDER)
entry["Level"] = Language::Translate(source.GetAccount(), _("(founder only)"));
else
- entry["Level"] = stringify(j);
+ entry["Level"] = Anope::ToString(j);
list.AddEntry(entry);
}
@@ -724,8 +742,8 @@ class CommandCSLevels : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
void DoReset(CommandSource &source, ChannelInfo *ci)
@@ -740,7 +758,7 @@ class CommandCSLevels : public Command
return;
}
- public:
+public:
CommandCSLevels(Module *creator) : Command(creator, "chanserv/levels", 2, 4)
{
this->SetDesc(_("Redefine the meanings of access levels"));
@@ -750,7 +768,7 @@ class CommandCSLevels : public Command
this->SetSyntax(_("\037channel\037 RESET"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[1];
const Anope::string &what = params.size() > 2 ? params[2] : "";
@@ -794,7 +812,7 @@ class CommandCSLevels : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (subcommand.equals_ci("DESC"))
{
@@ -803,10 +821,8 @@ class CommandCSLevels : public Command
ListFormatter list(source.GetAccount());
list.AddColumn(_("Name")).AddColumn(_("Description"));
- const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = 0; i < privs.size(); ++i)
+ for (const auto &p : PrivilegeManager::GetPrivileges())
{
- const Privilege &p = privs[i];
ListFormatter::ListEntry entry;
entry["Name"] = p.name;
entry["Description"] = Language::Translate(source.nc, p.desc.c_str());
@@ -816,8 +832,8 @@ class CommandCSLevels : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
else
{
@@ -847,13 +863,14 @@ class CommandCSLevels : public Command
}
};
-class CSAccess : public Module
+class CSAccess final
+ : public Module
{
AccessAccessProvider accessprovider;
CommandCSAccess commandcsaccess;
CommandCSLevels commandcslevels;
- public:
+public:
CSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
accessprovider(this), commandcsaccess(this), commandcslevels(this)
{
@@ -861,7 +878,7 @@ class CSAccess : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
defaultLevels.clear();
@@ -887,12 +904,12 @@ class CSAccess : public Module
}
}
- void OnCreateChan(ChannelInfo *ci) anope_override
+ void OnCreateChan(ChannelInfo *ci) override
{
reset_levels(ci);
}
- EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) anope_override
+ EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) override
{
if (group->ci == NULL)
return EVENT_CONTINUE;
diff --git a/modules/commands/cs_akick.cpp b/modules/chanserv/cs_akick.cpp
index ff93aa225..489b18772 100644
--- a/modules/commands/cs_akick.cpp
+++ b/modules/chanserv/cs_akick.cpp
@@ -11,7 +11,8 @@
#include "module.h"
-class CommandCSAKick : public Command
+class CommandCSAKick final
+ : public Command
{
void Enforce(CommandSource &source, ChannelInfo *ci)
{
@@ -96,10 +97,9 @@ class CommandCSAKick : public Command
/* Check excepts BEFORE we get this far */
if (ci->c)
{
- std::vector<Anope::string> modes = ci->c->GetModeList("EXCEPT");
- for (unsigned int i = 0; i < modes.size(); ++i)
+ for (const auto &mode : ci->c->GetModeList("EXCEPT"))
{
- if (Anope::Match(modes[i], mask))
+ if (Anope::Match(mode, mask))
{
source.Reply(CHAN_EXCEPTED, mask.c_str(), ci->name.c_str());
return;
@@ -129,10 +129,8 @@ class CommandCSAKick : public Command
{
/* Match against all currently online users with equal or
* higher access. - Viper */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u2] : UserListByNick)
{
- User *u2 = it->second;
-
AccessGroup nc_access = ci->AccessFor(nc), u_access = source.AccessFor(ci);
Entry entry_mask("", mask);
@@ -145,9 +143,9 @@ class CommandCSAKick : public Command
/* Match against the lastusermask of all nickalias's with equal
* or higher access. - Viper */
- for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
+ for (const auto &[_, na2] : *NickAliasList)
{
- na = it->second;
+ na = na2;
AccessGroup nc_access = ci->AccessFor(na->nc), u_access = source.AccessFor(ci);
if (na->nc && (na->nc == ci->GetFounder() || nc_access >= u_access))
@@ -206,19 +204,20 @@ class CommandCSAKick : public Command
/* Special case: is it a number/list? Only do search if it isn't. */
if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class AkickDelCallback : public NumberList
+ class AkickDelCallback final
+ : public NumberList
{
CommandSource &source;
ChannelInfo *ci;
Command *c;
- unsigned deleted;
+ unsigned deleted = 0;
AccessGroup ag;
- public:
- AkickDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), deleted(0), ag(source.AccessFor(ci))
+ public:
+ AkickDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), ag(source.AccessFor(ci))
{
}
- ~AkickDelCallback()
+ ~AkickDelCallback() override
{
if (!deleted)
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
@@ -228,7 +227,7 @@ class CommandCSAKick : public Command
source.Reply(_("Deleted %d entries from %s autokick list."), deleted, ci->name.c_str());
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > ci->GetAkickCount())
return;
@@ -283,17 +282,18 @@ class CommandCSAKick : public Command
if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class AkickListCallback : public NumberList
+ class AkickListCallback final
+ : public NumberList
{
ListFormatter &list;
ChannelInfo *ci;
- public:
+ public:
AkickListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci)
{
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > ci->GetAkickCount())
return;
@@ -311,7 +311,7 @@ class CommandCSAKick : public Command
lastused = UNKNOWN;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(number);
+ entry["Number"] = Anope::ToString(number);
if (akick->nc)
entry["Mask"] = akick->nc->display;
else
@@ -351,7 +351,7 @@ class CommandCSAKick : public Command
lastused = UNKNOWN;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
if (akick->nc)
entry["Mask"] = akick->nc->display;
else
@@ -373,8 +373,8 @@ class CommandCSAKick : public Command
source.Reply(_("Autokick list for %s:"), ci->name.c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of autokick list"));
}
@@ -428,7 +428,7 @@ class CommandCSAKick : public Command
source.Reply(_("Channel %s akick list has been cleared."), ci->name.c_str());
}
- public:
+public:
CommandCSAKick(Module *creator) : Command(creator, "chanserv/akick", 2, 4)
{
this->SetDesc(_("Maintain the AutoKick list"));
@@ -440,7 +440,7 @@ class CommandCSAKick : public Command
this->SetSyntax(_("\037channel\037 CLEAR"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string chan = params[0];
Anope::string cmd = params[1];
@@ -466,7 +466,7 @@ class CommandCSAKick : public Command
else if (!has_access)
source.Reply(ACCESS_DENIED);
else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && Anope::ReadOnly)
- source.Reply(_("Sorry, channel autokick list modification is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
else if (cmd.equals_ci("ADD"))
this->DoAdd(source, ci, params);
else if (cmd.equals_ci("DEL"))
@@ -485,7 +485,7 @@ class CommandCSAKick : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
BotInfo *bi = Config->GetClient("NickServ");
this->SendSyntax(source);
@@ -528,17 +528,18 @@ class CommandCSAKick : public Command
}
};
-class CSAKick : public Module
+class CSAKick final
+ : public Module
{
CommandCSAKick commandcsakick;
- public:
+public:
CSAKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsakick(this)
{
}
- EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
+ EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
if (!c->ci || c->MatchesList(u, "EXCEPT"))
return EVENT_CONTINUE;
diff --git a/modules/commands/cs_ban.cpp b/modules/chanserv/cs_ban.cpp
index 5dba33cee..9f2b691ef 100644
--- a/modules/commands/cs_ban.cpp
+++ b/modules/chanserv/cs_ban.cpp
@@ -13,17 +13,24 @@
static Module *me;
-class TempBan : public Timer
+class TempBan final
+ : public Timer
{
- private:
+private:
Anope::string channel;
Anope::string mask;
Anope::string mode;
- public:
- TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod) : Timer(me, seconds), channel(c->name), mask(banmask), mode(mod) { }
+public:
+ TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod)
+ : Timer(me, seconds)
+ , channel(c->name)
+ , mask(banmask)
+ , mode(mod)
+ {
+ }
- void Tick(time_t ctime) anope_override
+ void Tick() override
{
Channel *c = Channel::Find(this->channel);
if (c)
@@ -31,16 +38,17 @@ class TempBan : public Timer
}
};
-class CommandCSBan : public Command
+class CommandCSBan final
+ : public Command
{
- public:
+public:
CommandCSBan(Module *creator) : Command(creator, "chanserv/ban", 2, 4)
{
this->SetDesc(_("Bans a given nick or mask on a channel"));
this->SetSyntax(_("\037channel\037 [+\037expiry\037] {\037nick\037 | \037mask\037} [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Configuration::Block *block = Config->GetCommand(source);
const Anope::string &mode = block->Get<Anope::string>("mode", "BAN");
@@ -153,10 +161,10 @@ class CommandCSBan : public Command
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
{
signkickformat = signkickformat.replace_all_cs("%m", reason);
- c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
+ c->Kick(ci->WhoSends(), u2, signkickformat);
}
else
- c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
+ c->Kick(ci->WhoSends(), u2, reason);
}
}
}
@@ -208,7 +216,7 @@ class CommandCSBan : public Command
{
reason += " (Matches " + mask + ")";
signkickformat = signkickformat.replace_all_cs("%m", reason);
- c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
+ c->Kick(ci->WhoSends(), uc->user, signkickformat);
}
else
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
@@ -223,7 +231,7 @@ class CommandCSBan : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -237,11 +245,12 @@ class CommandCSBan : public Command
}
};
-class CSBan : public Module
+class CSBan final
+ : public Module
{
CommandCSBan commandcsban;
- public:
+public:
CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsban(this)
{
me = this;
diff --git a/modules/commands/cs_clone.cpp b/modules/chanserv/cs_clone.cpp
index 45b80187e..6f29a235c 100644
--- a/modules/commands/cs_clone.cpp
+++ b/modules/chanserv/cs_clone.cpp
@@ -12,18 +12,19 @@
#include "module.h"
#include "modules/bs_badwords.h"
-class CommandCSClone : public Command
+class CommandCSClone final
+ : public Command
{
- void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting)
+ static void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting)
{
if (ci->HasExt(setting))
target_ci->Extend<bool>(setting);
}
- void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ static void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
std::set<Anope::string> masks;
- unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
+ unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
unsigned count = 0;
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
@@ -44,6 +45,7 @@ class CommandCSClone : public Command
ChanAccess *newaccess = provider->Create();
newaccess->SetMask(taccess->Mask(), target_ci);
newaccess->creator = taccess->creator;
+ newaccess->description = taccess->description;
newaccess->last_seen = taccess->last_seen;
newaccess->created = taccess->created;
newaccess->AccessUnserialize(taccess->AccessSerialize());
@@ -56,7 +58,7 @@ class CommandCSClone : public Command
source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, ci->name.c_str(), target_ci->name.c_str());
}
- void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ static void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
target_ci->ClearAkick();
for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
@@ -71,7 +73,7 @@ class CommandCSClone : public Command
source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
- void CopyBadwords(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ static void CopyBadwords(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
*badwords = ci->Require<BadWords>("badwords");
@@ -96,13 +98,11 @@ class CommandCSClone : public Command
source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
- void CopyLevels(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ static void CopyLevels(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
{
- const Anope::map<int16_t> &cilevels = ci->GetLevelEntries();
-
- for (Anope::map<int16_t>::const_iterator it = cilevels.begin(); it != cilevels.end(); ++it)
+ for (const auto &[priv, level] : ci->GetLevelEntries())
{
- target_ci->SetLevel(it->first, it->second);
+ target_ci->SetLevel(priv, level);
}
source.Reply(_("All level entries from \002%s\002 have been cloned into \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
@@ -115,7 +115,7 @@ public:
this->SetSyntax(_("\037channel\037 \037target\037 [\037what\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &channel = params[0];
const Anope::string &target = params[1];
@@ -196,10 +196,10 @@ public:
target_ci->last_topic_setter = source.service->nick;
const Anope::string settings[] = { "NOAUTOOP", "CS_KEEP_MODES", "PEACE", "PERSIST", "RESTRICTED",
- "CS_SECURE", "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
+ "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
- for (unsigned int i = 0; i < sizeof(settings) / sizeof(Anope::string); ++i)
- CopySetting(ci, target_ci, settings[i]);
+ for (const auto &setting : settings)
+ CopySetting(ci, target_ci, setting);
CopyAccess(source, ci, target_ci);
CopyAkick(source, ci, target_ci);
@@ -235,7 +235,7 @@ public:
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clone " << (what.empty() ? "everything from it" : what) << " to " << target_ci->name;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -247,11 +247,12 @@ public:
}
};
-class CSClone : public Module
+class CSClone final
+ : public Module
{
CommandCSClone commandcsclone;
- public:
+public:
CSClone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsclone(this)
{
diff --git a/modules/commands/cs_drop.cpp b/modules/chanserv/cs_drop.cpp
index 7a205954b..fbde9fa5f 100644
--- a/modules/commands/cs_drop.cpp
+++ b/modules/chanserv/cs_drop.cpp
@@ -11,22 +11,28 @@
#include "module.h"
-class CommandCSDrop : public Command
+class CommandCSDrop final
+ : public Command
{
- public:
- CommandCSDrop(Module *creator) : Command(creator, "chanserv/drop", 1, 2)
+private:
+ PrimitiveExtensibleItem<Anope::string> dropcode;
+
+public:
+ CommandCSDrop(Module *creator)
+ : Command(creator, "chanserv/drop", 1, 2)
+ , dropcode(creator, "channel-dropcode")
{
this->SetDesc(_("Cancel the registration of a channel"));
- this->SetSyntax(_("\037channel\037 \037channel\037"));
+ this->SetSyntax(_("\037channel\037 [\037code\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
if (Anope::ReadOnly && !source.HasPriv("chanserv/administration"))
{
- source.Reply(_("Sorry, channel de-registration is temporarily disabled.")); // XXX: READ_ONLY_MODE?
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -37,22 +43,33 @@ class CommandCSDrop : public Command
return;
}
- if (params.size() < 2 || !chan.equals_ci(params[1]))
+ if ((ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && !source.HasCommand("chanserv/drop"))
{
- source.Reply(_("You must enter the channel name twice as a confirmation that you wish to drop \002%s\002."), chan.c_str());
+ source.Reply(ACCESS_DENIED);
return;
}
- if ((ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && !source.HasCommand("chanserv/drop"))
+ auto *code = dropcode.Get(ci);
+ if (params.size() < 2 || ((!code || !code->equals_ci(params[1])) && (!source.HasPriv("chanserv/drop/override") || params[1] != "OVERRIDE")))
{
- source.Reply(ACCESS_DENIED);
+ if (!code)
+ {
+ code = ci->Extend<Anope::string>("channel-dropcode");
+ *code = Anope::Random(15);
+ }
+
+ source.Reply(CONFIRM_DROP, ci->name.c_str(), source.service->GetQueryCommand().c_str(),
+ ci->name.c_str(), code->c_str());
return;
}
EventReturn MOD_RESULT;
FOREACH_RESULT(OnChanDrop, MOD_RESULT, (source, ci));
if (MOD_RESULT == EVENT_STOP)
+ {
+ dropcode.Unset(ci);
return;
+ }
bool override = (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER"));
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "(founder was: " << (ci->GetFounder() ? ci->GetFounder()->display : "none") << ")";
@@ -66,7 +83,7 @@ class CommandCSDrop : public Command
c->CheckModes();
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -77,15 +94,20 @@ class CommandCSDrop : public Command
source.Reply(_("Unregisters the named channel. Can only be used by\n"
"the \002channel founder\002."));
+ source.Reply(" ");
+ if (source.HasPriv("chanserv/drop/override"))
+ source.Reply(_("Additionally, Services Operators with the \037chanserv/drop/override\037 permission can\n"
+ "replace \037code\037 with \002OVERRIDE\002 to drop without a confirmation code."));
return true;
}
};
-class CSDrop : public Module
+class CSDrop final
+ : public Module
{
CommandCSDrop commandcsdrop;
- public:
+public:
CSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsdrop(this)
{
diff --git a/modules/commands/cs_enforce.cpp b/modules/chanserv/cs_enforce.cpp
index 55c97aad9..3b38b3a89 100644
--- a/modules/commands/cs_enforce.cpp
+++ b/modules/chanserv/cs_enforce.cpp
@@ -13,9 +13,10 @@
#include "module.h"
-class CommandCSEnforce : public Command
+class CommandCSEnforce final
+ : public Command
{
- private:
+private:
void DoSecureOps(CommandSource &source, ChannelInfo *ci)
{
bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify");
@@ -29,10 +30,8 @@ class CommandCSEnforce : public Command
bool hadsecureops = ci->HasExt("SECUREOPS");
ci->Extend<bool>("SECUREOPS");
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : ci->c->users)
{
- ChanUserContainer *uc = it->second;
-
ci->c->SetCorrectModes(uc->user, false);
}
@@ -48,9 +47,9 @@ class CommandCSEnforce : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce restricted";
std::vector<User *> users;
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+
+ for (const auto &[_, uc] : ci->c->users)
{
- ChanUserContainer *uc = it->second;
User *user = uc->user;
if (user->IsProtected())
@@ -60,14 +59,12 @@ class CommandCSEnforce : public Command
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
+ for (auto *user : users)
{
- User *user = users[i];
-
Anope::string mask = ci->GetIdealBan(user);
Anope::string reason = Language::Translate(user, _("RESTRICTED enforced by ")) + source.GetNick();
ci->c->SetMode(NULL, "BAN", mask);
- ci->c->Kick(NULL, user, "%s", reason.c_str());
+ ci->c->Kick(NULL, user, reason);
}
source.Reply(_("Restricted enforced on %s."), ci->name.c_str());
@@ -79,9 +76,8 @@ class CommandCSEnforce : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce registered only";
std::vector<User *> users;
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : ci->c->users)
{
- ChanUserContainer *uc = it->second;
User *user = uc->user;
if (user->IsProtected())
@@ -91,15 +87,13 @@ class CommandCSEnforce : public Command
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
+ for (auto *user : users)
{
- User *user = users[i];
-
Anope::string mask = ci->GetIdealBan(user);
Anope::string reason = Language::Translate(user, _("REGONLY enforced by ")) + source.GetNick();
if (!ci->c->HasMode("REGISTEREDONLY"))
ci->c->SetMode(NULL, "BAN", mask);
- ci->c->Kick(NULL, user, "%s", reason.c_str());
+ ci->c->Kick(NULL, user, reason);
}
source.Reply(_("Registered only enforced on %s."), ci->name.c_str());
@@ -111,27 +105,24 @@ class CommandCSEnforce : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce SSL only";
std::vector<User *> users;
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+ for (auto &[_, uc] : ci->c->users)
{
- ChanUserContainer *uc = it->second;
User *user = uc->user;
if (user->IsProtected())
continue;
- if (!user->HasMode("SSL") && !user->HasExt("ssl"))
+ if (!user->IsSecurelyConnected())
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
+ for (auto *user : users)
{
- User *user = users[i];
-
Anope::string mask = ci->GetIdealBan(user);
Anope::string reason = Language::Translate(user, _("SSLONLY enforced by ")) + source.GetNick();
if (!ci->c->HasMode("SSL"))
ci->c->SetMode(NULL, "BAN", mask);
- ci->c->Kick(NULL, user, "%s", reason.c_str());
+ ci->c->Kick(NULL, user, reason);
}
source.Reply(_("SSL only enforced on %s."), ci->name.c_str());
@@ -143,9 +134,8 @@ class CommandCSEnforce : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce bans";
std::vector<User *> users;
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : ci->c->users)
{
- ChanUserContainer *uc = it->second;
User *user = uc->user;
if (user->IsProtected())
@@ -155,12 +145,10 @@ class CommandCSEnforce : public Command
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
+ for (auto *user : users)
{
- User *user = users[i];
-
Anope::string reason = Language::Translate(user, _("BANS enforced by ")) + source.GetNick();
- ci->c->Kick(NULL, user, "%s", reason.c_str());
+ ci->c->Kick(NULL, user, reason);
}
source.Reply(_("Bans enforced on %s."), ci->name.c_str());
@@ -178,14 +166,8 @@ class CommandCSEnforce : public Command
return;
}
- int l;
- try
- {
- l = convertTo<int>(l_str);
- if (l < 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
+ auto l = Anope::Convert<int>(l_str, -1);
+ if (l < 0)
{
source.Reply(_("The limit on %s is not valid."), ci->name.c_str());
return;
@@ -210,25 +192,23 @@ class CommandCSEnforce : public Command
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
+ for (auto *user : users)
{
- User *user = users[i];
-
Anope::string reason = Language::Translate(user, _("LIMIT enforced by ")) + source.GetNick();
- ci->c->Kick(NULL, user, "%s", reason.c_str());
+ ci->c->Kick(NULL, user, reason);
}
- source.Reply(_("LIMIT enforced on %s, %d users removed."), ci->name.c_str(), users.size());
+ source.Reply(_("LIMIT enforced on %s, %zu users removed."), ci->name.c_str(), users.size());
}
- public:
+public:
CommandCSEnforce(Module *creator) : Command(creator, "chanserv/enforce", 2, 2)
{
this->SetDesc(_("Enforce various channel modes and set options"));
this->SetSyntax(_("\037channel\037 \037what\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &what = params.size() > 1 ? params[1] : "";
@@ -256,7 +236,7 @@ class CommandCSEnforce : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -277,11 +257,12 @@ class CommandCSEnforce : public Command
}
};
-class CSEnforce : public Module
+class CSEnforce final
+ : public Module
{
CommandCSEnforce commandcsenforce;
- public:
+public:
CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsenforce(this)
{
diff --git a/modules/commands/cs_entrymsg.cpp b/modules/chanserv/cs_entrymsg.cpp
index 8a84e9477..b1546428d 100644
--- a/modules/commands/cs_entrymsg.cpp
+++ b/modules/chanserv/cs_entrymsg.cpp
@@ -12,7 +12,9 @@
#include "module.h"
#include "modules/cs_entrymsg.h"
-struct EntryMsgImpl : EntryMsg, Serializable
+struct EntryMsgImpl final
+ : EntryMsg
+ , Serializable
{
EntryMsgImpl() : Serializable("EntryMsg")
{
@@ -26,24 +28,25 @@ struct EntryMsgImpl : EntryMsg, Serializable
this->when = ct;
}
- ~EntryMsgImpl();
+ ~EntryMsgImpl() override;
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["ci"] << this->chan;
- data["creator"] << this->creator;
- data["message"] << this->message;
- data.SetType("when", Serialize::Data::DT_INT); data["when"] << this->when;
+ data.Store("ci", this->chan);
+ data.Store("creator", this->creator);
+ data.Store("message", this->message);
+ data.Store("when", this->when);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
-struct EntryMessageListImpl : EntryMessageList
+struct EntryMessageListImpl final
+ : EntryMessageList
{
EntryMessageListImpl(Extensible *) { }
- EntryMsg* Create() anope_override
+ EntryMsg *Create() override
{
return new EntryMsgImpl();
}
@@ -65,7 +68,7 @@ EntryMsgImpl::~EntryMsgImpl()
}
-Serializable* EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sci, screator, smessage;
time_t swhen;
@@ -92,15 +95,16 @@ Serializable* EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data
data["when"] >> swhen;
- EntryMsgImpl *m = new EntryMsgImpl(ci, screator, smessage, swhen);
+ auto *m = new EntryMsgImpl(ci, screator, smessage, swhen);
(*messages)->push_back(m);
return m;
}
-class CommandEntryMessage : public Command
+class CommandEntryMessage final
+ : public Command
{
- private:
- void DoList(CommandSource &source, ChannelInfo *ci)
+private:
+ static void DoList(CommandSource &source, ChannelInfo *ci)
{
EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
@@ -119,7 +123,7 @@ class CommandEntryMessage : public Command
EntryMsg *msg = (*messages)->at(i);
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Creator"] = msg->creator;
entry["Created"] = Anope::strftime(msg->when, NULL, true);
entry["Message"] = msg->message;
@@ -128,8 +132,8 @@ class CommandEntryMessage : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of entry message list."));
}
@@ -158,21 +162,16 @@ class CommandEntryMessage : public Command
source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str());
else
{
- try
+ auto i = Anope::Convert<unsigned>(message, 0);
+ if (i > 0 && i <= (*messages)->size())
{
- unsigned i = convertTo<unsigned>(message);
- if (i > 0 && i <= (*messages)->size())
- {
- delete (*messages)->at(i - 1);
- if ((*messages)->empty())
- ci->Shrink<EntryMessageList>("entrymsg");
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
- source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
- }
- else
- throw ConvertException();
+ delete (*messages)->at(i - 1);
+ if ((*messages)->empty())
+ ci->Shrink<EntryMessageList>("entrymsg");
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
+ source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
}
- catch (const ConvertException &)
+ else
{
source.Reply(_("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str());
}
@@ -187,7 +186,7 @@ class CommandEntryMessage : public Command
source.Reply(_("Entry messages for \002%s\002 have been cleared."), ci->name.c_str());
}
- public:
+public:
CommandEntryMessage(Module *creator) : Command(creator, "chanserv/entrymsg", 2, 3)
{
this->SetDesc(_("Manage the channel's entry messages"));
@@ -197,7 +196,7 @@ class CommandEntryMessage : public Command
this->SetSyntax(_("\037channel\037 CLEAR"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (ci == NULL)
@@ -232,7 +231,7 @@ class CommandEntryMessage : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -260,28 +259,35 @@ class CommandEntryMessage : public Command
}
};
-class CSEntryMessage : public Module
+class CSEntryMessage final
+ : public Module
{
CommandEntryMessage commandentrymsg;
ExtensibleItem<EntryMessageListImpl> eml;
Serialize::Type entrymsg_type;
- public:
+public:
CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandentrymsg(this),
eml(this, "entrymsg"), entrymsg_type("EntryMsg", EntryMsgImpl::Unserialize)
{
}
- void OnJoinChannel(User *u, Channel *c) anope_override
+ void OnJoinChannel(User *u, Channel *c) override
{
if (u && c && c->ci && u->server->IsSynced())
{
EntryMessageList *messages = c->ci->GetExt<EntryMessageList>("entrymsg");
+ if (!messages)
+ return;
- if (messages != NULL)
- for (unsigned i = 0; i < (*messages)->size(); ++i)
- u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), (*messages)->at(i)->message.c_str());
+ for (const auto &message : *(*messages))
+ {
+ if (u->ShouldPrivmsg())
+ IRCD->SendContextPrivmsg(c->ci->WhoSends(), u, c, message->message);
+ else
+ IRCD->SendContextNotice(c->ci->WhoSends(), u, c, message->message);
+ }
}
}
};
diff --git a/modules/extra/stats/cs_fantasy_stats.cpp b/modules/chanserv/cs_fantasy_stats.cpp
index e5007af1e..eae70f116 100644
--- a/modules/extra/stats/cs_fantasy_stats.cpp
+++ b/modules/chanserv/cs_fantasy_stats.cpp
@@ -12,16 +12,17 @@
#include "module.h"
#include "modules/sql.h"
-class MySQLInterface : public SQL::Interface
+class MySQLInterface final
+ : public SQL::Interface
{
- public:
+public:
MySQLInterface(Module *o) : SQL::Interface(o) { }
- void OnResult(const SQL::Result &r) anope_override
+ void OnResult(const SQL::Result &r) override
{
}
- void OnError(const SQL::Result &r) anope_override
+ void OnError(const SQL::Result &r) override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
@@ -31,9 +32,10 @@ class MySQLInterface : public SQL::Interface
};
-class CommandCSStats : public Command
+class CommandCSStats final
+ : public Command
{
- public:
+public:
CommandCSStats(Module *creator) : Command (creator, "chanserv/stats", 0, 2)
{
this->SetDesc(_("Displays your Channel Stats"));
@@ -43,9 +45,10 @@ class CommandCSStats : public Command
void Execute(CommandSource &source, const std::vector<Anope::string> &params);
};
-class CommandCSGStats : public Command
+class CommandCSGStats final
+ : public Command
{
- public:
+public:
CommandCSGStats(Module *creator) : Command (creator, "chanserv/gstats", 0, 2)
{
this->SetDesc(_("Displays your Global Stats"));
@@ -58,14 +61,15 @@ class CommandCSGStats : public Command
class CSStats;
static CSStats *me;
-class CSStats : public Module
+class CSStats final
+ : public Module
{
CommandCSStats commandcsstats;
CommandCSGStats commandcsgstats;
ServiceReference<SQL::Provider> sql;
MySQLInterface sqlinterface;
Anope::string prefix;
- public:
+public:
CSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsstats(this), commandcsgstats(this), sql("", ""), sqlinterface(this)
{
@@ -73,16 +77,16 @@ class CSStats : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
- prefix = conf->GetModule("m_chanstats")->Get<const Anope::string>("prefix", "anope_");
- this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("m_chanstats")->Get<const Anope::string>("engine"));
+ prefix = conf->GetModule("chanstats")->Get<const Anope::string>("prefix", "anope_");
+ this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("chanstats")->Get<const Anope::string>("engine"));
}
SQL::Result RunQuery(const SQL::Query &query)
{
if (!this->sql)
- throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+ throw SQL::Exception("Unable to locate SQL reference, is mysql loaded and configured correctly?");
SQL::Result res = this->sql->RunQuery(query);
if (!res.GetError().empty())
diff --git a/modules/extra/stats/cs_fantasy_top.cpp b/modules/chanserv/cs_fantasy_top.cpp
index 4dad4c9c0..83cd6bee5 100644
--- a/modules/extra/stats/cs_fantasy_top.cpp
+++ b/modules/chanserv/cs_fantasy_top.cpp
@@ -12,16 +12,17 @@
#include "module.h"
#include "modules/sql.h"
-class MySQLInterface : public SQL::Interface
+class MySQLInterface final
+ : public SQL::Interface
{
- public:
+public:
MySQLInterface(Module *o) : SQL::Interface(o) { }
- void OnResult(const SQL::Result &r) anope_override
+ void OnResult(const SQL::Result &r) override
{
}
- void OnError(const SQL::Result &r) anope_override
+ void OnError(const SQL::Result &r) override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
@@ -30,9 +31,10 @@ class MySQLInterface : public SQL::Interface
}
};
-class CommandCSTop : public Command
+class CommandCSTop final
+ : public Command
{
- public:
+public:
CommandCSTop(Module *creator) : Command (creator, "chanserv/top", 0, 2)
{
this->SetDesc(_("Displays the top 3 users of a channel"));
@@ -42,9 +44,10 @@ class CommandCSTop : public Command
void Execute(CommandSource &source, const std::vector<Anope::string> &params);
};
-class CommandCSTop10 : public Command
+class CommandCSTop10 final
+ : public Command
{
- public:
+public:
CommandCSTop10(Module *creator) : Command (creator, "chanserv/top10", 0, 2)
{
this->SetDesc(_("Displays the top 10 users of a channel"));
@@ -54,9 +57,10 @@ class CommandCSTop10 : public Command
void Execute(CommandSource &source, const std::vector<Anope::string> &params);
};
-class CommandCSGTop : public Command
+class CommandCSGTop final
+ : public Command
{
- public:
+public:
CommandCSGTop(Module *creator) : Command (creator, "chanserv/gtop", 0, 1)
{
this->SetDesc(_("Displays the top 3 users of the network"));
@@ -65,9 +69,10 @@ class CommandCSGTop : public Command
void Execute(CommandSource &source, const std::vector<Anope::string> &params);
};
-class CommandCSGTop10 : public Command
+class CommandCSGTop10 final
+ : public Command
{
- public:
+public:
CommandCSGTop10(Module *creator) : Command (creator, "chanserv/gtop10", 0, 1)
{
this->SetDesc(_("Displays the top 10 users of the network"));
@@ -79,7 +84,8 @@ class CommandCSGTop10 : public Command
class CSTop;
static CSTop *me;
-class CSTop : public Module
+class CSTop final
+ : public Module
{
CommandCSTop commandcstop;
CommandCSGTop commandcsgtop;
@@ -89,7 +95,7 @@ class CSTop : public Module
MySQLInterface sqlinterface;
Anope::string prefix;
- public:
+public:
CSTop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcstop(this), commandcsgtop(this), commandcstop10(this), commandcsgtop10(this), sql("", ""),
sqlinterface(this)
@@ -98,16 +104,16 @@ class CSTop : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
- prefix = conf->GetModule("m_chanstats")->Get<const Anope::string>("prefix", "anope_");
- this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("m_chanstats")->Get<const Anope::string>("engine"));
+ prefix = conf->GetModule("chanstats")->Get<const Anope::string>("prefix", "anope_");
+ this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("chanstats")->Get<const Anope::string>("engine"));
}
SQL::Result RunQuery(const SQL::Query &query)
{
if (!this->sql)
- throw SQL::Exception("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
+ throw SQL::Exception("Unable to locate SQL reference, is mysql loaded and configured correctly?");
SQL::Result res = sql->RunQuery(query);
if (!res.GetError().empty())
@@ -149,7 +155,7 @@ class CSTop : public Module
source.Reply(_("Top %i of %s"), limit, (is_global ? "Network" : channel.c_str()));
for (int i = 0; i < res.Rows(); ++i)
{
- source.Reply(_("%2lu \002%-16s\002 letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"),
+ source.Reply(_("%2d \002%-16s\002 letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"),
i+1, res.Get(i, "nick").c_str(), res.Get(i, "letters").c_str(),
res.Get(i, "words").c_str(), res.Get(i, "line").c_str(),
res.Get(i, "smileys").c_str(), res.Get(i, "actions").c_str());
diff --git a/modules/commands/cs_flags.cpp b/modules/chanserv/cs_flags.cpp
index 08df06672..691319634 100644
--- a/modules/commands/cs_flags.cpp
+++ b/modules/chanserv/cs_flags.cpp
@@ -13,29 +13,28 @@
static std::map<Anope::string, char> defaultFlags;
-class FlagsChanAccess : public ChanAccess
+class FlagsChanAccess final
+ : public ChanAccess
{
- public:
+public:
std::set<char> flags;
FlagsChanAccess(AccessProvider *p) : ChanAccess(p)
{
}
- bool HasPriv(const Anope::string &priv) const anope_override
+ bool HasPriv(const Anope::string &priv) const override
{
std::map<Anope::string, char>::iterator it = defaultFlags.find(priv);
- if (it != defaultFlags.end() && this->flags.count(it->second) > 0)
- return true;
- return false;
+ return it != defaultFlags.end() && this->flags.count(it->second) > 0;
}
- Anope::string AccessSerialize() const anope_override
+ Anope::string AccessSerialize() const override
{
return Anope::string(this->flags.begin(), this->flags.end());
}
- void AccessUnserialize(const Anope::string &data) anope_override
+ void AccessUnserialize(const Anope::string &data) override
{
for (unsigned i = data.length(); i > 0; --i)
this->flags.insert(data[i - 1]);
@@ -48,9 +47,9 @@ class FlagsChanAccess : public ChanAccess
std::set<char> buffer;
- for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it)
- if (access->HasPriv(it->first))
- buffer.insert(it->second);
+ for (auto &[priv, flag] : defaultFlags)
+ if (access->HasPriv(priv))
+ buffer.insert(flag);
if (buffer.empty())
return "(none)";
@@ -59,9 +58,10 @@ class FlagsChanAccess : public ChanAccess
}
};
-class FlagsAccessProvider : public AccessProvider
+class FlagsAccessProvider final
+ : public AccessProvider
{
- public:
+public:
static FlagsAccessProvider *ap;
FlagsAccessProvider(Module *o) : AccessProvider(o, "access/flags")
@@ -69,16 +69,17 @@ class FlagsAccessProvider : public AccessProvider
ap = this;
}
- ChanAccess *Create() anope_override
+ ChanAccess *Create() override
{
return new FlagsChanAccess(this);
}
};
-FlagsAccessProvider* FlagsAccessProvider::ap;
+FlagsAccessProvider *FlagsAccessProvider::ap;
-class CommandCSFlags : public Command
+class CommandCSFlags final
+ : public Command
{
- void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags)
+ void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags, Anope::string description)
{
if (flags.empty())
{
@@ -120,11 +121,21 @@ class CommandCSFlags : public Command
source.Reply(_("Masks and unregistered users may not be on access lists."));
return;
}
+ else if (na && na->nc->HasExt("NEVEROP"))
+ {
+ source.Reply(_("\002%s\002 does not wish to be added to channel access lists."),
+ na->nc->display.c_str());
+ return;
+ }
else if (mask.find_first_of("!*@") == Anope::string::npos && !na)
{
User *targ = User::Find(mask, true);
if (targ != NULL)
+ {
mask = "*!*@" + targ->GetDisplayedHost();
+ if (description.empty())
+ description = targ->nick;
+ }
else
{
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
@@ -168,7 +179,7 @@ class CommandCSFlags : public Command
}
}
- unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
+ unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
if (access_max && ci->GetDeepAccessCount() >= access_max)
{
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
@@ -189,14 +200,14 @@ class CommandCSFlags : public Command
add = false;
break;
case '*':
- for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it)
+ for (const auto &[priv, flag] : defaultFlags)
{
- bool has = current_flags.count(it->second);
+ bool has = current_flags.count(flag);
// If we are adding a flag they already have or removing one they don't have, don't bother
if (add == has)
continue;
- if (!u_access.HasPriv(it->first) && !u_access.founder)
+ if (!u_access.HasPriv(priv) && !u_access.founder)
{
if (source.HasPriv("chanserv/access/modify"))
override = true;
@@ -205,9 +216,9 @@ class CommandCSFlags : public Command
}
if (add)
- current_flags.insert(it->second);
+ current_flags.insert(flag);
else
- current_flags.erase(it->second);
+ current_flags.erase(flag);
}
break;
default:
@@ -218,11 +229,11 @@ class CommandCSFlags : public Command
i = flags.length();
}
- for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it)
+ for (const auto &[priv, flag] : defaultFlags)
{
- if (f != it->second)
+ if (f != flag)
continue;
- else if (!u_access.HasPriv(it->first) && !u_access.founder)
+ else if (!u_access.HasPriv(priv) && !u_access.founder)
{
if (source.HasPriv("chanserv/access/modify"))
override = true;
@@ -262,7 +273,8 @@ class CommandCSFlags : public Command
return;
FlagsChanAccess *access = anope_dynamic_static_cast<FlagsChanAccess *>(provider->Create());
access->SetMask(mask, ci);
- access->creator = source.GetNick();
+ access->creator = source.GetNick();
+ access->description = current ? current->description : description;
access->last_seen = current ? current->last_seen : 0;
access->created = Anope::CurTime;
access->flags = current_flags;
@@ -286,7 +298,7 @@ class CommandCSFlags : public Command
source.Reply(_("Flags for \002%s\002 on %s set to +\002%s\002"), access->Mask().c_str(), ci->name.c_str(), access->AccessSerialize().c_str());
}
- void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
+ static void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
const Anope::string &arg = params.size() > 2 ? params[2] : "";
@@ -298,7 +310,7 @@ class CommandCSFlags : public Command
ListFormatter list(source.GetAccount());
- list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Flags")).AddColumn(_("Creator")).AddColumn(_("Created"));
+ list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Flags")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Description"));
unsigned count = 0;
for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i)
@@ -314,7 +326,7 @@ class CommandCSFlags : public Command
for (size_t j = 1; j < arg.length(); ++j)
if (flags.find(arg[j]) == Anope::string::npos)
pass = false;
- if (pass == false)
+ if (!pass)
continue;
}
else if (!Anope::Match(access->Mask(), arg))
@@ -323,11 +335,12 @@ class CommandCSFlags : public Command
ListFormatter::ListEntry entry;
++count;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Mask"] = access->Mask();
entry["Flags"] = flags;
entry["Creator"] = access->creator;
entry["Created"] = Anope::strftime(access->created, source.nc, true);
+ entry["Description"] = access->description;
list.AddEntry(entry);
}
@@ -339,8 +352,8 @@ class CommandCSFlags : public Command
list.Process(replies);
source.Reply(_("Flags list for %s"), ci->name.c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
if (count == ci->GetAccessCount())
source.Reply(_("End of access list."));
else
@@ -367,16 +380,16 @@ class CommandCSFlags : public Command
return;
}
- public:
- CommandCSFlags(Module *creator) : Command(creator, "chanserv/flags", 1, 4)
+public:
+ CommandCSFlags(Module *creator) : Command(creator, "chanserv/flags", 1, 5)
{
this->SetDesc(_("Modify the list of privileged users"));
- this->SetSyntax(_("\037channel\037 [MODIFY] \037mask\037 \037changes\037"));
+ this->SetSyntax(_("\037channel\037 [MODIFY] \037mask\037 \037changes\037 [\037description\037]"));
this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | +\037flags\037]"));
this->SetSyntax(_("\037channel\037 CLEAR"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
const Anope::string &cmd = params.size() > 1 ? params[1] : "";
@@ -402,30 +415,32 @@ class CommandCSFlags : public Command
if (!has_access)
source.Reply(ACCESS_DENIED);
else if (Anope::ReadOnly && !is_list)
- source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
else if (is_list)
this->DoList(source, ci, params);
else if (cmd.equals_ci("CLEAR"))
this->DoClear(source, ci);
else
{
- Anope::string mask, flags;
+ Anope::string mask, flags, description;
if (cmd.equals_ci("MODIFY"))
{
mask = params.size() > 2 ? params[2] : "";
flags = params.size() > 3 ? params[3] : "";
+ description = params.size() > 4 ? params[4] : "";
}
else
{
mask = cmd;
flags = params.size() > 2 ? params[2] : "";
+ description = params.size() > 3 ? params[3] : "";
}
- this->DoModify(source, ci, mask, flags);
+ this->DoModify(source, ci, mask, flags, description);
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -450,27 +465,28 @@ class CommandCSFlags : public Command
typedef std::multimap<char, Anope::string, ci::less> reverse_map;
reverse_map reverse;
- for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it)
- reverse.insert(std::make_pair(it->second, it->first));
+ for (auto &[priv, flag] : defaultFlags)
+ reverse.emplace(flag, priv);
- for (reverse_map::iterator it = reverse.begin(), it_end = reverse.end(); it != it_end; ++it)
+ for (auto &[flag, priv] : reverse)
{
- Privilege *p = PrivilegeManager::FindPrivilege(it->second);
+ Privilege *p = PrivilegeManager::FindPrivilege(priv);
if (p == NULL)
continue;
- source.Reply(" %c - %s", it->first, Language::Translate(source.nc, p->desc.c_str()));
+ source.Reply(" %c - %s", flag, Language::Translate(source.nc, p->desc.c_str()));
}
return true;
}
};
-class CSFlags : public Module
+class CSFlags final
+ : public Module
{
FlagsAccessProvider accessprovider;
CommandCSFlags commandcsflags;
- public:
+public:
CSFlags(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
accessprovider(this), commandcsflags(this)
{
@@ -478,7 +494,7 @@ class CSFlags : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
defaultFlags.clear();
diff --git a/modules/commands/cs_getkey.cpp b/modules/chanserv/cs_getkey.cpp
index 1fb602ef7..21e58b11d 100644
--- a/modules/commands/cs_getkey.cpp
+++ b/modules/chanserv/cs_getkey.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandCSGetKey : public Command
+class CommandCSGetKey final
+ : public Command
{
- public:
+public:
CommandCSGetKey(Module *creator) : Command(creator, "chanserv/getkey", 1, 1)
{
this->SetDesc(_("Returns the key of the given channel"));
this->SetSyntax(_("\037channel\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
@@ -50,7 +51,7 @@ class CommandCSGetKey : public Command
source.Reply(_("Key for channel \002%s\002 is \002%s\002."), chan.c_str(), key.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -59,11 +60,12 @@ class CommandCSGetKey : public Command
}
};
-class CSGetKey : public Module
+class CSGetKey final
+ : public Module
{
CommandCSGetKey commandcsgetkey;
- public:
+public:
CSGetKey(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsgetkey(this)
{
diff --git a/modules/commands/cs_info.cpp b/modules/chanserv/cs_info.cpp
index 99bbb912e..c1200aa3e 100644
--- a/modules/commands/cs_info.cpp
+++ b/modules/chanserv/cs_info.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandCSInfo : public Command
+class CommandCSInfo final
+ : public Command
{
- public:
+public:
CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2)
{
this->SetDesc(_("Lists information about the specified registered channel"));
@@ -21,7 +22,7 @@ class CommandCSInfo : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
@@ -57,7 +58,7 @@ class CommandCSInfo : public Command
if (show_all)
{
- info[_("Ban type")] = stringify(ci->bantype);
+ info[_("Ban type")] = Anope::ToString(ci->bantype);
}
FOREACH_MOD(OnChanInfo, (source, ci, info, show_all));
@@ -65,11 +66,11 @@ class CommandCSInfo : public Command
std::vector<Anope::string> replies;
info.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -83,11 +84,12 @@ class CommandCSInfo : public Command
}
};
-class CSInfo : public Module
+class CSInfo final
+ : public Module
{
CommandCSInfo commandcsinfo;
- public:
+public:
CSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsinfo(this)
{
diff --git a/modules/commands/cs_invite.cpp b/modules/chanserv/cs_invite.cpp
index ad5205e83..1d36c0375 100644
--- a/modules/commands/cs_invite.cpp
+++ b/modules/chanserv/cs_invite.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandCSInvite : public Command
+class CommandCSInvite final
+ : public Command
{
- public:
+public:
CommandCSInvite(Module *creator) : Command(creator, "chanserv/invite", 1, 3)
{
this->SetDesc(_("Invites you or an optionally specified nick into a channel"));
this->SetSyntax(_("\037channel\037 [\037nick\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
@@ -84,7 +85,7 @@ class CommandCSInvite : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -97,11 +98,12 @@ class CommandCSInvite : public Command
}
};
-class CSInvite : public Module
+class CSInvite final
+ : public Module
{
CommandCSInvite commandcsinvite;
- public:
+public:
CSInvite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsinvite(this)
{
diff --git a/modules/commands/cs_kick.cpp b/modules/chanserv/cs_kick.cpp
index ea9dd6c2e..dfcd2995c 100644
--- a/modules/commands/cs_kick.cpp
+++ b/modules/chanserv/cs_kick.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandCSKick : public Command
+class CommandCSKick final
+ : public Command
{
- public:
+public:
CommandCSKick(Module *creator) : Command(creator, "chanserv/kick", 2, 3)
{
this->SetDesc(_("Kicks a specified nick from a channel"));
@@ -21,7 +22,7 @@ class CommandCSKick : public Command
this->SetSyntax(_("\037channel\037 \037mask\037 [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
const Anope::string &target = params[1];
@@ -71,10 +72,10 @@ class CommandCSKick : public Command
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
{
signkickformat = signkickformat.replace_all_cs("%m", reason);
- c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
+ c->Kick(ci->WhoSends(), u2, signkickformat);
}
else
- c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
+ c->Kick(ci->WhoSends(), u2, reason);
}
}
else if (u_access.HasPriv("FOUNDER"))
@@ -105,7 +106,7 @@ class CommandCSKick : public Command
{
reason += " (Matches " + mask + ")";
signkickformat = signkickformat.replace_all_cs("%m", reason);
- c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
+ c->Kick(ci->WhoSends(), uc->user, signkickformat);
}
else
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
@@ -121,7 +122,7 @@ class CommandCSKick : public Command
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -133,11 +134,12 @@ class CommandCSKick : public Command
}
};
-class CSKick : public Module
+class CSKick final
+ : public Module
{
CommandCSKick commandcskick;
- public:
+public:
CSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcskick(this)
{
diff --git a/modules/commands/cs_list.cpp b/modules/chanserv/cs_list.cpp
index f2126ff6b..429b87d4d 100644
--- a/modules/commands/cs_list.cpp
+++ b/modules/chanserv/cs_list.cpp
@@ -12,16 +12,17 @@
#include "module.h"
#include "modules/cs_mode.h"
-class CommandCSList : public Command
+class CommandCSList final
+ : public Command
{
- public:
+public:
CommandCSList(Module *creator) : Command(creator, "chanserv/list", 1, 2)
{
this->SetDesc(_("Lists all registered channels matching the given pattern"));
this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string pattern = params[0];
unsigned nchans;
@@ -35,12 +36,10 @@ class CommandCSList : public Command
sepstream(pattern.substr(1), '-').GetToken(n1, 0);
sepstream(pattern, '-').GetToken(n2, 1);
- try
- {
- from = convertTo<int>(n1);
- to = convertTo<int>(n2);
- }
- catch (const ConvertException &)
+ auto num1 = Anope::TryConvert<int>(n1);
+ auto num2 = Anope::TryConvert<int>(n2);
+
+ if (!num1.has_value() || !num2.has_value())
{
source.Reply(LIST_INCORRECT_RANGE);
source.Reply(_("To search for channels starting with #, search for the channel\n"
@@ -48,6 +47,8 @@ class CommandCSList : public Command
return;
}
+ from = num1.value();
+ to = num2.value();
pattern = "*";
}
@@ -75,13 +76,11 @@ class CommandCSList : public Command
list.AddColumn(_("Name")).AddColumn(_("Description"));
Anope::map<ChannelInfo *> ordered_map;
- for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
- ordered_map[it->first] = it->second;
+ for (const auto &[cname, ci] : *RegisteredChannelList)
+ ordered_map[cname] = ci;
- for (Anope::map<ChannelInfo *>::const_iterator it = ordered_map.begin(), it_end = ordered_map.end(); it != it_end; ++it)
+ for (const auto &[_, ci] : ordered_map)
{
- const ChannelInfo *ci = it->second;
-
if (!is_servadmin)
{
if (ci->HasExt("CS_PRIVATE") || ci->HasExt("CS_SUSPENDED"))
@@ -124,13 +123,13 @@ class CommandCSList : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of list - %d/%d matches shown."), nchans > listmax ? listmax : nchans, nchans);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -172,16 +171,17 @@ class CommandCSList : public Command
}
};
-class CommandCSSetPrivate : public Command
+class CommandCSSetPrivate final
+ : public Command
{
- public:
+public:
CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Hide channel from the LIST command"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -225,7 +225,7 @@ class CommandCSSetPrivate : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -240,20 +240,21 @@ class CommandCSSetPrivate : public Command
}
};
-class CSList : public Module
+class CSList final
+ : public Module
{
CommandCSList commandcslist;
CommandCSSetPrivate commandcssetprivate;
SerializableExtensibleItem<bool> priv;
- public:
+public:
CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcslist(this), commandcssetprivate(this), priv(this, "CS_PRIVATE")
{
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) override
{
if (!show_all)
return;
diff --git a/modules/commands/cs_log.cpp b/modules/chanserv/cs_log.cpp
index 62ddde2aa..f3a32daed 100644
--- a/modules/commands/cs_log.cpp
+++ b/modules/chanserv/cs_log.cpp
@@ -12,13 +12,15 @@
#include "module.h"
#include "modules/cs_log.h"
-struct LogSettingImpl : LogSetting, Serializable
+struct LogSettingImpl final
+ : LogSetting
+ , Serializable
{
LogSettingImpl() : Serializable("LogSetting")
{
}
- ~LogSettingImpl()
+ ~LogSettingImpl() override
{
ChannelInfo *ci = ChannelInfo::Find(chan);
if (ci)
@@ -33,19 +35,19 @@ struct LogSettingImpl : LogSetting, Serializable
}
}
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["ci"] << chan;
- data["service_name"] << service_name;
- data["command_service"] << command_service;
- data["command_name"] << command_name;
- data["method"] << method;
- data["extra"] << extra;
- data["creator"] << creator;
- data.SetType("created", Serialize::Data::DT_INT); data["created"] << created;
+ data.Store("ci", chan);
+ data.Store("service_name", service_name);
+ data.Store("command_service", command_service);
+ data.Store("command_name", command_name);
+ data.Store("method", method);
+ data.Store("extra", extra);
+ data.Store("creator", creator);
+ data.Store("created", created);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sci;
data["ci"] >> sci;
@@ -77,11 +79,12 @@ struct LogSettingImpl : LogSetting, Serializable
}
};
-struct LogSettingsImpl : LogSettings
+struct LogSettingsImpl final
+ : LogSettings
{
LogSettingsImpl(Extensible *) { }
- ~LogSettingsImpl()
+ ~LogSettingsImpl() override
{
for (iterator it = (*this)->begin(); it != (*this)->end();)
{
@@ -91,13 +94,14 @@ struct LogSettingsImpl : LogSettings
}
}
- LogSetting *Create() anope_override
+ LogSetting *Create() override
{
return new LogSettingImpl();
}
};
-class CommandCSLog : public Command
+class CommandCSLog final
+ : public Command
{
public:
CommandCSLog(Module *creator) : Command(creator, "chanserv/log", 1, 4)
@@ -107,7 +111,7 @@ public:
this->SetSyntax(_("\037channel\037 \037command\037 \037method\037 [\037status\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &channel = params[0];
@@ -131,7 +135,7 @@ public:
const LogSetting *log = (*ls)->at(i);
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ 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;
@@ -144,8 +148,8 @@ public:
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
else if (params.size() > 2)
@@ -199,12 +203,14 @@ public:
return;
}
- for (unsigned i = 0; i < extra.length(); ++i)
- if (ModeManager::GetStatusChar(extra[i]) == 0)
+ for (auto chr : extra)
+ {
+ if (ModeManager::GetStatusChar(chr) == 0)
{
- source.Reply(_("%c is an unknown status mode."), extra[i]);
+ source.Reply(_("%c is an unknown status mode."), chr);
return;
}
+ }
bool override = !source.AccessFor(ci).HasPriv("SET");
@@ -230,7 +236,7 @@ public:
}
}
- LogSetting *log = new LogSettingImpl();
+ auto *log = new LogSettingImpl();
log->chan = ci->name;
log->service_name = service_name;
if (bi)
@@ -251,7 +257,7 @@ public:
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -279,21 +285,22 @@ public:
}
};
-class CSLog : public Module
+class CSLog final
+ : public Module
{
ServiceReference<MemoServService> MSService;
CommandCSLog commandcslog;
ExtensibleItem<LogSettingsImpl> logsettings;
Serialize::Type logsetting_type;
- struct LogDefault
+ struct LogDefault final
{
Anope::string service, command, method;
};
std::vector<LogDefault> defaults;
- public:
+public:
CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
MSService("MemoServService", "MemoServ"), commandcslog(this),
logsettings(this, "logsettings"), logsetting_type("LogSetting", LogSettingImpl::Unserialize)
@@ -301,7 +308,7 @@ class CSLog : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
defaults.clear();
@@ -320,17 +327,15 @@ class CSLog : public Module
}
}
- void OnChanRegistered(ChannelInfo *ci) anope_override
+ void OnChanRegistered(ChannelInfo *ci) override
{
if (defaults.empty())
return;
LogSettings *ls = logsettings.Require(ci);
- for (unsigned i = 0; i < defaults.size(); ++i)
+ for (auto &d : defaults)
{
- LogDefault &d = defaults[i];
-
- LogSetting *log = new LogSettingImpl();
+ auto *log = new LogSettingImpl();
log->chan = ci->name;
if (!d.service.empty())
@@ -353,18 +358,17 @@ class CSLog : public Module
}
}
- void OnLog(Log *l) anope_override
+ void OnLog(Log *l) override
{
if (l->type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced())
return;
LogSettings *ls = logsettings.Get(l->ci);
if (ls)
- for (unsigned i = 0; i < (*ls)->size(); ++i)
+ {
+ for (auto *log : *(*ls))
{
- const LogSetting *log = (*ls)->at(i);
-
- /* wrong command */
+ /* wrong command */
if (log->service_name != l->c->name)
continue;
@@ -387,12 +391,13 @@ class CSLog : public Module
/* Sending a channel message or notice in response to a fantasy command */;
else if (log->method.equals_ci("MESSAGE") && l->ci->c)
{
- IRCD->SendPrivmsg(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str());
+ IRCD->SendPrivmsg(l->ci->WhoSends(), log->extra + l->ci->c->name, buffer);
l->ci->WhoSends()->lastmsg = Anope::CurTime;
}
else if (log->method.equals_ci("NOTICE") && l->ci->c)
- IRCD->SendNotice(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str());
+ IRCD->SendNotice(l->ci->WhoSends(), log->extra + l->ci->c->name, buffer);
}
+ }
}
};
diff --git a/modules/commands/cs_mode.cpp b/modules/chanserv/cs_mode.cpp
index c168d29a6..47e2b84ad 100644
--- a/modules/commands/cs_mode.cpp
+++ b/modules/chanserv/cs_mode.cpp
@@ -12,13 +12,15 @@
#include "module.h"
#include "modules/cs_mode.h"
-struct ModeLockImpl : ModeLock, Serializable
+struct ModeLockImpl final
+ : ModeLock
+ , Serializable
{
ModeLockImpl() : Serializable("ModeLock")
{
}
- ~ModeLockImpl()
+ ~ModeLockImpl() override
{
ChannelInfo *chan = ChannelInfo::Find(ci);
if (chan)
@@ -29,11 +31,12 @@ struct ModeLockImpl : ModeLock, Serializable
}
}
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
-struct ModeLocksImpl : ModeLocks
+struct ModeLocksImpl final
+ : ModeLocks
{
Serialize::Reference<ChannelInfo> ci;
Serialize::Checker<ModeList> mlocks;
@@ -42,26 +45,23 @@ struct ModeLocksImpl : ModeLocks
{
}
- ~ModeLocksImpl()
+ ~ModeLocksImpl() override
{
ModeList modelist;
mlocks->swap(modelist);
- for (ModeList::iterator it = modelist.begin(); it != modelist.end(); ++it)
+ for (auto *ml : modelist)
{
- ModeLock *ml = *it;
delete ml;
}
}
- bool HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const anope_override
+ bool HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const override
{
if (!mode)
return false;
- for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ for (auto *ml : *this->mlocks)
{
- const ModeLock *ml = *it;
-
if (ml->name == mode->name && ml->set == status && ml->param == param)
return true;
}
@@ -69,7 +69,7 @@ struct ModeLocksImpl : ModeLocks
return false;
}
- bool SetMLock(ChannelMode *mode, bool status, const Anope::string &param, Anope::string setter, time_t created = Anope::CurTime) anope_override
+ bool SetMLock(ChannelMode *mode, bool status, const Anope::string &param, Anope::string setter, time_t created = Anope::CurTime) override
{
if (!mode)
return false;
@@ -79,7 +79,7 @@ struct ModeLocksImpl : ModeLocks
if (setter.empty())
setter = ci->GetFounder() ? ci->GetFounder()->display : "Unknown";
- ModeLock *ml = new ModeLockImpl();
+ auto *ml = new ModeLockImpl();
ml->ci = ci->name;
ml->set = status;
ml->name = mode->name;
@@ -99,15 +99,13 @@ struct ModeLocksImpl : ModeLocks
return true;
}
- bool RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param = "") anope_override
+ bool RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param = "") override
{
if (!mode)
return false;
- for (ModeList::iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ for (auto *m : *this->mlocks)
{
- ModeLock *m = *it;
-
if (m->name == mode->name)
{
// For list or status modes, we must check the parameter
@@ -128,44 +126,41 @@ struct ModeLocksImpl : ModeLocks
return false;
}
- void RemoveMLock(ModeLock *mlock) anope_override
+ void RemoveMLock(ModeLock *mlock) override
{
ModeList::iterator it = std::find(this->mlocks->begin(), this->mlocks->end(), mlock);
if (it != this->mlocks->end())
this->mlocks->erase(it);
}
- void ClearMLock() anope_override
+ void ClearMLock() override
{
ModeList ml;
this->mlocks->swap(ml);
- for (unsigned i = 0; i < ml.size(); ++i)
- delete ml[i];
+ for (const auto *lock : ml)
+ delete lock;
}
- const ModeList &GetMLock() const anope_override
+ const ModeList &GetMLock() const override
{
return this->mlocks;
}
- std::list<ModeLock *> GetModeLockList(const Anope::string &name) anope_override
+ std::list<ModeLock *> GetModeLockList(const Anope::string &name) override
{
std::list<ModeLock *> mlist;
- for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ for (auto *m : *this->mlocks)
{
- ModeLock *m = *it;
- if (m->name == name)
+ if (m->name == name)
mlist.push_back(m);
}
return mlist;
}
- const ModeLock *GetMLock(const Anope::string &mname, const Anope::string &param = "") anope_override
+ const ModeLock *GetMLock(const Anope::string &mname, const Anope::string &param = "") override
{
- for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ for (auto *m : *this->mlocks)
{
- ModeLock *m = *it;
-
if (m->name == mname && m->param == param)
return m;
}
@@ -173,13 +168,12 @@ struct ModeLocksImpl : ModeLocks
return NULL;
}
- Anope::string GetMLockAsString(bool complete) const anope_override
+ Anope::string GetMLockAsString(bool complete) const override
{
Anope::string pos = "+", neg = "-", params;
- for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ for (auto *ml : *this->mlocks)
{
- const ModeLock *ml = *it;
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
if (!cm || cm->type == MODE_LIST || cm->type == MODE_STATUS)
@@ -202,7 +196,7 @@ struct ModeLocksImpl : ModeLocks
return pos + neg + params;
}
- void Check() anope_override
+ void Check() override
{
if (this->mlocks->empty())
ci->Shrink<ModeLocks>("modelocks");
@@ -211,15 +205,15 @@ struct ModeLocksImpl : ModeLocks
void ModeLockImpl::Serialize(Serialize::Data &data) const
{
- data["ci"] << this->ci;
- data["set"] << this->set;
- data["name"] << this->name;
- data["param"] << this->param;
- data["setter"] << this->setter;
- data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
+ data.Store("ci", this->ci);
+ data.Store("set", this->set);
+ data.Store("name", this->name);
+ data.Store("param", this->param);
+ data.Store("setter", this->setter);
+ data.Store("created", this->created);
}
-Serializable* ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sci;
@@ -250,9 +244,10 @@ Serializable* ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data
return ml;
}
-class CommandCSMode : public Command
+class CommandCSMode final
+ : public Command
{
- bool CanSet(CommandSource &source, ChannelInfo *ci, ChannelMode *cm, bool self)
+ static bool CanSet(CommandSource &source, ChannelInfo *ci, ChannelMode *cm, bool self)
{
if (!ci || !cm || cm->type != MODE_STATUS)
return false;
@@ -281,9 +276,8 @@ class CommandCSMode : public Command
if (subcommand.equals_ci("SET"))
{
const ModeLocks::ModeList mlocks = modelocks->GetMLock();
- for (ModeLocks::ModeList::const_iterator it = mlocks.begin(); it != mlocks.end(); ++it)
+ for (auto *ml : mlocks)
{
- const ModeLock *ml = *it;
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
if (cm && cm->CanSet(source.GetUser()))
modelocks->RemoveMLock(cm, ml->set, ml->param);
@@ -299,9 +293,9 @@ class CommandCSMode : public Command
int adding = 1;
bool needreply = true;
- for (size_t i = 0; i < modes.length(); ++i)
+ for (auto mode : modes)
{
- switch (modes[i])
+ switch (mode)
{
case '+':
adding = 1;
@@ -311,15 +305,15 @@ class CommandCSMode : public Command
break;
default:
needreply = false;
- ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
if (!cm)
{
- source.Reply(_("Unknown mode character %c ignored."), modes[i]);
+ source.Reply(_("Unknown mode character %c ignored."), mode);
break;
}
else if (u && !cm->CanSet(u))
{
- source.Reply(_("You may not (un)lock mode %c."), modes[i]);
+ source.Reply(_("You may not (un)lock mode %c."), mode);
break;
}
@@ -342,7 +336,7 @@ class CommandCSMode : public Command
continue;
}
- if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
+ if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "50"))
{
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
continue;
@@ -391,9 +385,9 @@ class CommandCSMode : public Command
int adding = 1;
bool needreply = true;
- for (size_t i = 0; i < modes.length(); ++i)
+ for (auto mode : modes)
{
- switch (modes[i])
+ switch (mode)
{
case '+':
adding = 1;
@@ -403,15 +397,15 @@ class CommandCSMode : public Command
break;
default:
needreply = false;
- ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
if (!cm)
{
- source.Reply(_("Unknown mode character %c ignored."), modes[i]);
+ source.Reply(_("Unknown mode character %c ignored."), mode);
break;
}
else if (u && !cm->CanSet(u))
{
- source.Reply(_("You may not (un)lock mode %c."), modes[i]);
+ source.Reply(_("You may not (un)lock mode %c."), mode);
break;
}
@@ -448,9 +442,8 @@ class CommandCSMode : public Command
ListFormatter list(source.GetAccount());
list.AddColumn(_("Mode")).AddColumn(_("Param")).AddColumn(_("Creator")).AddColumn(_("Created"));
- for (ModeLocks::ModeList::const_iterator it = mlocks.begin(), it_end = mlocks.end(); it != it_end; ++it)
+ for (auto *ml : mlocks)
{
- const ModeLock *ml = *it;
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
if (!cm)
continue;
@@ -468,8 +461,8 @@ class CommandCSMode : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
else
@@ -489,9 +482,9 @@ class CommandCSMode : public Command
bool override = !source.AccessFor(ci).HasPriv("MODE") && source.HasPriv("chanserv/administration");
int adding = -1;
- for (size_t i = 0; i < modes.length(); ++i)
+ for (auto mode : modes)
{
- switch (modes[i])
+ switch (mode)
{
case '+':
adding = 1;
@@ -521,7 +514,7 @@ class CommandCSMode : public Command
default:
if (adding == -1)
break;
- ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
if (!cm || (u && !cm->CanSet(u) && !can_override))
continue;
switch (cm->type)
@@ -666,9 +659,11 @@ class CommandCSMode : public Command
else
{
std::vector<Anope::string> v = ci->c->GetModeList(cm->name);
- for (unsigned j = 0; j < v.size(); ++j)
- if (Anope::Match(v[j], param))
- ci->c->RemoveMode(NULL, cm, v[j]);
+ for (const auto &mode : v)
+ {
+ if (Anope::Match(mode, param))
+ ci->c->RemoveMode(NULL, cm, mode);
+ }
}
}
} // switch
@@ -685,8 +680,8 @@ class CommandCSMode : public Command
{
std::vector<Anope::string> new_params;
new_params.push_back(params[0]);
- new_params.push_back("SET");
- new_params.push_back("-*");
+ new_params.emplace_back("SET");
+ new_params.emplace_back("-*");
this->DoSet(source, ci, new_params);
return;
}
@@ -721,13 +716,13 @@ class CommandCSMode : public Command
std::vector<Anope::string> new_params;
new_params.push_back(params[0]);
- new_params.push_back("SET");
- new_params.push_back("-" + stringify(cm->mchar));
- new_params.push_back("*");
+ new_params.emplace_back("SET");
+ new_params.push_back("-" + Anope::ToString(cm->mchar));
+ new_params.emplace_back("*");
this->DoSet(source, ci, new_params);
}
- public:
+public:
CommandCSMode(Module *creator) : Command(creator, "chanserv/mode", 2, 4)
{
this->SetDesc(_("Control modes and mode locks on a channel"));
@@ -736,7 +731,7 @@ class CommandCSMode : public Command
this->SetSyntax(_("\037channel\037 CLEAR [\037what\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &subcommand = params[1];
@@ -766,7 +761,7 @@ class CommandCSMode : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -799,37 +794,13 @@ class CommandCSMode : public Command
static Anope::map<std::pair<bool, Anope::string> > modes;
-class CommandCSModes : public Command
+class CommandCSModes final
+ : public Command
{
- public:
- CommandCSModes(Module *creator) : Command(creator, "chanserv/modes", 1, 2)
+private:
+ void DoMode(CommandSource &source, ChannelInfo *ci, User *targ)
{
- this->SetSyntax(_("\037channel\037 [\037user\037]"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = source.GetUser(),
- *targ = params.size() > 1 ? User::Find(params[1], true) : u;
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
-
- if (!targ)
- {
- if (params.size() > 1)
- source.Reply(NICK_X_NOT_IN_USE, params[1].c_str());
- return;
- }
-
- if (!ci)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
- else if (!ci->c)
- {
- source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
- return;
- }
+ auto *u = source.GetUser();
AccessGroup u_access = source.AccessFor(ci), targ_access = ci->AccessFor(targ);
const std::pair<bool, Anope::string> &m = modes[source.command];
@@ -879,7 +850,49 @@ class CommandCSModes : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "on " << targ->nick;
}
- const Anope::string GetDesc(CommandSource &source) const anope_override
+public:
+ CommandCSModes(Module *creator) : Command(creator, "chanserv/modes", 1)
+ {
+ this->SetSyntax(_("\037channel\037 [\037user\037]+"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ auto *ci = ChannelInfo::Find(params[0]);
+ if (!ci)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+ if (!ci->c)
+ {
+ source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
+ return;
+ }
+
+ if (params.size() == 1)
+ {
+ // The source is executing the command on themself.
+ if (source.GetUser())
+ DoMode(source, ci, source.GetUser());
+ return;
+ }
+
+ // The source has provided list of nicks.
+ for (size_t i = 1; i < params.size(); ++i)
+ {
+ auto &nick = params[i];
+ auto *targ = User::Find(nick, true);
+ if (!targ)
+ {
+ source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
+ continue;
+ }
+ DoMode(source, ci, targ);
+ }
+ }
+
+ const Anope::string GetDesc(CommandSource &source) const override
{
const std::pair<bool, Anope::string> &m = modes[source.command];
if (!m.second.empty())
@@ -893,7 +906,7 @@ class CommandCSModes : public Command
return "";
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
const std::pair<bool, Anope::string> &m = modes[source.command];
if (m.second.empty())
@@ -902,11 +915,11 @@ class CommandCSModes : public Command
this->SendSyntax(source);
source.Reply(" ");
if (m.first)
- source.Reply(_("Gives %s status to the selected nick on a channel. If \037nick\037 is\n"
+ source.Reply(_("Gives %s status to the selected nicks on a channel. If \037nick\037 is\n"
"not given, it will %s you."),
m.second.upper().c_str(), m.second.lower().c_str());
else
- source.Reply(_("Removes %s status from the selected nick on a channel. If \037nick\037 is\n"
+ source.Reply(_("Removes %s status from the selected nicks on a channel. If \037nick\037 is\n"
"not given, it will de%s you."),
m.second.upper().c_str(), m.second.lower().c_str());
source.Reply(" ");
@@ -916,14 +929,15 @@ class CommandCSModes : public Command
}
};
-class CSMode : public Module
+class CSMode final
+ : public Module
{
CommandCSMode commandcsmode;
CommandCSModes commandcsmodes;
ExtensibleItem<ModeLocksImpl> modelocks;
Serialize::Type modelocks_type;
- public:
+public:
CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsmode(this), commandcsmodes(this),
modelocks(this, "modelocks"),
@@ -932,7 +946,7 @@ class CSMode : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
modes.clear();
@@ -956,17 +970,17 @@ class CSMode : public Module
}
}
- void OnCheckModes(Reference<Channel> &c) anope_override
+ void OnCheckModes(Reference<Channel> &c) override
{
if (!c || !c->ci)
return;
ModeLocks *locks = modelocks.Get(c->ci);
if (locks)
- for (ModeLocks::ModeList::const_iterator it = locks->GetMLock().begin(), it_end = locks->GetMLock().end(); it != it_end; ++it)
+ {
+ for (auto *ml : locks->GetMLock())
{
- const ModeLock *ml = *it;
- ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
+ ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
if (!cm)
continue;
@@ -1003,9 +1017,10 @@ class CSMode : public Module
c->RemoveMode(NULL, cm, ml->param, false);
}
}
+ }
}
- void OnChanRegistered(ChannelInfo *ci) anope_override
+ void OnChanRegistered(ChannelInfo *ci) override
{
ModeLocks *ml = modelocks.Require(ci);
Anope::string mlock;
@@ -1013,21 +1028,21 @@ class CSMode : public Module
if (sep.GetToken(mlock))
{
bool add = true;
- for (unsigned i = 0; i < mlock.length(); ++i)
+ for (auto mode : mlock)
{
- if (mlock[i] == '+')
+ if (mode == '+')
{
add = true;
continue;
}
- if (mlock[i] == '-')
+ if (mode == '-')
{
add = false;
continue;
}
- ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
if (!cm)
continue;
@@ -1055,7 +1070,7 @@ class CSMode : public Module
ml->Check();
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) override
{
if (!show_hidden)
return;
diff --git a/modules/commands/cs_register.cpp b/modules/chanserv/cs_register.cpp
index c485c6aa0..e4e9ad951 100644
--- a/modules/commands/cs_register.cpp
+++ b/modules/chanserv/cs_register.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandCSRegister : public Command
+class CommandCSRegister final
+ : public Command
{
- public:
+public:
CommandCSRegister(Module *creator) : Command(creator, "chanserv/register", 1, 2)
{
this->SetDesc(_("Register a channel"));
this->SetSyntax(_("\037channel\037 [\037description\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
const Anope::string &chdesc = params.size() > 1 ? params[1] : "";
@@ -32,7 +33,7 @@ class CommandCSRegister : public Command
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (Anope::ReadOnly)
- source.Reply(_("Sorry, channel registration is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
else if (nc->HasExt("UNCONFIRMED"))
source.Reply(_("You must confirm your account before you can register a channel."));
else if (chan[0] == '&')
@@ -79,7 +80,7 @@ class CommandCSRegister : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -99,9 +100,9 @@ class CommandCSRegister : public Command
Anope::string cmd;
if (Command::FindCommandFromService("chanserv/access", bi, cmd))
source.Reply(_(" \n"
- "See the \002%s\002 command (\002%s%s HELP ACCESS\002) for\n"
+ "See the \002%s\002 command (\002%s HELP ACCESS\002) for\n"
"information on giving a subset of these privileges to\n"
- "other channel users.\n"), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str());
+ "other channel users.\n"), cmd.c_str(), bi->GetQueryCommand().c_str());
source.Reply(_(" \n"
"NOTICE: In order to register a channel, you must have\n"
"first registered your nickname."));
@@ -110,11 +111,12 @@ class CommandCSRegister : public Command
};
-class CSRegister : public Module
+class CSRegister final
+ : public Module
{
CommandCSRegister commandcsregister;
- public:
+public:
CSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsregister(this)
{
diff --git a/modules/commands/cs_seen.cpp b/modules/chanserv/cs_seen.cpp
index 6b19c1d8b..6197975f5 100644
--- a/modules/commands/cs_seen.cpp
+++ b/modules/chanserv/cs_seen.cpp
@@ -19,10 +19,11 @@ enum TypeInfo
static bool simple;
struct SeenInfo;
static SeenInfo *FindInfo(const Anope::string &nick);
-typedef Anope::hash_map<SeenInfo *> database_map;
+typedef Anope::unordered_map<SeenInfo *> database_map;
database_map database;
-struct SeenInfo : Serializable
+struct SeenInfo final
+ : Serializable
{
Anope::string nick;
Anope::string vhost;
@@ -36,25 +37,25 @@ struct SeenInfo : Serializable
{
}
- ~SeenInfo()
+ ~SeenInfo() override
{
database_map::iterator iter = database.find(nick);
if (iter != database.end() && iter->second == this)
database.erase(iter);
}
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["nick"] << nick;
- data["vhost"] << vhost;
- data["type"] << type;
- data["nick2"] << nick2;
- data["channel"] << channel;
- data["message"] << message;
- data.SetType("last", Serialize::Data::DT_INT); data["last"] << last;
+ data.Store("nick", nick);
+ data.Store("vhost", vhost);
+ data.Store("type", type);
+ data.Store("nick2", nick2);
+ data.Store("channel", channel);
+ data.Store("message", message);
+ data.Store("last", last);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string snick;
@@ -65,7 +66,7 @@ struct SeenInfo : Serializable
s = anope_dynamic_static_cast<SeenInfo *>(obj);
else
{
- SeenInfo* &info = database[snick];
+ SeenInfo *&info = database[snick];
if (!info)
info = new SeenInfo();
s = info;
@@ -109,9 +110,10 @@ static bool ShouldHide(const Anope::string &channel, User *u)
return false;
}
-class CommandOSSeen : public Command
+class CommandOSSeen final
+ : public Command
{
- public:
+public:
CommandOSSeen(Module *creator) : Command(creator, "operserv/seen", 1, 2)
{
this->SetDesc(_("Statistics and maintenance for seen data"));
@@ -119,20 +121,20 @@ class CommandOSSeen : public Command
this->SetSyntax(_("CLEAR \037time\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (params[0].equals_ci("STATS"))
{
size_t mem_counter;
mem_counter = sizeof(database_map);
- for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end; ++it)
+ for (auto &[nick, si] : database)
{
mem_counter += (5 * sizeof(Anope::string)) + sizeof(TypeInfo) + sizeof(time_t);
- mem_counter += it->first.capacity();
- mem_counter += it->second->vhost.capacity();
- mem_counter += it->second->nick2.capacity();
- mem_counter += it->second->channel.capacity();
- mem_counter += it->second->message.capacity();
+ mem_counter += nick.capacity();
+ mem_counter += si->vhost.capacity();
+ mem_counter += si->nick2.capacity();
+ mem_counter += si->channel.capacity();
+ mem_counter += si->message.capacity();
}
source.Reply(_("%lu nicks are stored in the database, using %.2Lf kB of memory."), database.size(), static_cast<long double>(mem_counter) / 1024);
}
@@ -165,7 +167,7 @@ class CommandOSSeen : public Command
this->SendSyntax(source);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -180,9 +182,10 @@ class CommandOSSeen : public Command
}
};
-class CommandSeen : public Command
+class CommandSeen final
+ : public Command
{
- void SimpleSeen(CommandSource &source, const std::vector<Anope::string> &params)
+ static void SimpleSeen(CommandSource &source, const std::vector<Anope::string> &params)
{
if (!source.c || !source.c->ci)
{
@@ -222,9 +225,8 @@ class CommandSeen : public Command
return;
}
- for (Channel::ChanUserList::const_iterator it = source.c->users.begin(), it_end = source.c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : source.c->users)
{
- ChanUserContainer *uc = it->second;
User *u = uc->user;
if (u->Account() == na->nc)
@@ -236,10 +238,8 @@ class CommandSeen : public Command
AccessGroup ag = source.c->ci->AccessFor(na->nc);
time_t last = 0;
- for (unsigned int i = 0; i < ag.paths.size(); ++i)
+ for (const auto &p : ag.paths)
{
- ChanAccess::Path &p = ag.paths[i];
-
if (p.empty())
continue;
@@ -255,7 +255,7 @@ class CommandSeen : public Command
source.Reply(_("%s was last seen here %s ago."), na->nick.c_str(), Anope::Duration(Anope::CurTime - last, source.GetAccount()).c_str());
}
- public:
+public:
CommandSeen(Module *creator) : Command(creator, "chanserv/seen", 1, 2)
{
this->SetDesc(_("Tells you about the last time a user was seen"));
@@ -263,16 +263,16 @@ class CommandSeen : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &target = params[0];
if (simple)
return this->SimpleSeen(source, params);
- if (target.length() > Config->GetBlock("networkinfo")->Get<unsigned>("nicklen"))
+ if (target.length() > IRCD->MaxNick)
{
- source.Reply(_("Nick too long, max length is %u characters."), Config->GetBlock("networkinfo")->Get<unsigned>("nicklen"));
+ source.Reply(_("Nick too long, max length is %zu characters."), IRCD->MaxNick);
return;
}
@@ -360,7 +360,7 @@ class CommandSeen : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -371,22 +371,23 @@ class CommandSeen : public Command
}
};
-class CSSeen : public Module
+class CSSeen final
+ : public Module
{
Serialize::Type seeninfo_type;
CommandSeen commandseen;
CommandOSSeen commandosseen;
- public:
+public:
CSSeen(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), seeninfo_type("SeenInfo", SeenInfo::Unserialize), commandseen(this), commandosseen(this)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
simple = conf->GetModule(this)->Get<bool>("simple");
}
- void OnExpireTick() anope_override
+ void OnExpireTick() override
{
size_t previous_size = database.size();
time_t purgetime = Config->GetModule(this)->Get<time_t>("purgetime");
@@ -406,45 +407,45 @@ class CSSeen : public Module
Log(LOG_DEBUG) << "cs_seen: Purged database, checked " << previous_size << " nicks and removed " << (previous_size - database.size()) << " old entries.";
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (!u->Quitting())
UpdateUser(u, NEW, u->nick, "", "", "");
}
- void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
+ void OnUserNickChange(User *u, const Anope::string &oldnick) override
{
UpdateUser(u, NICK_TO, oldnick, u->nick, "", "");
UpdateUser(u, NICK_FROM, u->nick, oldnick, "", "");
}
- void OnUserQuit(User *u, const Anope::string &msg) anope_override
+ void OnUserQuit(User *u, const Anope::string &msg) override
{
UpdateUser(u, QUIT, u->nick, "", "", msg);
}
- void OnJoinChannel(User *u, Channel *c) anope_override
+ void OnJoinChannel(User *u, Channel *c) override
{
UpdateUser(u, JOIN, u->nick, "", c->name, "");
}
- void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) anope_override
+ void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) override
{
UpdateUser(u, PART, u->nick, "", channel, msg);
}
- void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &msg) anope_override
+ void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &msg) override
{
UpdateUser(cu->user, KICK, cu->user->nick, source.GetSource(), cu->chan->name, msg);
}
- private:
- void UpdateUser(const User *u, const TypeInfo Type, const Anope::string &nick, const Anope::string &nick2, const Anope::string &channel, const Anope::string &message)
+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())
return;
- SeenInfo* &info = database[nick];
+ SeenInfo *&info = database[nick];
if (!info)
info = new SeenInfo();
info->nick = nick;
diff --git a/modules/commands/cs_set.cpp b/modules/chanserv/cs_set.cpp
index fa62d1577..7f9e49dd3 100644
--- a/modules/commands/cs_set.cpp
+++ b/modules/chanserv/cs_set.cpp
@@ -12,21 +12,22 @@
#include "module.h"
#include "modules/cs_mode.h"
-class CommandCSSet : public Command
+class CommandCSSet final
+ : public Command
{
- public:
+public:
CommandCSSet(Module *creator) : Command(creator, "chanserv/set", 2, 3)
{
this->SetDesc(_("Set channel options and information"));
this->SetSyntax(_("\037option\037 \037channel\037 \037parameters\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -37,10 +38,8 @@ class CommandCSSet : public Command
Anope::string this_name = source.command;
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
- for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
+ for (const auto &[c_name, info] : source.service->commands)
{
- const Anope::string &c_name = it->first;
- const CommandInfo &info = it->second;
if (c_name.find_ci(this_name + " ") == 0)
{
if (info.hide)
@@ -56,26 +55,27 @@ class CommandCSSet : public Command
else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
continue;
- source.command = it->first;
+ source.command = c_name;
c->OnServHelp(source);
}
}
- source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n"
- "particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
+ source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information on a\n"
+ "particular option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
return true;
}
};
-class CommandCSSetAutoOp : public Command
+class CommandCSSetAutoOp final
+ : public Command
{
- public:
+public:
CommandCSSetAutoOp(Module *creator, const Anope::string &cname = "chanserv/set/autoop") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Should services automatically give status to users"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -117,28 +117,29 @@ class CommandCSSetAutoOp : public Command
this->OnSyntaxError(source, "AUTOOP");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Enables or disables %s's autoop feature for a\n"
"channel. When disabled, users who join the channel will\n"
"not automatically gain any status from %s."), source.service->nick.c_str(),
- source.service->nick.c_str(), this->name.c_str());
+ source.service->nick.c_str());
return true;
}
};
-class CommandCSSetBanType : public Command
+class CommandCSSetBanType final
+ : public Command
{
- public:
+public:
CommandCSSetBanType(Module *creator, const Anope::string &cname = "chanserv/set/bantype") : Command(creator, cname, 2, 2)
{
- this->SetDesc(_("Set how Services make bans on the channel"));
+ this->SetDesc(_("Set how services make bans on the channel"));
this->SetSyntax(_("\037channel\037 \037bantype\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -164,22 +165,19 @@ class CommandCSSetBanType : public Command
return;
}
- try
- {
- int16_t new_type = convertTo<int16_t>(params[1]);
- if (new_type < 0 || new_type > 3)
- throw ConvertException("Invalid range");
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type;
- ci->bantype = new_type;
- source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype);
- }
- catch (const ConvertException &)
+ auto new_type = Anope::Convert<int16_t>(params[1], -1);
+ if (new_type < 0 || new_type > 3)
{
source.Reply(_("\002%s\002 is not a valid ban type."), params[1].c_str());
+ return;
}
+
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type;
+ ci->bantype = new_type;
+ source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -191,21 +189,22 @@ class CommandCSSetBanType : public Command
"0: ban in the form *!user@host\n"
"1: ban in the form *!*user@host\n"
"2: ban in the form *!*@host\n"
- "3: ban in the form *!*user@*.domain"), this->name.c_str());
+ "3: ban in the form *!*user@*.domain"));
return true;
}
};
-class CommandCSSetDescription : public Command
+class CommandCSSetDescription final
+ : public Command
{
- public:
+public:
CommandCSSetDescription(Module *creator, const Anope::string &cname = "chanserv/set/description") : Command(creator, cname, 1, 2)
{
this->SetDesc(_("Set the channel description"));
this->SetSyntax(_("\037channel\037 [\037description\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -248,26 +247,27 @@ class CommandCSSetDescription : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Sets the description for the channel, which shows up with\n"
- "the \002LIST\002 and \002INFO\002 commands."), this->name.c_str());
+ "the \002LIST\002 and \002INFO\002 commands."));
return true;
}
};
-class CommandCSSetFounder : public Command
+class CommandCSSetFounder final
+ : public Command
{
- public:
+public:
CommandCSSetFounder(Module *creator, const Anope::string &cname = "chanserv/set/founder") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Set the founder of a channel"));
this->SetSyntax(_("\037channel\037 \037nick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -317,26 +317,27 @@ class CommandCSSetFounder : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Changes the founder of a channel. The new nickname must\n"
- "be a registered one."), this->name.c_str());
+ "be a registered one."));
return true;
}
};
-class CommandCSSetKeepModes : public Command
+class CommandCSSetKeepModes final
+ : public Command
{
- public:
+public:
CommandCSSetKeepModes(Module *creator, const Anope::string &cname = "chanserv/set/keepmodes") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Retain modes when channel is not in use"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -381,7 +382,7 @@ class CommandCSSetKeepModes : public Command
this->OnSyntaxError(source, "KEEPMODES");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -392,16 +393,17 @@ class CommandCSSetKeepModes : public Command
}
};
-class CommandCSSetPeace : public Command
+class CommandCSSetPeace final
+ : public Command
{
- public:
+public:
CommandCSSetPeace(Module *creator, const Anope::string &cname = "chanserv/set/peace") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Regulate the use of critical commands"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -445,7 +447,7 @@ class CommandCSSetPeace : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -464,16 +466,17 @@ inline static Anope::string BotModes()
);
}
-class CommandCSSetPersist : public Command
+class CommandCSSetPersist final
+ : public Command
{
- public:
+public:
CommandCSSetPersist(Module *creator, const Anope::string &cname = "chanserv/set/persist") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Set the channel as permanent"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -585,7 +588,7 @@ class CommandCSSetPersist : public Command
this->OnSyntaxError(source, "PERSIST");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
BotInfo *BotServ = Config->GetClient("BotServ");
BotInfo *ChanServ = Config->GetClient("ChanServ");
@@ -615,16 +618,17 @@ class CommandCSSetPersist : public Command
}
};
-class CommandCSSetRestricted : public Command
+class CommandCSSetRestricted final
+ : public Command
{
- public:
+public:
CommandCSSetRestricted(Module *creator, const Anope::string &cname = "chanserv/set/restricted") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Restrict access to the channel"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -666,7 +670,7 @@ class CommandCSSetRestricted : public Command
this->OnSyntaxError(source, "RESTRICTED");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -677,79 +681,17 @@ class CommandCSSetRestricted : public Command
}
};
-class CommandCSSetSecure : public Command
-{
- public:
- CommandCSSetSecure(Module *creator, const Anope::string &cname = "chanserv/set/secure") : Command(creator, cname, 2, 2)
- {
- this->SetDesc(_("Activate security features"));
- this->SetSyntax(_("\037channel\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (params[1].equals_ci("ON"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure";
- ci->Extend<bool>("CS_SECURE");
- source.Reply(_("Secure option for %s is now \002on\002."), ci->name.c_str());
- }
- else if (params[1].equals_ci("OFF"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure";
- ci->Shrink<bool>("CS_SECURE");
- source.Reply(_("Secure option for %s is now \002off\002."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, "SECURE");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Enables or disables security features for a\n"
- "channel. When \002SECURE\002 is set, only users who have\n"
- "identified to services, and are not only recognized, will be\n"
- "given access to channels from account-based access entries."));
- return true;
- }
-};
-
-class CommandCSSetSecureFounder : public Command
+class CommandCSSetSecureFounder final
+ : public Command
{
- public:
+public:
CommandCSSetSecureFounder(Module *creator, const Anope::string &cname = "chanserv/set/securefounder") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Stricter control of channel founder status"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -791,7 +733,7 @@ class CommandCSSetSecureFounder : public Command
this->OnSyntaxError(source, "SECUREFOUNDER");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -804,16 +746,17 @@ class CommandCSSetSecureFounder : public Command
}
};
-class CommandCSSetSecureOps : public Command
+class CommandCSSetSecureOps final
+ : public Command
{
- public:
+public:
CommandCSSetSecureOps(Module *creator, const Anope::string &cname = "chanserv/set/secureops") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Stricter control of chanop status"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -855,7 +798,7 @@ class CommandCSSetSecureOps : public Command
this->OnSyntaxError(source, "SECUREOPS");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -866,16 +809,17 @@ class CommandCSSetSecureOps : public Command
}
};
-class CommandCSSetSignKick : public Command
+class CommandCSSetSignKick final
+ : public Command
{
- public:
+public:
CommandCSSetSignKick(Module *creator, const Anope::string &cname = "chanserv/set/signkick") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Sign kicks that are done with the KICK command"));
this->SetSyntax(_("\037channel\037 {ON | LEVEL | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -927,7 +871,7 @@ class CommandCSSetSignKick : public Command
this->OnSyntaxError(source, "SIGNKICK");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -943,16 +887,17 @@ class CommandCSSetSignKick : public Command
}
};
-class CommandCSSetSuccessor : public Command
+class CommandCSSetSuccessor final
+ : public Command
{
- public:
+public:
CommandCSSetSuccessor(Module *creator, const Anope::string &cname = "chanserv/set/successor") : Command(creator, cname, 1, 2)
{
this->SetDesc(_("Set the successor for a channel"));
this->SetSyntax(_("\037channel\037 [\037nick\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -1012,7 +957,7 @@ class CommandCSSetSuccessor : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -1037,16 +982,17 @@ class CommandCSSetSuccessor : public Command
}
};
-class CommandCSSetNoexpire : public Command
+class CommandCSSetNoexpire final
+ : public Command
{
- public:
+public:
CommandCSSetNoexpire(Module *creator) : Command(creator, "chanserv/saset/noexpire", 2, 2)
{
this->SetDesc(_("Prevent the channel from expiring"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -1085,7 +1031,7 @@ class CommandCSSetNoexpire : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -1095,17 +1041,19 @@ class CommandCSSetNoexpire : public Command
}
};
-class CSSet : public Module
+class CSSet final
+ : public Module
{
SerializableExtensibleItem<bool> noautoop, peace, securefounder,
- restricted, secure, secureops, signkick, signkick_level, noexpire,
+ restricted, secureops, signkick, signkick_level, noexpire,
persist;
- struct KeepModes : SerializableExtensibleItem<bool>
+ struct KeepModes final
+ : SerializableExtensibleItem<bool>
{
KeepModes(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { }
- void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data);
@@ -1114,18 +1062,18 @@ class CSSet : public Module
const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(s);
Anope::string modes;
- for (Channel::ModeList::const_iterator it = ci->last_modes.begin(); it != ci->last_modes.end(); ++it)
+ for (const auto &[last_mode, last_value] : ci->last_modes)
{
if (!modes.empty())
modes += " ";
- modes += it->first;
- if (!it->second.empty())
- modes += "," + it->second;
+ modes += last_mode;
+ if (!last_value.empty())
+ modes += "," + last_value;
}
- data["last_modes"] << modes;
+ data.Store("last_modes", modes);
}
- void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
{
SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data);
@@ -1140,9 +1088,9 @@ class CSSet : public Module
{
size_t c = modes.find(',');
if (c == Anope::string::npos)
- ci->last_modes.insert(std::make_pair(modes, ""));
+ ci->last_modes.emplace(modes, "");
else
- ci->last_modes.insert(std::make_pair(modes.substr(0, c), modes.substr(c + 1)));
+ ci->last_modes.emplace(modes.substr(0, c), modes.substr(c + 1));
}
}
} keep_modes;
@@ -1156,7 +1104,6 @@ class CSSet : public Module
CommandCSSetPeace commandcssetpeace;
CommandCSSetPersist commandcssetpersist;
CommandCSSetRestricted commandcssetrestricted;
- CommandCSSetSecure commandcssetsecure;
CommandCSSetSecureFounder commandcssetsecurefounder;
CommandCSSetSecureOps commandcssetsecureops;
CommandCSSetSignKick commandcssetsignkick;
@@ -1167,11 +1114,11 @@ class CSSet : public Module
bool persist_lower_ts;
- public:
+public:
CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
noautoop(this, "NOAUTOOP"), peace(this, "PEACE"),
securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"),
- secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
+ secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
signkick_level(this, "SIGNKICK_LEVEL"), noexpire(this, "CS_NO_EXPIRE"),
persist(this, "PERSIST"),
keep_modes(this, "CS_KEEP_MODES"),
@@ -1179,34 +1126,34 @@ class CSSet : public Module
commandcsset(this), commandcssetautoop(this), commandcssetbantype(this),
commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this),
commandcssetpeace(this), commandcssetpersist(this), commandcssetrestricted(this),
- commandcssetsecure(this), commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this),
+ commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this),
commandcssetsuccessor(this), commandcssetnoexpire(this),
inhabit("inhabit")
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
persist_lower_ts = conf->GetModule(this)->Get<bool>("persist_lower_ts");
}
- void OnCreateChan(ChannelInfo *ci) anope_override
+ void OnCreateChan(ChannelInfo *ci) override
{
ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
}
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
if (c->ci && keep_modes.HasExt(c->ci))
{
Channel::ModeList ml = c->ci->last_modes;
- for (Channel::ModeList::iterator it = ml.begin(); it != ml.end(); ++it)
- c->SetMode(c->ci->WhoSends(), it->first, it->second);
+ for (const auto &[last_mode, last_value] : ml)
+ c->SetMode(c->ci->WhoSends(), last_mode, last_value);
}
}
- EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
+ EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT"))
return EVENT_CONTINUE;
@@ -1217,14 +1164,14 @@ class CSSet : public Module
return EVENT_CONTINUE;
}
- void OnDelChan(ChannelInfo *ci) anope_override
+ void OnDelChan(ChannelInfo *ci) override
{
if (ci->c && persist.HasExt(ci))
ci->c->RemoveMode(ci->WhoSends(), "PERM", "", false);
persist.Unset(ci);
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override
{
if (c->ci)
{
@@ -1239,7 +1186,7 @@ class CSSet : public Module
return EVENT_CONTINUE;
}
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override
{
if (mode->name == "PERM")
{
@@ -1253,7 +1200,7 @@ class CSSet : public Module
return EVENT_CONTINUE;
}
- void OnJoinChannel(User *u, Channel *c) anope_override
+ void OnJoinChannel(User *u, Channel *c) override
{
if (u->server != Me && persist_lower_ts && c->ci && persist.HasExt(c->ci) && c->creation_time > c->ci->time_registered)
{
@@ -1264,7 +1211,7 @@ class CSSet : public Module
}
}
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override
+ void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) override
{
if (chan->ci)
{
@@ -1276,13 +1223,13 @@ class CSSet : public Module
}
}
- void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override
+ void OnPreChanExpire(ChannelInfo *ci, bool &expire) override
{
if (noexpire.HasExt(ci))
expire = false;
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) override
{
if (!show_all)
return;
@@ -1291,8 +1238,6 @@ class CSSet : public Module
info.AddOption(_("Peace"));
if (restricted.HasExt(ci))
info.AddOption(_("Restricted access"));
- if (secure.HasExt(ci))
- info.AddOption(_("Security"));
if (securefounder.HasExt(ci))
info.AddOption(_("Secure founder"));
if (secureops.HasExt(ci))
diff --git a/modules/commands/cs_set_misc.cpp b/modules/chanserv/cs_set_misc.cpp
index 1c6e29d20..7fef1e022 100644
--- a/modules/commands/cs_set_misc.cpp
+++ b/modules/chanserv/cs_set_misc.cpp
@@ -15,13 +15,14 @@
static Module *me;
static Anope::map<Anope::string> descriptions;
+static Anope::map<uint16_t> numerics;
struct CSMiscData;
static Anope::map<ExtensibleItem<CSMiscData> *> items;
static ExtensibleItem<CSMiscData> *GetItem(const Anope::string &name)
{
- ExtensibleItem<CSMiscData>* &it = items[name];
+ ExtensibleItem<CSMiscData> *&it = items[name];
if (!it)
try
{
@@ -31,7 +32,9 @@ static ExtensibleItem<CSMiscData> *GetItem(const Anope::string &name)
return it;
}
-struct CSMiscData : MiscData, Serializable
+struct CSMiscData final
+ : MiscData
+ , Serializable
{
CSMiscData(Extensible *obj) : Serializable("CSMiscData") { }
@@ -42,14 +45,14 @@ struct CSMiscData : MiscData, Serializable
data = d;
}
- void Serialize(Serialize::Data &sdata) const anope_override
+ void Serialize(Serialize::Data &sdata) const override
{
- sdata["ci"] << this->object;
- sdata["name"] << this->name;
- sdata["data"] << this->data;
+ sdata.Store("ci", this->object);
+ sdata.Store("name", this->name);
+ sdata.Store("data", this->data);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sci, sname, sdata;
@@ -88,15 +91,16 @@ static Anope::string GetAttribute(const Anope::string &command)
return command;
}
-class CommandCSSetMisc : public Command
+class CommandCSSetMisc final
+ : public Command
{
- public:
+public:
CommandCSSetMisc(Module *creator, const Anope::string &cname = "chanserv/set/misc") : Command(creator, cname, 1, 2)
{
this->SetSyntax(_("\037channel\037 [\037parameters\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -143,7 +147,7 @@ class CommandCSSetMisc : public Command
}
}
- void OnServHelp(CommandSource &source) anope_override
+ void OnServHelp(CommandSource &source) override
{
if (descriptions.count(source.command))
{
@@ -152,7 +156,7 @@ class CommandCSSetMisc : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (descriptions.count(source.command))
{
@@ -164,27 +168,29 @@ class CommandCSSetMisc : public Command
}
};
-class CSSetMisc : public Module
+class CSSetMisc final
+ : public Module
{
CommandCSSetMisc commandcssetmisc;
Serialize::Type csmiscdata_type;
- public:
+public:
CSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcssetmisc(this), csmiscdata_type("CSMiscData", CSMiscData::Unserialize)
{
me = this;
}
- ~CSSetMisc()
+ ~CSSetMisc() override
{
- for (Anope::map<ExtensibleItem<CSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it)
- delete it->second;
+ for (const auto &[_, item] : items)
+ delete item;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
descriptions.clear();
+ numerics.clear();
for (int i = 0; i < conf->CountBlock("command"); ++i)
{
@@ -200,14 +206,35 @@ class CSSetMisc : public Module
continue;
descriptions[cname] = desc;
+
+ auto numeric = block->Get<unsigned>("misc_numeric");
+ if (numeric >= 1 && numeric <= 999)
+ numerics["cs_set_misc:" + GetAttribute(cname)] = numeric;
}
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool) anope_override
+ void OnJoinChannel(User *user, Channel *c) override
+ {
+ if (!c->ci || !user->server->IsSynced() || numerics.empty())
+ return;
+
+ for (const auto &[name, ext] : items)
+ {
+ auto *data = ext->Get(c->ci);
+ if (!data)
+ continue;
+
+ auto numeric = numerics.find(name);
+ if (numeric != numerics.end())
+ IRCD->SendNumeric(numeric->second, user->GetUID(), c->ci->name, data->data);
+ }
+ }
+
+
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool) override
{
- for (Anope::map<ExtensibleItem<CSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it)
+ for (const auto &[_, e] : items)
{
- ExtensibleItem<CSMiscData> *e = it->second;
MiscData *data = e->Get(ci);
if (data != NULL)
diff --git a/modules/commands/cs_status.cpp b/modules/chanserv/cs_status.cpp
index 9eb0294b0..39b54280e 100644
--- a/modules/commands/cs_status.cpp
+++ b/modules/chanserv/cs_status.cpp
@@ -11,7 +11,8 @@
#include "module.h"
-class CommandCSStatus : public Command
+class CommandCSStatus final
+ : public Command
{
public:
CommandCSStatus(Module *creator) : Command(creator, "chanserv/status", 1, 2)
@@ -20,7 +21,7 @@ public:
this->SetSyntax(_("\037channel\037 [\037user\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &channel = params[0];
@@ -57,11 +58,9 @@ public:
{
source.Reply(_("Access for \002%s\002 on \002%s\002:"), nick.c_str(), ci->name.c_str());
- for (unsigned i = 0; i < ag.paths.size(); ++i)
+ for (const auto &p : ag.paths)
{
- ChanAccess::Path &p = ag.paths[i];
-
- if (p.empty())
+ if (p.empty())
continue;
if (p.size() == 1)
@@ -99,7 +98,7 @@ public:
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -112,11 +111,12 @@ public:
}
};
-class CSStatus : public Module
+class CSStatus final
+ : public Module
{
CommandCSStatus commandcsstatus;
- public:
+public:
CSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsstatus(this)
{
}
diff --git a/modules/chanserv/cs_statusupdate.cpp b/modules/chanserv/cs_statusupdate.cpp
new file mode 100644
index 000000000..725f16f22
--- /dev/null
+++ b/modules/chanserv/cs_statusupdate.cpp
@@ -0,0 +1,58 @@
+/*
+ *
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+
+class StatusUpdate final
+ : public Module
+{
+private:
+ void OnAccessChange(ChannelInfo *ci, ChanAccess *access, bool adding)
+ {
+ if (!ci->c)
+ return;
+
+ for (const auto &[_, uc] : ci->c->users)
+ {
+ auto *user = uc->user;
+
+ ChannelInfo *next;
+ if (user->server != Me && access->Matches(user, user->Account(), next))
+ {
+ auto ag = ci->AccessFor(user);
+
+ for (auto *cms : ModeManager::GetStatusChannelModesByRank())
+ {
+ if (!ag.HasPriv("AUTO" + cms->name))
+ ci->c->RemoveMode(NULL, cms, user->GetUID());
+ }
+
+ if (adding)
+ ci->c->SetCorrectModes(user, true);
+ }
+ }
+ }
+
+public:
+ StatusUpdate(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ {
+ }
+
+ void OnAccessAdd(ChannelInfo *ci, CommandSource &, ChanAccess *access) override
+ {
+ OnAccessChange(ci, access, true);
+ }
+
+ void OnAccessDel(ChannelInfo *ci, CommandSource &, ChanAccess *access) override
+ {
+ OnAccessChange(ci, access, false);
+ }
+};
+
+MODULE_INIT(StatusUpdate)
diff --git a/modules/commands/cs_suspend.cpp b/modules/chanserv/cs_suspend.cpp
index fc51e0b8f..2633bc094 100644
--- a/modules/commands/cs_suspend.cpp
+++ b/modules/chanserv/cs_suspend.cpp
@@ -12,20 +12,22 @@
#include "module.h"
#include "modules/suspend.h"
-struct CSSuspendInfo : SuspendInfo, Serializable
+struct CSSuspendInfo final
+ : SuspendInfo
+ , Serializable
{
CSSuspendInfo(Extensible *) : Serializable("CSSuspendInfo") { }
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["chan"] << what;
- data["by"] << by;
- data["reason"] << reason;
- data["time"] << when;
- data["expires"] << expires;
+ data.Store("chan", what);
+ data.Store("by", by);
+ data.Store("reason", reason);
+ data.Store("time", when);
+ data.Store("expires", expires);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string schan;
data["chan"] >> schan;
@@ -50,21 +52,22 @@ struct CSSuspendInfo : SuspendInfo, Serializable
}
};
-class CommandCSSuspend : public Command
+class CommandCSSuspend final
+ : public Command
{
- public:
+public:
CommandCSSuspend(Module *creator) : Command(creator, "chanserv/suspend", 2, 3)
{
this->SetDesc(_("Prevent a channel from being used preserving channel data and settings"));
this->SetSyntax(_("\037channel\037 [+\037expiry\037] [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
Anope::string expiry = params[1];
Anope::string reason = params.size() > 2 ? params[2] : "";
- time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("expire");
+ time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("suspendexpire");
if (!expiry.empty() && expiry[0] != '+')
{
@@ -109,16 +112,15 @@ class CommandCSSuspend : public Command
{
std::vector<User *> users;
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : ci->c->users)
{
- ChanUserContainer *uc = it->second;
User *user = uc->user;
if (!user->HasMode("OPER") && user->server != Me)
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
- ci->c->Kick(NULL, users[i], "%s", !reason.empty() ? reason.c_str() : Language::Translate(users[i], _("This channel has been suspended.")));
+ for (auto *user : users)
+ ci->c->Kick(NULL, user, "%s", !reason.empty() ? reason.c_str() : Language::Translate(user, _("This channel has been suspended.")));
}
Log(LOG_ADMIN, source, this, ci) << "(" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never");
@@ -127,7 +129,7 @@ class CommandCSSuspend : public Command
FOREACH_MOD(OnChanSuspend, (ci));
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -143,16 +145,17 @@ class CommandCSSuspend : public Command
}
};
-class CommandCSUnSuspend : public Command
+class CommandCSUnSuspend final
+ : public Command
{
- public:
+public:
CommandCSUnSuspend(Module *creator) : Command(creator, "chanserv/unsuspend", 1, 1)
{
this->SetDesc(_("Releases a suspended channel"));
this->SetSyntax(_("\037channel\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
@@ -184,7 +187,7 @@ class CommandCSUnSuspend : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -194,7 +197,8 @@ class CommandCSUnSuspend : public Command
}
};
-class CSSuspend : public Module
+class CSSuspend final
+ : public Module
{
CommandCSSuspend commandcssuspend;
CommandCSUnSuspend commandcsunsuspend;
@@ -202,7 +206,7 @@ class CSSuspend : public Module
Serialize::Type suspend_type;
std::vector<Anope::string> show;
- struct trim
+ struct trim final
{
Anope::string operator()(Anope::string s) const
{
@@ -222,21 +226,21 @@ class CSSuspend : public Module
return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end();
}
- public:
+public:
CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcssuspend(this), commandcsunsuspend(this), suspend(this, "CS_SUSPENDED"),
suspend_type("CSSuspendInfo", CSSuspendInfo::Unserialize)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Anope::string s = conf->GetModule(this)->Get<Anope::string>("show");
commasepstream(s).GetTokens(show);
std::transform(show.begin(), show.end(), show.begin(), trim());
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) override
{
CSSuspendInfo *si = suspend.Get(ci);
if (!si)
@@ -254,7 +258,7 @@ class CSSuspend : public Module
info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount());
}
- void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override
+ void OnPreChanExpire(ChannelInfo *ci, bool &expire) override
{
CSSuspendInfo *si = suspend.Get(ci);
if (!si)
@@ -269,7 +273,7 @@ class CSSuspend : public Module
}
}
- EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
+ EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
if (u->HasMode("OPER") || !c->ci)
return EVENT_CONTINUE;
@@ -288,7 +292,7 @@ class CSSuspend : public Module
return EVENT_STOP;
}
- EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) anope_override
+ EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) override
{
CSSuspendInfo *si = suspend.Get(ci);
if (si && !source.HasCommand("chanserv/drop"))
diff --git a/modules/commands/cs_sync.cpp b/modules/chanserv/cs_sync.cpp
index b308e0c5d..46b6bad66 100644
--- a/modules/commands/cs_sync.cpp
+++ b/modules/chanserv/cs_sync.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandCSSync : public Command
+class CommandCSSync final
+ : public Command
{
- public:
+public:
CommandCSSync(Module *creator) : Command(creator, "chanserv/sync", 1, 1)
{
this->SetDesc(_("Sync users channel modes"));
this->SetSyntax(_("\037channel\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
@@ -35,14 +36,14 @@ class CommandCSSync : public Command
bool override = !source.AccessFor(ci).HasPriv("ACCESS_CHANGE") && source.HasPriv("chanserv/administration");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci);
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
- ci->c->SetCorrectModes(it->second->user, true);
+ for (const auto &[_, uc] : ci->c->users)
+ ci->c->SetCorrectModes(uc->user, true);
source.Reply(_("All user modes on \002%s\002 have been synced."), ci->name.c_str());
}
}
- bool OnHelp(CommandSource &source, const Anope::string &params) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &params) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -52,10 +53,11 @@ class CommandCSSync : public Command
}
};
-class CSSync : public Module
+class CSSync final
+ : public Module
{
CommandCSSync commandcssync;
- public:
+public:
CSSync(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcssync(this)
{
diff --git a/modules/commands/cs_topic.cpp b/modules/chanserv/cs_topic.cpp
index 7f55e46e3..7f05d1d83 100644
--- a/modules/commands/cs_topic.cpp
+++ b/modules/chanserv/cs_topic.cpp
@@ -12,16 +12,17 @@
#include "module.h"
#include "modules/cs_mode.h"
-class CommandCSSetKeepTopic : public Command
+class CommandCSSetKeepTopic final
+ : public Command
{
- public:
+public:
CommandCSSetKeepTopic(Module *creator, const Anope::string &cname = "chanserv/set/keeptopic") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Retain topic when channel is not in use"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -63,7 +64,7 @@ class CommandCSSetKeepTopic : public Command
this->OnSyntaxError(source, "KEEPTOPIC");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -76,7 +77,8 @@ class CommandCSSetKeepTopic : public Command
}
};
-class CommandCSTopic : public Command
+class CommandCSTopic final
+ : public Command
{
ExtensibleRef<bool> topiclock;
@@ -142,7 +144,7 @@ class CommandCSTopic : public Command
this->Set(source, ci, new_topic);
}
- public:
+public:
CommandCSTopic(Module *creator) : Command(creator, "chanserv/topic", 2, 3),
topiclock("TOPICLOCK")
{
@@ -152,7 +154,7 @@ class CommandCSTopic : public Command
this->SetSyntax(_("\037channel\037 [UNLOCK|LOCK]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &subcmd = params[1];
@@ -186,7 +188,7 @@ class CommandCSTopic : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -202,21 +204,22 @@ class CommandCSTopic : public Command
}
};
-class CSTopic : public Module
+class CSTopic final
+ : public Module
{
CommandCSTopic commandcstopic;
CommandCSSetKeepTopic commandcssetkeeptopic;
SerializableExtensibleItem<bool> topiclock, keeptopic;
- public:
+public:
CSTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcstopic(this), commandcssetkeeptopic(this), topiclock(this, "TOPICLOCK"), keeptopic(this, "KEEPTOPIC")
{
}
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
if (c->ci)
{
@@ -228,7 +231,7 @@ class CSTopic : public Module
}
}
- void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
+ void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override
{
if (!c->ci)
return;
@@ -250,7 +253,7 @@ class CSTopic : public Module
}
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) override
{
if (keeptopic.HasExt(ci))
info.AddOption(_("Topic retention"));
@@ -259,7 +262,7 @@ class CSTopic : public Module
ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks");
const ModeLock *secret = ml ? ml->GetMLock("SECRET") : NULL;
- if (!ci->last_topic.empty() && (show_all || ((!secret || secret->set == false) && (!ci->c || !ci->c->HasMode("SECRET")))))
+ if (!ci->last_topic.empty() && (show_all || ((!secret || !secret->set) && (!ci->c || !ci->c->HasMode("SECRET")))))
{
info[_("Last topic")] = ci->last_topic;
info[_("Topic set by")] = ci->last_topic_setter;
diff --git a/modules/commands/cs_unban.cpp b/modules/chanserv/cs_unban.cpp
index 1bc14695d..09dcee602 100644
--- a/modules/commands/cs_unban.cpp
+++ b/modules/chanserv/cs_unban.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandCSUnban : public Command
+class CommandCSUnban final
+ : public Command
{
- public:
+public:
CommandCSUnban(Module *creator) : Command(creator, "chanserv/unban", 0, 2)
{
this->SetDesc(_("Remove all bans preventing a user from entering a channel"));
this->SetSyntax(_("\037channel\037 [\037nick\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelMode *cm = ModeManager::FindChannelModeByName("BAN");
if (!cm)
@@ -38,17 +39,20 @@ class CommandCSUnban : public Command
source.GetAccount()->GetChannelReferences(queue);
unsigned count = 0;
- for (unsigned i = 0; i < queue.size(); ++i)
+ for (auto *ci : queue)
{
- ChannelInfo *ci = queue[i];
+ if (!ci->c || !(source.AccessFor(ci).HasPriv("UNBAN") || source.AccessFor(ci).HasPriv("UNBANME")))
+ continue;
- if (!ci->c || !source.AccessFor(ci).HasPriv("UNBAN"))
+ if (IRCD->CanClearBans)
+ {
+ IRCD->SendClearBans(ci->WhoSends(), ci->c, source.GetUser());
+ count++;
continue;
-
- FOREACH_MOD(OnChannelUnban, (source.GetUser(), ci));
+ }
- for (unsigned j = 0; j < modes.size(); ++j)
- if (ci->c->Unban(source.GetUser(), modes[j]->name, true))
+ for (const auto *mode : modes)
+ if (ci->c->Unban(source.GetUser(), mode->name, true))
++count;
}
@@ -71,12 +75,6 @@ class CommandCSUnban : public Command
return;
}
- if (!source.AccessFor(ci).HasPriv("UNBAN") && !source.HasPriv("chanserv/kick"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
User *u2 = source.GetUser();
if (params.size() > 1)
u2 = User::Find(params[1], true);
@@ -87,20 +85,33 @@ class CommandCSUnban : public Command
return;
}
+ if (!source.AccessFor(ci).HasPriv("UNBAN") &&
+ (u2 != source.GetUser() || !source.AccessFor(ci).HasPriv("UNBANME")) &&
+ !source.HasPriv("chanserv/kick"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
bool override = !source.AccessFor(ci).HasPriv("UNBAN") && source.HasPriv("chanserv/kick");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to unban " << u2->nick;
- FOREACH_MOD(OnChannelUnban, (u2, ci));
- for (unsigned i = 0; i < modes.size(); ++i)
- ci->c->Unban(u2, modes[i]->name, source.GetUser() == u2);
+ if (IRCD->CanClearBans)
+ IRCD->SendClearBans(ci->WhoSends(), ci->c, source.GetUser());
+ else
+ {
+ for (const auto *mode : modes)
+ ci->c->Unban(u2, mode->name, source.GetUser() == u2);
+ }
+
if (u2 == source.GetUser())
source.Reply(_("You have been unbanned from \002%s\002."), ci->c->name.c_str());
else
source.Reply(_("\002%s\002 has been unbanned from \002%s\002."), u2->nick.c_str(), ci->c->name.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -115,11 +126,12 @@ class CommandCSUnban : public Command
}
};
-class CSUnban : public Module
+class CSUnban final
+ : public Module
{
CommandCSUnban commandcsunban;
- public:
+public:
CSUnban(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsunban(this)
{
diff --git a/modules/commands/cs_updown.cpp b/modules/chanserv/cs_updown.cpp
index 074386795..28c35042d 100644
--- a/modules/commands/cs_updown.cpp
+++ b/modules/chanserv/cs_updown.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandCSUp : public Command
+class CommandCSUp final
+ : public Command
{
- void SetModes(User *u, Channel *c)
+ static void SetModes(User *u, Channel *c)
{
if (!c->ci)
return;
@@ -24,9 +25,8 @@ class CommandCSUp : public Command
bool given = false;
AccessGroup u_access = c->ci->AccessFor(u);
- for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i)
+ for (auto *cm : ModeManager::GetStatusChannelModesByRank())
{
- ChannelModeStatus *cm = ModeManager::GetStatusChannelModesByRank()[i];
bool has_priv = u_access.HasPriv("AUTO" + cm->name) || u_access.HasPriv(cm->name);
if (has_priv)
@@ -42,14 +42,14 @@ class CommandCSUp : public Command
}
}
}
- public:
+public:
CommandCSUp(Module *creator) : Command(creator, "chanserv/up", 0, 2)
{
this->SetDesc(_("Updates a selected nicks status on a channel"));
this->SetSyntax(_("[\037channel\037 [\037nick\037]]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (params.empty())
{
@@ -119,7 +119,7 @@ class CommandCSUp : public Command
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -130,9 +130,10 @@ class CommandCSUp : public Command
}
};
-class CommandCSDown : public Command
+class CommandCSDown final
+ : public Command
{
- void RemoveAll(User *u, Channel *c)
+ static void RemoveAll(User *u, Channel *c)
{
ChanUserContainer *cu = c->FindUser(u);
if (cu != NULL)
@@ -140,14 +141,14 @@ class CommandCSDown : public Command
c->RemoveMode(NULL, ModeManager::FindChannelModeByChar(cu->status.Modes()[--i]), u->GetUID());
}
- public:
+public:
CommandCSDown(Module *creator) : Command(creator, "chanserv/down", 0, 2)
{
this->SetDesc(_("Removes a selected nicks status from a channel"));
this->SetSyntax(_("[\037channel\037 [\037nick\037]]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (params.empty())
{
@@ -216,7 +217,7 @@ class CommandCSDown : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -227,12 +228,13 @@ class CommandCSDown : public Command
}
};
-class CSUpDown : public Module
+class CSUpDown final
+ : public Module
{
CommandCSUp commandcsup;
CommandCSDown commandcsdown;
- public:
+public:
CSUpDown(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandcsup(this), commandcsdown(this)
{
diff --git a/modules/commands/cs_xop.cpp b/modules/chanserv/cs_xop.cpp
index 059ed005d..55f8eb4bc 100644
--- a/modules/commands/cs_xop.cpp
+++ b/modules/chanserv/cs_xop.cpp
@@ -17,16 +17,17 @@ namespace
std::map<Anope::string, std::vector<Anope::string> > permissions;
}
-class XOPChanAccess : public ChanAccess
+class XOPChanAccess final
+ : public ChanAccess
{
- public:
+public:
Anope::string type;
XOPChanAccess(AccessProvider *p) : ChanAccess(p)
{
}
- bool HasPriv(const Anope::string &priv) const anope_override
+ bool HasPriv(const Anope::string &priv) const override
{
for (std::vector<Anope::string>::iterator it = std::find(order.begin(), order.end(), this->type); it != order.end(); ++it)
{
@@ -37,12 +38,12 @@ class XOPChanAccess : public ChanAccess
return false;
}
- Anope::string AccessSerialize() const anope_override
+ Anope::string AccessSerialize() const override
{
return this->type;
}
- void AccessUnserialize(const Anope::string &data) anope_override
+ void AccessUnserialize(const Anope::string &data) override
{
this->type = data;
}
@@ -58,48 +59,54 @@ class XOPChanAccess : public ChanAccess
{
std::map<Anope::string, int> count;
- for (std::map<Anope::string, std::vector<Anope::string> >::const_iterator it = permissions.begin(), it_end = permissions.end(); it != it_end; ++it)
+ for (const auto &[name, perms] : permissions)
{
- int &c = count[it->first];
- const std::vector<Anope::string> &perms = it->second;
- for (unsigned i = 0; i < perms.size(); ++i)
- if (access->HasPriv(perms[i]))
+ int &c = count[name];
+ for (const auto &perm : perms)
+ {
+ if (access->HasPriv(perm))
++c;
+ }
}
- Anope::string max;
- int maxn = 0;
- for (std::map<Anope::string, int>::iterator it = count.begin(), it_end = count.end(); it != it_end; ++it)
- if (it->second > maxn)
+ Anope::string maxname;
+ int maxpriv = 0;
+ for (const auto &[name, priv] : count)
+ {
+ if (priv > maxpriv)
{
- maxn = it->second;
- max = it->first;
+ maxname = name;
+ maxpriv = priv;
}
+ }
- return max;
+ return maxname;
}
}
};
-class XOPAccessProvider : public AccessProvider
+class XOPAccessProvider final
+ : public AccessProvider
{
- public:
+public:
XOPAccessProvider(Module *o) : AccessProvider(o, "access/xop")
{
}
- ChanAccess *Create() anope_override
+ ChanAccess *Create() override
{
return new XOPChanAccess(this);
}
};
-class CommandCSXOP : public Command
+class CommandCSXOP final
+ : public Command
{
- private:
+private:
void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
Anope::string mask = params.size() > 2 ? params[2] : "";
+ Anope::string description = params.size() > 3 ? params[3] : "";
if (mask.empty())
{
@@ -109,7 +116,7 @@ class CommandCSXOP : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -162,11 +169,21 @@ class CommandCSXOP : public Command
source.Reply(_("Masks and unregistered users may not be on access lists."));
return;
}
+ else if (na && na->nc->HasExt("NEVEROP"))
+ {
+ source.Reply(_("\002%s\002 does not wish to be added to channel access lists."),
+ na->nc->display.c_str());
+ return;
+ }
else if (mask.find_first_of("!*@") == Anope::string::npos && !na)
{
User *targ = User::Find(mask, true);
if (targ != NULL)
+ {
mask = "*!*@" + targ->GetDisplayedHost();
+ if (description.empty())
+ description = targ->nick;
+ }
else
{
source.Reply(NICK_X_NOT_REGISTERED, mask.c_str());
@@ -195,7 +212,7 @@ class CommandCSXOP : public Command
}
}
- unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
+ unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
if (access_max && ci->GetDeepAccessCount() >= access_max)
{
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
@@ -208,6 +225,7 @@ class CommandCSXOP : public Command
XOPChanAccess *acc = anope_dynamic_static_cast<XOPChanAccess *>(provider->Create());
acc->SetMask(mask, ci);
acc->creator = source.GetNick();
+ acc->description = description;
acc->type = source.command.upper();
acc->last_seen = 0;
acc->created = Anope::CurTime;
@@ -232,7 +250,7 @@ class CommandCSXOP : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -280,20 +298,21 @@ class CommandCSXOP : public Command
/* Special case: is it a number/list? Only do search if it isn't. */
if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class XOPDelCallback : public NumberList
+ class XOPDelCallback final
+ : public NumberList
{
CommandSource &source;
ChannelInfo *ci;
Command *c;
- unsigned deleted;
+ unsigned deleted = 0;
Anope::string nicks;
bool override;
- public:
- XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), override(_override)
+ public:
+ XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), override(_override)
{
}
- ~XOPDelCallback()
+ ~XOPDelCallback() override
{
if (!deleted)
source.Reply(_("No matching entries on %s %s list."), ci->name.c_str(), source.command.c_str());
@@ -308,7 +327,7 @@ class CommandCSXOP : public Command
}
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > ci->GetAccessCount())
return;
@@ -379,21 +398,22 @@ class CommandCSXOP : public Command
}
ListFormatter list(source.GetAccount());
- list.AddColumn(_("Number")).AddColumn(_("Mask"));
+ list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Description"));
if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class XOPListCallback : public NumberList
+ class XOPListCallback final
+ : public NumberList
{
ListFormatter &list;
ChannelInfo *ci;
CommandSource &source;
- public:
+ public:
XOPListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist, CommandSource &src) : NumberList(numlist, false), list(_list), ci(_ci), source(src)
{
}
- void HandleNumber(unsigned Number) anope_override
+ void HandleNumber(unsigned Number) override
{
if (!Number || Number > ci->GetAccessCount())
return;
@@ -404,8 +424,9 @@ class CommandCSXOP : public Command
return;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(Number);
+ entry["Number"] = Anope::ToString(Number);
entry["Mask"] = a->Mask();
+ entry["Description"] = a->description;
this->list.AddEntry(entry);
}
} nl_list(list, ci, nick, source);
@@ -423,8 +444,9 @@ class CommandCSXOP : public Command
continue;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Mask"] = a->Mask();
+ entry["Description"] = a->description;
list.AddEntry(entry);
}
}
@@ -437,8 +459,8 @@ class CommandCSXOP : public Command
list.Process(replies);
source.Reply(_("%s list for %s"), source.command.c_str(), ci->name.c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
@@ -446,7 +468,7 @@ class CommandCSXOP : public Command
{
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -480,21 +502,21 @@ class CommandCSXOP : public Command
source.Reply(_("Channel %s %s list has been cleared."), ci->name.c_str(), source.command.c_str());
}
- public:
+public:
CommandCSXOP(Module *modname) : Command(modname, "chanserv/xop", 2, 4)
{
- this->SetSyntax(_("\037channel\037 ADD \037mask\037"));
+ this->SetSyntax(_("\037channel\037 ADD \037mask\037 [\037description\037]"));
this->SetSyntax(_("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}"));
this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]"));
this->SetSyntax(_("\037channel\037 CLEAR"));
}
- const Anope::string GetDesc(CommandSource &source) const anope_override
+ const Anope::string GetDesc(CommandSource &source) const override
{
return Anope::printf(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.upper().c_str());
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (ci == NULL)
@@ -518,7 +540,7 @@ class CommandCSXOP : public Command
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
const Anope::string &cmd = source.command.upper();
@@ -529,9 +551,9 @@ class CommandCSXOP : public Command
" "), cmd.c_str(), cmd.c_str());
Anope::string buf;
- for (unsigned i = 0; i < permissions[cmd].size(); ++i)
+ for (const auto &permission : permissions[cmd])
{
- buf += ", " + permissions[cmd][i];
+ buf += ", " + permission;
if (buf.length() > 75)
{
source.Reply(" %s\n", buf.substr(2).c_str());
@@ -572,22 +594,23 @@ class CommandCSXOP : public Command
source.Reply(_("Alternative methods of modifying channel access lists are\n"
"available."));
if (!access_cmd.empty())
- source.Reply(_("See \002%s%s HELP %s\002 for more information\n"
- "about the access list."), Config->StrictPrivmsg.c_str(), access_bi->nick.c_str(), access_cmd.c_str());
+ source.Reply(_("See \002%s HELP %s\002 for more information\n"
+ "about the access list."), access_bi->GetQueryCommand().c_str(), access_cmd.c_str());
if (!flags_cmd.empty())
- source.Reply(_("See \002%s%s HELP %s\002 for more information\n"
- "about the flags system."), Config->StrictPrivmsg.c_str(), flags_bi->nick.c_str(), flags_cmd.c_str());
+ source.Reply(_("See \002%s HELP %s\002 for more information\n"
+ "about the flags system."), flags_bi->GetQueryCommand().c_str(), flags_cmd.c_str());
}
return true;
}
};
-class CSXOP : public Module
+class CSXOP final
+ : public Module
{
XOPAccessProvider accessprovider;
CommandCSXOP commandcsxop;
- public:
+public:
CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
accessprovider(this), commandcsxop(this)
{
@@ -595,7 +618,7 @@ class CSXOP : public Module
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
order.clear();
permissions.clear();
diff --git a/modules/extra/stats/m_chanstats.cpp b/modules/chanstats.cpp
index 794bd129f..05c745ff2 100644
--- a/modules/extra/stats/m_chanstats.cpp
+++ b/modules/chanstats.cpp
@@ -9,16 +9,17 @@
#include "module.h"
#include "modules/sql.h"
-class CommandCSSetChanstats : public Command
+class CommandCSSetChanstats final
+ : public Command
{
- public:
+public:
CommandCSSetChanstats(Module *creator) : Command(creator, "chanserv/set/chanstats", 2, 2)
{
this->SetDesc(_("Turn chanstats statistics on or off"));
this->SetSyntax(_("\037channel\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (!ci)
@@ -54,7 +55,7 @@ class CommandCSSetChanstats : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -63,9 +64,10 @@ class CommandCSSetChanstats : public Command
}
};
-class CommandNSSetChanstats : public Command
+class CommandNSSetChanstats
+ : public Command
{
- public:
+public:
CommandNSSetChanstats(Module *creator, const Anope::string &sname = "nickserv/set/chanstats", size_t min = 1 ) : Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Turn chanstats statistics on or off"));
@@ -107,12 +109,12 @@ class CommandNSSetChanstats : public Command
this->OnSyntaxError(source, "CHANSTATS");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, params[0]);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -121,21 +123,22 @@ class CommandNSSetChanstats : public Command
}
};
-class CommandNSSASetChanstats : public CommandNSSetChanstats
+class CommandNSSASetChanstats final
+ : public CommandNSSetChanstats
{
- public:
+public:
CommandNSSASetChanstats(Module *creator) : CommandNSSetChanstats(creator, "nickserv/saset/chanstats", 2)
{
this->ClearSyntax();
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, params[0], params[1], true);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -144,16 +147,17 @@ class CommandNSSASetChanstats : public CommandNSSetChanstats
}
};
-class MySQLInterface : public SQL::Interface
+class MySQLInterface final
+ : public SQL::Interface
{
- public:
+public:
MySQLInterface(Module *o) : SQL::Interface(o) { }
- void OnResult(const SQL::Result &r) anope_override
+ void OnResult(const SQL::Result &r) override
{
}
- void OnError(const SQL::Result &r) anope_override
+ void OnError(const SQL::Result &r) override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Chanstats: Error executing query " << r.finished_query << ": " << r.GetError();
@@ -162,7 +166,8 @@ class MySQLInterface : public SQL::Interface
}
};
-class MChanstats : public Module
+class MChanstats final
+ : public Module
{
SerializableExtensibleItem<bool> cs_stats, ns_stats;
@@ -184,14 +189,14 @@ class MChanstats : public Module
sql->Run(&sqlinterface, q);
}
- size_t CountWords(const Anope::string &msg)
+ static size_t CountWords(const Anope::string &msg)
{
size_t words = 0;
for (size_t pos = 0; pos != Anope::string::npos; pos = msg.find(" ", pos+1))
words++;
return words;
}
- size_t CountSmileys(const Anope::string &msg, const Anope::string &smileylist)
+ static size_t CountSmileys(const Anope::string &msg, const Anope::string &smileylist)
{
size_t smileys = 0;
spacesepstream sep(smileylist);
@@ -205,7 +210,7 @@ class MChanstats : public Module
return smileys;
}
- const Anope::string GetDisplay(User *u)
+ Anope::string GetDisplay(User *u)
{
if (u && u->IsIdentified() && ns_stats.HasExt(u->Account()))
return u->Account()->display;
@@ -273,45 +278,45 @@ class MChanstats : public Module
if (!this->HasTable(prefix +"chanstats"))
{
query = "CREATE TABLE `" + prefix + "chanstats` ("
- "`id` int(11) NOT NULL AUTO_INCREMENT,"
+ "`id` int NOT NULL AUTO_INCREMENT,"
"`chan` varchar(64) NOT NULL DEFAULT '',"
"`nick` varchar(64) NOT NULL DEFAULT '',"
"`type` ENUM('total', 'monthly', 'weekly', 'daily') NOT NULL,"
"`letters` bigint unsigned NOT NULL DEFAULT '0',"
"`words` bigint unsigned NOT NULL DEFAULT '0',"
- "`line` int(10) unsigned NOT NULL DEFAULT '0',"
- "`actions` int(10) unsigned NOT NULL DEFAULT '0',"
- "`smileys_happy` int(10) unsigned NOT NULL DEFAULT '0',"
- "`smileys_sad` int(10) unsigned NOT NULL DEFAULT '0',"
- "`smileys_other` int(10) unsigned NOT NULL DEFAULT '0',"
- "`kicks` int(10) unsigned NOT NULL DEFAULT '0',"
- "`kicked` int(10) unsigned NOT NULL DEFAULT '0',"
- "`modes` int(10) unsigned NOT NULL DEFAULT '0',"
- "`topics` int(10) unsigned NOT NULL DEFAULT '0',"
- "`time0` int(10) unsigned NOT NULL default '0',"
- "`time1` int(10) unsigned NOT NULL default '0',"
- "`time2` int(10) unsigned NOT NULL default '0',"
- "`time3` int(10) unsigned NOT NULL default '0',"
- "`time4` int(10) unsigned NOT NULL default '0',"
- "`time5` int(10) unsigned NOT NULL default '0',"
- "`time6` int(10) unsigned NOT NULL default '0',"
- "`time7` int(10) unsigned NOT NULL default '0',"
- "`time8` int(10) unsigned NOT NULL default '0',"
- "`time9` int(10) unsigned NOT NULL default '0',"
- "`time10` int(10) unsigned NOT NULL default '0',"
- "`time11` int(10) unsigned NOT NULL default '0',"
- "`time12` int(10) unsigned NOT NULL default '0',"
- "`time13` int(10) unsigned NOT NULL default '0',"
- "`time14` int(10) unsigned NOT NULL default '0',"
- "`time15` int(10) unsigned NOT NULL default '0',"
- "`time16` int(10) unsigned NOT NULL default '0',"
- "`time17` int(10) unsigned NOT NULL default '0',"
- "`time18` int(10) unsigned NOT NULL default '0',"
- "`time19` int(10) unsigned NOT NULL default '0',"
- "`time20` int(10) unsigned NOT NULL default '0',"
- "`time21` int(10) unsigned NOT NULL default '0',"
- "`time22` int(10) unsigned NOT NULL default '0',"
- "`time23` int(10) unsigned NOT NULL default '0',"
+ "`line` int unsigned NOT NULL DEFAULT '0',"
+ "`actions` int unsigned NOT NULL DEFAULT '0',"
+ "`smileys_happy` int unsigned NOT NULL DEFAULT '0',"
+ "`smileys_sad` int unsigned NOT NULL DEFAULT '0',"
+ "`smileys_other` int unsigned NOT NULL DEFAULT '0',"
+ "`kicks` int unsigned NOT NULL DEFAULT '0',"
+ "`kicked` int unsigned NOT NULL DEFAULT '0',"
+ "`modes` int unsigned NOT NULL DEFAULT '0',"
+ "`topics` int unsigned NOT NULL DEFAULT '0',"
+ "`time0` int unsigned NOT NULL default '0',"
+ "`time1` int unsigned NOT NULL default '0',"
+ "`time2` int unsigned NOT NULL default '0',"
+ "`time3` int unsigned NOT NULL default '0',"
+ "`time4` int unsigned NOT NULL default '0',"
+ "`time5` int unsigned NOT NULL default '0',"
+ "`time6` int unsigned NOT NULL default '0',"
+ "`time7` int unsigned NOT NULL default '0',"
+ "`time8` int unsigned NOT NULL default '0',"
+ "`time9` int unsigned NOT NULL default '0',"
+ "`time10` int unsigned NOT NULL default '0',"
+ "`time11` int unsigned NOT NULL default '0',"
+ "`time12` int unsigned NOT NULL default '0',"
+ "`time13` int unsigned NOT NULL default '0',"
+ "`time14` int unsigned NOT NULL default '0',"
+ "`time15` int unsigned NOT NULL default '0',"
+ "`time16` int unsigned NOT NULL default '0',"
+ "`time17` int unsigned NOT NULL default '0',"
+ "`time18` int unsigned NOT NULL default '0',"
+ "`time19` int unsigned NOT NULL default '0',"
+ "`time20` int unsigned NOT NULL default '0',"
+ "`time21` int unsigned NOT NULL default '0',"
+ "`time22` int unsigned NOT NULL default '0',"
+ "`time23` int unsigned NOT NULL default '0',"
"PRIMARY KEY (`id`),"
"UNIQUE KEY `chan` (`chan`,`nick`,`type`),"
"KEY `nick` (`nick`),"
@@ -327,9 +332,9 @@ class MChanstats : public Module
this->RunQuery(query);
}
query = "CREATE PROCEDURE `" + prefix + "chanstats_proc_update`"
- "(chan_ VARCHAR(255), nick_ VARCHAR(255), line_ INT(10), letters_ INT(10),"
- "words_ INT(10), actions_ INT(10), sm_h_ INT(10), sm_s_ INT(10), sm_o_ INT(10),"
- "kicks_ INT(10), kicked_ INT(10), modes_ INT(10), topics_ INT(10))"
+ "(chan_ VARCHAR(255), nick_ VARCHAR(255), line_ int, letters_ int,"
+ "words_ int, actions_ int, sm_h_ int, sm_s_ int, sm_o_ int,"
+ "kicks_ int, kicked_ int, modes_ int, topics_ int)"
"BEGIN "
"DECLARE time_ VARCHAR(20);"
"SET time_ = CONCAT('time', hour(now()));"
@@ -363,7 +368,7 @@ class MChanstats : public Module
query = "CREATE PROCEDURE `" + prefix + "chanstats_proc_chgdisplay`"
"(old_nick varchar(255), new_nick varchar(255))"
"BEGIN "
- "DECLARE res_count int(10) unsigned;"
+ "DECLARE res_count int unsigned;"
"SELECT COUNT(nick) INTO res_count FROM `" + prefix + "chanstats` WHERE nick = new_nick;"
"IF res_count = 0 THEN "
"UPDATE `" + prefix + "chanstats` SET `nick` = new_nick WHERE `nick` = old_nick;"
@@ -376,7 +381,7 @@ class MChanstats : public Module
"smileys_sad_, smileys_other_, kicks_, kicked_, modes_, topics_,"
"time0_, time1_, time2_, time3_, time4_, time5_, time6_, time7_, time8_, time9_,"
"time10_, time11_, time12_, time13_, time14_, time15_, time16_, time17_, time18_,"
- "time19_, time20_, time21_, time22_, time23_ INT(10) unsigned;"
+ "time19_, time20_, time21_, time22_, time23_ int unsigned;"
"DECLARE stats_cursor CURSOR FOR "
"SELECT chan, type, letters, words, line, actions, smileys_happy,"
"smileys_sad, smileys_other, kicks, kicked, modes, topics, time0, time1,"
@@ -483,7 +488,7 @@ class MChanstats : public Module
}
- public:
+public:
MChanstats(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, EXTRA | VENDOR),
cs_stats(this, "CS_STATS"), ns_stats(this, "NS_STATS"),
@@ -492,7 +497,7 @@ class MChanstats : public Module
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
prefix = block->Get<const Anope::string>("prefix", "anope_");
@@ -509,7 +514,7 @@ class MChanstats : public Module
Log(this) << "no database connection to " << engine;
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) override
{
if (!show_all)
return;
@@ -517,7 +522,7 @@ class MChanstats : public Module
info.AddOption(_("Chanstats"));
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
{
if (!show_hidden)
return;
@@ -525,7 +530,7 @@ class MChanstats : public Module
info.AddOption(_("Chanstats"));
}
- void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
+ void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override
{
if (!source || !source->IsIdentified() || !c->ci || !cs_stats.HasExt(c->ci))
return;
@@ -535,19 +540,19 @@ class MChanstats : public Module
this->RunQuery(query);
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override
{
this->OnModeChange(c, setter.GetUser());
return EVENT_CONTINUE;
}
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *, const Anope::string &param) anope_override
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *, const Anope::string &param) override
{
this->OnModeChange(c, setter.GetUser());
return EVENT_CONTINUE;
}
- private:
+private:
void OnModeChange(Channel *c, User *u)
{
if (!u || !u->IsIdentified() || !c->ci || !cs_stats.HasExt(c->ci))
@@ -559,8 +564,8 @@ class MChanstats : public Module
this->RunQuery(query);
}
- public:
- void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) anope_override
+public:
+ void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) override
{
if (!cu->chan->ci || !cs_stats.HasExt(cu->chan->ci))
return;
@@ -576,7 +581,7 @@ class MChanstats : public Module
this->RunQuery(query);
}
- void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
+ void OnPrivmsg(User *u, Channel *c, Anope::string &msg, const Anope::map<Anope::string> &tags) override
{
if (!c->ci || !cs_stats.HasExt(c->ci))
return;
@@ -617,14 +622,14 @@ class MChanstats : public Module
this->RunQuery(query);
}
- void OnDelCore(NickCore *nc) anope_override
+ void OnDelCore(NickCore *nc) override
{
query = "DELETE FROM `" + prefix + "chanstats` WHERE `nick` = @nick@;";
query.SetValue("nick", nc->display);
this->RunQuery(query);
}
- void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) anope_override
+ void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) override
{
query = "CALL " + prefix + "chanstats_proc_chgdisplay(@old_display@, @new_display@);";
query.SetValue("old_display", nc->display);
@@ -632,20 +637,20 @@ class MChanstats : public Module
this->RunQuery(query);
}
- void OnDelChan(ChannelInfo *ci) anope_override
+ void OnDelChan(ChannelInfo *ci) override
{
query = "DELETE FROM `" + prefix + "chanstats` WHERE `chan` = @channel@;";
query.SetValue("channel", ci->name);
this->RunQuery(query);
}
- void OnChanRegistered(ChannelInfo *ci)
+ void OnChanRegistered(ChannelInfo *ci) override
{
if (CSDefChanstats)
ci->Extend<bool>("CS_STATS");
}
- void OnNickRegister(User *user, NickAlias *na, const Anope::string &)
+ void OnNickRegister(User *user, NickAlias *na, const Anope::string &) override
{
if (NSDefChanstats)
na->nc->Extend<bool>("NS_STATS");
diff --git a/modules/commands/bs_botlist.cpp b/modules/commands/bs_botlist.cpp
deleted file mode 100644
index 43cbed955..000000000
--- a/modules/commands/bs_botlist.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/* BotServ core functions
- *
- * (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"
-
-class CommandBSBotList : public Command
-{
- public:
- CommandBSBotList(Module *creator) : Command(creator, "botserv/botlist", 0, 0)
- {
- this->SetDesc(_("Lists available bots"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- unsigned count = 0;
- ListFormatter list(source.GetAccount());
-
- list.AddColumn(_("Nick")).AddColumn(_("Mask"));
-
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- {
- BotInfo *bi = it->second;
-
- if (source.HasPriv("botserv/administration") || !bi->oper_only)
- {
- ++count;
- ListFormatter::ListEntry entry;
- entry["Nick"] = (bi->oper_only ? "* " : "") + bi->nick;
- entry["Mask"] = bi->GetIdent() + "@" + bi->host;
- list.AddEntry(entry);
- }
- }
-
- std::vector<Anope::string> replies;
- list.Process(replies);
-
- if (!count)
- source.Reply(_("There are no bots available at this time.\n"
- "Ask a Services Operator to create one!"));
- else
- {
- source.Reply(_("Bot list:"));
-
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
-
- source.Reply(_("%d bots available."), count);
- }
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Lists all available bots on this network.\n"
- "Bots prefixed by a * are reserved for IRC Operators."));
- return true;
- }
-};
-
-class BSBotList : public Module
-{
- CommandBSBotList commandbsbotlist;
-
- public:
- BSBotList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandbsbotlist(this)
- {
-
- }
-};
-
-MODULE_INIT(BSBotList)
diff --git a/modules/commands/gl_global.cpp b/modules/commands/gl_global.cpp
deleted file mode 100644
index 5ba992a50..000000000
--- a/modules/commands/gl_global.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Global core functions
- *
- * (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"
-
-class CommandGLGlobal : public Command
-{
- ServiceReference<GlobalService> GService;
-
- public:
- CommandGLGlobal(Module *creator) : Command(creator, "global/global", 1, 1), GService("GlobalService", "Global")
- {
- this->SetDesc(_("Send a message to all users"));
- this->SetSyntax(_("\037message\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &msg = params[0];
-
- if (!GService)
- source.Reply("No global reference, is global loaded?");
- else
- {
- Log(LOG_ADMIN, source, this);
- GService->SendGlobal(NULL, source.GetNick(), msg);
- }
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- Reference<BotInfo> sender;
- if (GService)
- sender = GService->GetDefaultSender();
- if (!sender)
- sender = source.service;
-
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Allows Administrators to send messages to all users on the\n"
- "network. The message will be sent from the nick \002%s\002."), sender->nick.c_str());
- return true;
- }
-};
-
-class GLGlobal : public Module
-{
- CommandGLGlobal commandglglobal;
-
- public:
- GLGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandglglobal(this)
- {
-
- }
-};
-
-MODULE_INIT(GLGlobal)
diff --git a/modules/commands/ns_access.cpp b/modules/commands/ns_access.cpp
deleted file mode 100644
index 23e81ccc9..000000000
--- a/modules/commands/ns_access.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/* NickServ core functions
- *
- * (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"
-
-class CommandNSAccess : public Command
-{
- private:
- void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask)
- {
- if (mask.empty())
- {
- this->OnSyntaxError(source, "ADD");
- return;
- }
-
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- if (nc->access.size() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax", "32"))
- {
- source.Reply(_("Sorry, the maximum of %d access entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("accessmax"));
- return;
- }
-
- if (nc->FindAccess(mask))
- {
- source.Reply(_("Mask \002%s\002 already present on %s's access list."), mask.c_str(), nc->display.c_str());
- return;
- }
-
- nc->AddAccess(mask);
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD mask " << mask << " to " << nc->display;
- source.Reply(_("\002%s\002 added to %s's access list."), mask.c_str(), nc->display.c_str());
-
- return;
- }
-
- void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask)
- {
- if (mask.empty())
- {
- this->OnSyntaxError(source, "DEL");
- return;
- }
-
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- if (!nc->FindAccess(mask))
- {
- source.Reply(_("\002%s\002 not found on %s's access list."), mask.c_str(), nc->display.c_str());
- return;
- }
-
- nc->EraseAccess(mask);
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE mask " << mask << " from " << nc->display;
- source.Reply(_("\002%s\002 deleted from %s's access list."), mask.c_str(), nc->display.c_str());
-
- return;
- }
-
- void DoList(CommandSource &source, NickCore *nc, const Anope::string &mask)
- {
- unsigned i, end;
-
- if (nc->access.empty())
- {
- source.Reply(_("%s's access list is empty."), nc->display.c_str());
- return;
- }
-
- source.Reply(_("Access list for %s:"), nc->display.c_str());
- for (i = 0, end = nc->access.size(); i < end; ++i)
- {
- Anope::string access = nc->GetAccess(i);
- if (!mask.empty() && !Anope::Match(access, mask))
- continue;
- source.Reply(" %s", access.c_str());
- }
-
- return;
- }
- public:
- CommandNSAccess(Module *creator) : Command(creator, "nickserv/access", 1, 3)
- {
- this->SetDesc(_("Modify the list of authorized addresses"));
- this->SetSyntax(_("ADD [\037nickname\037] \037mask\037"));
- this->SetSyntax(_("DEL [\037nickname\037] \037mask\037"));
- this->SetSyntax(_("LIST [\037nickname\037]"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &cmd = params[0];
- Anope::string nick, mask;
-
- if (cmd.equals_ci("LIST"))
- nick = params.size() > 1 ? params[1] : "";
- else
- {
- nick = params.size() == 3 ? params[1] : "";
- mask = params.size() > 1 ? params[params.size() - 1] : "";
- }
-
- NickCore *nc;
- if (!nick.empty())
- {
- const NickAlias *na = NickAlias::Find(nick);
- if (na == NULL)
- {
- source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
- return;
- }
- else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
- else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->nc && na->nc->IsServicesOper() && !cmd.equals_ci("LIST"))
- {
- source.Reply(_("You may view but not modify the access list of other Services Operators."));
- return;
- }
-
- nc = na->nc;
- }
- else
- nc = source.nc;
-
- if (!mask.empty() && (mask.find('@') == Anope::string::npos || mask.find('!') != Anope::string::npos))
- {
- source.Reply(BAD_USERHOST_MASK);
- source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
- }
- else if (cmd.equals_ci("LIST"))
- return this->DoList(source, nc, mask);
- else if (nc->HasExt("NS_SUSPENDED"))
- source.Reply(NICK_X_SUSPENDED, nc->display.c_str());
- else if (cmd.equals_ci("ADD"))
- return this->DoAdd(source, nc, mask);
- else if (cmd.equals_ci("DEL"))
- return this->DoDel(source, nc, mask);
- else
- this->OnSyntaxError(source, "");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Modifies or displays the access list for your nick. This\n"
- "is the list of addresses which will be automatically\n"
- "recognized by %s as allowed to use the nick. If\n"
- "you want to use the nick from a different address, you\n"
- "need to send an \002IDENTIFY\002 command to make %s\n"
- "recognize you. Services Operators may provide a nick\n"
- "to modify other users' access lists.\n"
- " \n"
- "Examples:\n"
- " \n"
- " \002ACCESS ADD anyone@*.bepeg.com\002\n"
- " Allows access to user \002anyone\002 from any machine in\n"
- " the \002bepeg.com\002 domain.\n"
- " \n"
- " \002ACCESS DEL anyone@*.bepeg.com\002\n"
- " Reverses the previous command.\n"
- " \n"
- " \002ACCESS LIST\002\n"
- " Displays the current access list."), source.service->nick.c_str(), source.service->nick.c_str());
- return true;
- }
-};
-
-class NSAccess : public Module
-{
- CommandNSAccess commandnsaccess;
-
- public:
- NSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsaccess(this)
- {
- }
-
- void OnNickRegister(User *u, NickAlias *na, const Anope::string &) anope_override
- {
- if (u && Config->GetModule(this)->Get<bool>("addaccessonreg"))
- na->nc->AddAccess(u->Mask());
- }
-};
-
-MODULE_INIT(NSAccess)
diff --git a/modules/commands/ns_drop.cpp b/modules/commands/ns_drop.cpp
deleted file mode 100644
index 486ac1d4b..000000000
--- a/modules/commands/ns_drop.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/* NickServ core functions
- *
- * (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"
-
-class CommandNSDrop : public Command
-{
- public:
- CommandNSDrop(Module *creator) : Command(creator, "nickserv/drop", 1, 1)
- {
- this->SetSyntax(_("\037nickname\037"));
- this->SetDesc(_("Cancel the registration of a nickname"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &nick = params[0];
-
- if (Anope::ReadOnly && !source.HasPriv("nickserv/drop"))
- {
- source.Reply(_("Sorry, nickname de-registration is temporarily disabled."));
- return;
- }
-
- NickAlias *na = NickAlias::Find(nick);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
- return;
- }
-
- bool is_mine = source.GetAccount() == na->nc;
-
- if (!is_mine && !source.HasPriv("nickserv/drop"))
- source.Reply(ACCESS_DENIED);
- else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && !is_mine && na->nc->IsServicesOper())
- source.Reply(_("You may not drop other Services Operators' nicknames."));
- else
- {
- FOREACH_MOD(OnNickDrop, (source, na));
-
- Log(!is_mine ? LOG_ADMIN : LOG_COMMAND, source, this) << "to drop nickname " << na->nick << " (group: " << na->nc->display << ") (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
- delete na;
-
- source.Reply(_("Nickname \002%s\002 has been dropped."), nick.c_str());
- }
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Drops the given nick from the database. Once your nickname\n"
- "is dropped you may lose all of your access and channels that\n"
- "you may own. Any other user will be able to gain control of\n"
- "this nick."));
- if (!source.HasPriv("nickserv/drop"))
- source.Reply(_("You may drop any nick within your group."));
- else
- source.Reply(_("As a Services Operator, you may drop any nick."));
-
- return true;
- }
-};
-
-class NSDrop : public Module
-{
- CommandNSDrop commandnsdrop;
-
- public:
- NSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsdrop(this)
- {
-
- }
-};
-
-MODULE_INIT(NSDrop)
diff --git a/modules/commands/ns_getpass.cpp b/modules/commands/ns_getpass.cpp
deleted file mode 100644
index 97f7050f0..000000000
--- a/modules/commands/ns_getpass.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/* NickServ core functions
- *
- * (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"
-
-class CommandNSGetPass : public Command
-{
- public:
- CommandNSGetPass(Module *creator) : Command(creator, "nickserv/getpass", 1, 1)
- {
- this->SetDesc(_("Retrieve the password for a nickname"));
- this->SetSyntax(_("\037nickname\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &nick = params[0];
- Anope::string tmp_pass;
- const NickAlias *na;
-
- if (!(na = NickAlias::Find(nick)))
- source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
- else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && na->nc->IsServicesOper())
- source.Reply(_("You may not get the password of other Services Operators."));
- else
- {
- if (Anope::Decrypt(na->nc->pass, tmp_pass) == 1)
- {
- Log(LOG_ADMIN, source, this) << "for " << nick;
- source.Reply(_("Password for %s is \002%s\002."), nick.c_str(), tmp_pass.c_str());
- }
- else
- source.Reply(_("GETPASS command unavailable because encryption is in use."));
- }
- return;
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Returns the password for the given nickname. \002Note\002 that\n"
- "whenever this command is used, a message including the\n"
- "person who issued the command and the nickname it was used\n"
- "on will be logged and sent out as a WALLOPS/GLOBOPS."));
- return true;
- }
-};
-
-class NSGetPass : public Module
-{
- CommandNSGetPass commandnsgetpass;
-
- public:
- NSGetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsgetpass(this)
- {
-
- Anope::string tmp_pass = "plain:tmp";
- if (!Anope::Decrypt(tmp_pass, tmp_pass))
- throw ModuleException("Incompatible with the encryption module being used");
-
- }
-};
-
-MODULE_INIT(NSGetPass)
diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp
deleted file mode 100644
index ce455cad7..000000000
--- a/modules/commands/ns_set.cpp
+++ /dev/null
@@ -1,1350 +0,0 @@
-/* NickServ core functions
- *
- * (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"
-
-class CommandNSSet : public Command
-{
- public:
- CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3)
- {
- this->SetDesc(_("Set options, including kill protection"));
- this->SetSyntax(_("\037option\037 \037parameters\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->OnSyntaxError(source, "");
- return;
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Sets various nickname options. \037option\037 can be one of:"));
-
- Anope::string this_name = source.command;
- bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
- hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
- for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
- {
- const Anope::string &c_name = it->first;
- const CommandInfo &info = it->second;
-
- if (c_name.find_ci(this_name + " ") == 0)
- {
- if (info.hide)
- continue;
-
- ServiceReference<Command> c("Command", info.name);
- // XXX dup
- if (!c)
- continue;
- else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
- continue;
- else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
- continue;
-
- source.command = c_name;
- c->OnServHelp(source);
- }
- }
-
- source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
- "on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
-
- return true;
- }
-};
-
-class CommandNSSASet : public Command
-{
- public:
- CommandNSSASet(Module *creator) : Command(creator, "nickserv/saset", 2, 4)
- {
- this->SetDesc(_("Set SET-options on another nickname"));
- this->SetSyntax(_("\037option\037 \037nickname\037 \037parameters\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->OnSyntaxError(source, "");
- return;
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Sets various nickname options. \037option\037 can be one of:"));
-
- Anope::string this_name = source.command;
- for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
- {
- const Anope::string &c_name = it->first;
- const CommandInfo &info = it->second;
-
- if (c_name.find_ci(this_name + " ") == 0)
- {
- ServiceReference<Command> command("Command", info.name);
- if (command)
- {
- source.command = c_name;
- command->OnServHelp(source);
- }
- }
- }
-
- source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n"
- "on a specific option. The options will be set on the given\n"
- "\037nickname\037."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str());
- return true;
- }
-};
-
-class CommandNSSetPassword : public Command
-{
- public:
- CommandNSSetPassword(Module *creator) : Command(creator, "nickserv/set/password", 1)
- {
- this->SetDesc(_("Set your nickname password"));
- this->SetSyntax(_("\037new-password\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &param = params[0];
- unsigned len = param.length();
-
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- if (source.GetNick().equals_ci(param) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
- {
- source.Reply(MORE_OBSCURE_PASSWORD);
- return;
- }
-
- unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
- if (len > passlen)
- {
- source.Reply(PASSWORD_TOO_LONG, passlen);
- return;
- }
-
- Log(LOG_COMMAND, source, this) << "to change their password";
-
- Anope::Encrypt(param, source.nc->pass);
- Anope::string tmp_pass;
- if (Anope::Decrypt(source.nc->pass, tmp_pass) == 1)
- source.Reply(_("Password for \002%s\002 changed to \002%s\002."), source.nc->display.c_str(), tmp_pass.c_str());
- else
- source.Reply(_("Password for \002%s\002 changed."), source.nc->display.c_str());
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Changes the password used to identify you as the nick's\n"
- "owner."));
- return true;
- }
-};
-
-class CommandNSSASetPassword : public Command
-{
- public:
- CommandNSSASetPassword(Module *creator) : Command(creator, "nickserv/saset/password", 2, 2)
- {
- this->SetDesc(_("Set the nickname password"));
- this->SetSyntax(_("\037nickname\037 \037new-password\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *setter_na = NickAlias::Find(params[0]);
- if (setter_na == NULL)
- {
- source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
- NickCore *nc = setter_na->nc;
-
- size_t len = params[1].length();
-
- if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper())
- {
- source.Reply(_("You may not change the password of other Services Operators."));
- return;
- }
-
- if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
- {
- source.Reply(MORE_OBSCURE_PASSWORD);
- return;
- }
-
- unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
- if (len > passlen)
- {
- source.Reply(PASSWORD_TOO_LONG, passlen);
- return;
- }
-
- Log(LOG_ADMIN, source, this) << "to change the password of " << nc->display;
-
- Anope::Encrypt(params[1], nc->pass);
- Anope::string tmp_pass;
- if (Anope::Decrypt(nc->pass, tmp_pass) == 1)
- source.Reply(_("Password for \002%s\002 changed to \002%s\002."), nc->display.c_str(), tmp_pass.c_str());
- else
- source.Reply(_("Password for \002%s\002 changed."), nc->display.c_str());
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Changes the password used to identify as the nick's owner."));
- return true;
- }
-};
-
-class CommandNSSetAutoOp : public Command
-{
- public:
- CommandNSSetAutoOp(Module *creator, const Anope::string &sname = "nickserv/set/autoop", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Sets whether services should set channel status modes on you automatically."));
- this->SetSyntax("{ON | OFF}");
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (na == NULL)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable autoop for " << na->nc->display;
- nc->Extend<bool>("AUTOOP");
- source.Reply(_("Services will from now on set status modes on %s in channels."), nc->display.c_str());
- }
- else if (param.equals_ci("OFF"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable autoop for " << na->nc->display;
- nc->Shrink<bool>("AUTOOP");
- source.Reply(_("Services will no longer set status modes on %s in channels."), nc->display.c_str());
- }
- else
- this->OnSyntaxError(source, "AUTOOP");
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- BotInfo *bi = Config->GetClient("ChanServ");
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Sets whether you will be given your channel status modes automatically.\n"
- "Set to \002ON\002 to allow %s to set status modes on you automatically\n"
- "when entering channels. Note that depending on channel settings some modes\n"
- "may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ");
- return true;
- }
-};
-
-class CommandNSSASetAutoOp : public CommandNSSetAutoOp
-{
- public:
- CommandNSSASetAutoOp(Module *creator) : CommandNSSetAutoOp(creator, "nickserv/saset/autoop", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- BotInfo *bi = Config->GetClient("ChanServ");
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Sets whether the given nickname will be given its status modes\n"
- "in channels automatically. Set to \002ON\002 to allow %s\n"
- "to set status modes on the given nickname automatically when it\n"
- "is entering channels. Note that depending on channel settings\n"
- "some modes may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ");
- return true;
- }
-};
-
-class CommandNSSetDisplay : public Command
-{
- public:
- CommandNSSetDisplay(Module *creator, const Anope::string &sname = "nickserv/set/display", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Set the display of your group in Services"));
- this->SetSyntax(_("\037new-display\037"));
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- NickAlias *user_na = NickAlias::Find(user), *na = NickAlias::Find(param);
-
- if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
- {
- source.Reply(_("This command may not be used on this network because nickname ownership is disabled."));
- return;
- }
- if (user_na == NULL)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- else if (!na || *na->nc != *user_na->nc)
- {
- source.Reply(_("The new display MUST be a nickname of the nickname group %s."), user_na->nc->display.c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, user_na->nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- Log(user_na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the display of " << user_na->nc->display << " to " << na->nick;
-
- user_na->nc->SetDisplay(na);
-
- /* Send updated account name */
- for (std::list<User *>::iterator it = user_na->nc->users.begin(); it != user_na->nc->users.end(); ++it)
- {
- User *u = *it;
- IRCD->SendLogin(u, user_na);
- }
-
- source.Reply(NICK_SET_DISPLAY_CHANGED, user_na->nc->display.c_str());
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Changes the display used to refer to your nickname group in\n"
- "Services. The new display MUST be a nick of your group."));
- return true;
- }
-};
-
-class CommandNSSASetDisplay : public CommandNSSetDisplay
-{
- public:
- CommandNSSASetDisplay(Module *creator) : CommandNSSetDisplay(creator, "nickserv/saset/display", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 \037new-display\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Changes the display used to refer to the nickname group in\n"
- "Services. The new display MUST be a nick of the group."));
- return true;
- }
-};
-
-class CommandNSSetEmail : public Command
-{
- static bool SendConfirmMail(User *u, NickCore *nc, BotInfo *bi, const Anope::string &new_email)
- {
- Anope::string code = Anope::Random(9);
-
- std::pair<Anope::string, Anope::string> *n = nc->Extend<std::pair<Anope::string, Anope::string> >("ns_set_email");
- n->first = new_email;
- n->second = code;
-
- Anope::string subject = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_subject"),
- message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message");
-
- subject = subject.replace_all_cs("%e", nc->email);
- subject = subject.replace_all_cs("%E", new_email);
- subject = subject.replace_all_cs("%n", nc->display);
- subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
- subject = subject.replace_all_cs("%c", code);
-
- message = message.replace_all_cs("%e", nc->email);
- message = message.replace_all_cs("%E", new_email);
- message = message.replace_all_cs("%n", nc->display);
- message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
- message = message.replace_all_cs("%c", code);
-
- Anope::string old = nc->email;
- nc->email = new_email;
- bool b = Mail::Send(u, nc, bi, subject, message);
- nc->email = old;
- return b;
- }
-
- public:
- CommandNSSetEmail(Module *creator, const Anope::string &cname = "nickserv/set/email", size_t min = 0) : Command(creator, cname, min, min + 1)
- {
- this->SetDesc(_("Associate an E-mail address with your nickname"));
- this->SetSyntax(_("\037address\037"));
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- if (nc->HasExt("UNCONFIRMED"))
- {
- source.Reply(_("You may not change the email of an unconfirmed account."));
- return;
- }
-
- if (param.empty() && Config->GetModule("nickserv")->Get<bool>("forceemail", "yes"))
- {
- source.Reply(_("You cannot unset the e-mail on this network."));
- return;
- }
- else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper())
- {
- source.Reply(_("You may not change the e-mail of other Services Operators."));
- return;
- }
- else if (!param.empty() && !Mail::Validate(param))
- {
- source.Reply(MAIL_X_INVALID, param.c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (!param.empty() && Config->GetModule("nickserv")->Get<bool>("confirmemailchanges") && !source.IsServicesOper())
- {
- if (SendConfirmMail(source.GetUser(), source.GetAccount(), source.service, param))
- {
- Log(LOG_COMMAND, source, this) << "to request changing the email of " << nc->display << " to " << param;
- source.Reply(_("A confirmation e-mail has been sent to \002%s\002. Follow the instructions in it to change your e-mail address."), param.c_str());
- }
- }
- else
- {
- if (!param.empty())
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the email of " << nc->display << " to " << param;
- nc->email = param;
- source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
- }
- else
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the email of " << nc->display;
- nc->email.clear();
- source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str());
- }
- }
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params.size() ? params[0] : "");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Associates the given E-mail address with your nickname.\n"
- "This address will be displayed whenever someone requests\n"
- "information on the nickname with the \002INFO\002 command."));
- return true;
- }
-};
-
-class CommandNSSASetEmail : public CommandNSSetEmail
-{
- public:
- CommandNSSASetEmail(Module *creator) : CommandNSSetEmail(creator, "nickserv/saset/email", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 \037address\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params.size() > 1 ? params[1] : "");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Associates the given E-mail address with the nickname."));
- return true;
- }
-};
-
-class CommandNSSetKeepModes : public Command
-{
- public:
- CommandNSSetKeepModes(Module *creator, const Anope::string &sname = "nickserv/set/keepmodes", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Enable or disable keep modes"));
- this->SetSyntax("{ON | OFF}");
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable keepmodes for " << nc->display;
- nc->Extend<bool>("NS_KEEP_MODES");
- source.Reply(_("Keep modes for %s is now \002on\002."), nc->display.c_str());
- }
- else if (param.equals_ci("OFF"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable keepmodes for " << nc->display;
- nc->Shrink<bool>("NS_KEEP_MODES");
- source.Reply(_("Keep modes for %s is now \002off\002."), nc->display.c_str());
- }
- else
- this->OnSyntaxError(source, "");
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Enables or disables keepmodes for your nick. If keep\n"
- "modes is enabled, services will remember your usermodes\n"
- "and attempt to re-set them the next time you authenticate."));
- return true;
- }
-};
-
-class CommandNSSASetKeepModes : public CommandNSSetKeepModes
-{
- public:
- CommandNSSASetKeepModes(Module *creator) : CommandNSSetKeepModes(creator, "nickserv/saset/keepmodes", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Enables or disables keepmodes for the given nick. If keep\n"
- "modes is enabled, services will remember users' usermodes\n"
- "and attempt to re-set them the next time they authenticate."));
- return true;
- }
-};
-
-class CommandNSSetKill : public Command
-{
- public:
- CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Turn protection on or off"));
- this->SetSyntax("{ON | QUICK | IMMED | OFF}");
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
- {
- source.Reply(_("This command may not be used on this network because nickname ownership is disabled."));
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- nc->Extend<bool>("KILLPROTECT");
- nc->Shrink<bool>("KILL_QUICK");
- nc->Shrink<bool>("KILL_IMMED");
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display;
- source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str());
- }
- else if (param.equals_ci("QUICK"))
- {
- nc->Extend<bool>("KILLPROTECT");
- nc->Extend<bool>("KILL_QUICK");
- nc->Shrink<bool>("KILL_IMMED");
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display;
- source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str());
- }
- else if (param.equals_ci("IMMED"))
- {
- if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed"))
- {
- nc->Extend<bool>("KILLPROTECT");
- nc->Shrink<bool>("KILL_QUICK");
- nc->Extend<bool>("KILL_IMMED");
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display;
- source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str());
- }
- else
- source.Reply(_("The \002IMMED\002 option is not available on this network."));
- }
- else if (param.equals_ci("OFF"))
- {
- nc->Shrink<bool>("KILLPROTECT");
- nc->Shrink<bool>("KILL_QUICK");
- nc->Shrink<bool>("KILL_IMMED");
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display;
- source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str());
- }
- else
- this->OnSyntaxError(source, "KILL");
-
- return;
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns the automatic protection option for your nick\n"
- "on or off. With protection on, if another user\n"
- "tries to take your nick, they will be given one minute to\n"
- "change to another nick, after which %s will forcibly change\n"
- "their nick.\n"
- " \n"
- "If you select \002QUICK\002, the user will be given only 20 seconds\n"
- "to change nicks instead of the usual 60. If you select\n"
- "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
- "warned first or given a chance to change their nick; please\n"
- "do not use this option unless necessary. Also, your\n"
- "network's administrators may have disabled this option."), source.service->nick.c_str());
- return true;
- }
-};
-
-class CommandNSSASetKill : public CommandNSSetKill
-{
- public:
- CommandNSSASetKill(Module *creator) : CommandNSSetKill(creator, "nickserv/saset/kill", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns the automatic protection option for the nick\n"
- "on or off. With protection on, if another user\n"
- "tries to take the nick, they will be given one minute to\n"
- "change to another nick, after which %s will forcibly change\n"
- "their nick.\n"
- " \n"
- "If you select \002QUICK\002, the user will be given only 20 seconds\n"
- "to change nicks instead of the usual 60. If you select\n"
- "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
- "warned first or given a chance to change their nick; please\n"
- "do not use this option unless necessary. Also, your\n"
- "network's administrators may have disabled this option."), source.service->nick.c_str());
- return true;
- }
-};
-
-class CommandNSSetLanguage : public Command
-{
- public:
- CommandNSSetLanguage(Module *creator, const Anope::string &sname = "nickserv/set/language", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Set the language Services will use when messaging you"));
- this->SetSyntax(_("\037language\037"));
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param != "en_US")
- for (unsigned j = 0; j < Language::Languages.size(); ++j)
- {
- if (Language::Languages[j] == param)
- break;
- else if (j + 1 == Language::Languages.size())
- {
- this->OnSyntaxError(source, "");
- return;
- }
- }
-
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << param;
-
- nc->language = param;
- if (source.GetAccount() == nc)
- source.Reply(_("Language changed to \002English\002."));
- else
- source.Reply(_("Language for \002%s\002 changed to \002%s\002."), nc->display.c_str(), Language::Translate(param.c_str(), _("English")));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &param) anope_override
- {
- this->Run(source, source.nc->display, param[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Changes the language Services uses when sending messages to\n"
- "you (for example, when responding to a command you send).\n"
- "\037language\037 should be chosen from the following list of\n"
- "supported languages:"));
-
- source.Reply(" en_US (English)");
- for (unsigned j = 0; j < Language::Languages.size(); ++j)
- {
- const Anope::string &langname = Language::Translate(Language::Languages[j].c_str(), _("English"));
- if (langname == "English")
- continue;
- source.Reply(" %s (%s)", Language::Languages[j].c_str(), langname.c_str());
- }
-
- return true;
- }
-};
-
-class CommandNSSASetLanguage : public CommandNSSetLanguage
-{
- public:
- CommandNSSASetLanguage(Module *creator) : CommandNSSetLanguage(creator, "nickserv/saset/language", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 \037language\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Changes the language Services uses when sending messages to\n"
- "the given user (for example, when responding to a command they send).\n"
- "\037language\037 should be chosen from the following list of\n"
- "supported languages:"));
- source.Reply(" en (English)");
- for (unsigned j = 0; j < Language::Languages.size(); ++j)
- {
- const Anope::string &langname = Language::Translate(Language::Languages[j].c_str(), _("English"));
- if (langname == "English")
- continue;
- source.Reply(" %s (%s)", Language::Languages[j].c_str(), langname.c_str());
- }
- return true;
- }
-};
-
-class CommandNSSetMessage : public Command
-{
- public:
- CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Change the communication method of Services"));
- this->SetSyntax("{ON | OFF}");
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- if (!Config->GetBlock("options")->Get<bool>("useprivmsg"))
- {
- source.Reply(_("You cannot %s on this network."), source.command.c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
- nc->Extend<bool>("MSG");
- source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
- }
- else if (param.equals_ci("OFF"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
- nc->Shrink<bool>("MSG");
- source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
- }
- else
- this->OnSyntaxError(source, "MSG");
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- Anope::string cmd = source.command;
- size_t i = cmd.find_last_of(' ');
- if (i != Anope::string::npos)
- cmd = cmd.substr(i + 1);
-
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Allows you to choose the way Services are communicating with\n"
- "you. With \002%s\002 set, Services will use messages, else they'll\n"
- "use notices."), cmd.upper().c_str());
- return true;
- }
-
- void OnServHelp(CommandSource &source) anope_override
- {
- if (Config->GetBlock("options")->Get<bool>("useprivmsg"))
- Command::OnServHelp(source);
- }
-};
-
-class CommandNSSASetMessage : public CommandNSSetMessage
-{
- public:
- CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Allows you to choose the way Services are communicating with\n"
- "the given user. With \002MSG\002 set, Services will use messages,\n"
- "else they'll use notices."));
- return true;
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-};
-
-class CommandNSSetSecure : public Command
-{
- public:
- CommandNSSetSecure(Module *creator, const Anope::string &sname = "nickserv/set/secure", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Turn nickname security on or off"));
- this->SetSyntax("{ON | OFF}");
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable secure for " << nc->display;
- nc->Extend<bool>("NS_SECURE");
- source.Reply(_("Secure option is now \002on\002 for \002%s\002."), nc->display.c_str());
- }
- else if (param.equals_ci("OFF"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable secure for " << nc->display;
- nc->Shrink<bool>("NS_SECURE");
- source.Reply(_("Secure option is now \002off\002 for \002%s\002."), nc->display.c_str());
- }
- else
- this->OnSyntaxError(source, "SECURE");
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns %s's security features on or off for your\n"
- "nick. With \002SECURE\002 set, you must enter your password\n"
- "before you will be recognized as the owner of the nick,\n"
- "regardless of whether your address is on the access\n"
- "list. However, if you are on the access list, %s\n"
- "will not auto-kill you regardless of the setting of the\n"
- "\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str());
- return true;
- }
-};
-
-class CommandNSSASetSecure : public CommandNSSetSecure
-{
- public:
- CommandNSSASetSecure(Module *creator) : CommandNSSetSecure(creator, "nickserv/saset/secure", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns %s's security features on or off for your\n"
- "nick. With \002SECURE\002 set, you must enter your password\n"
- "before you will be recognized as the owner of the nick,\n"
- "regardless of whether your address is on the access\n"
- "list. However, if you are on the access list, %s\n"
- "will not auto-kill you regardless of the setting of the\n"
- "\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str());
- return true;
- }
-};
-
-class CommandNSSASetNoexpire : public Command
-{
- public:
- CommandNSSASetNoexpire(Module *creator) : Command(creator, "nickserv/saset/noexpire", 1, 2)
- {
- this->SetDesc(_("Prevent the nickname from expiring"));
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (Anope::ReadOnly)
- {
- source.Reply(READ_ONLY_MODE);
- return;
- }
-
- NickAlias *na = NickAlias::Find(params[0]);
- if (na == NULL)
- {
- source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- Anope::string param = params.size() > 1 ? params[1] : "";
-
- if (param.equals_ci("ON"))
- {
- Log(LOG_ADMIN, source, this) << "to enable noexpire for " << na->nick << " (" << na->nc->display << ")";
- na->Extend<bool>("NS_NO_EXPIRE");
- source.Reply(_("Nick %s \002will not\002 expire."), na->nick.c_str());
- }
- else if (param.equals_ci("OFF"))
- {
- Log(LOG_ADMIN, source, this) << "to disable noexpire for " << na->nick << " (" << na->nc->display << ")";
- na->Shrink<bool>("NS_NO_EXPIRE");
- source.Reply(_("Nick %s \002will\002 expire."), na->nick.c_str());
- }
- else
- this->OnSyntaxError(source, "NOEXPIRE");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Sets whether the given nickname will expire. Setting this\n"
- "to \002ON\002 prevents the nickname from expiring."));
- return true;
- }
-};
-
-class NSSet : public Module
-{
- CommandNSSet commandnsset;
- CommandNSSASet commandnssaset;
-
- CommandNSSetAutoOp commandnssetautoop;
- CommandNSSASetAutoOp commandnssasetautoop;
-
- CommandNSSetDisplay commandnssetdisplay;
- CommandNSSASetDisplay commandnssasetdisplay;
-
- CommandNSSetEmail commandnssetemail;
- CommandNSSASetEmail commandnssasetemail;
-
- CommandNSSetKeepModes commandnssetkeepmodes;
- CommandNSSASetKeepModes commandnssasetkeepmodes;
-
- CommandNSSetKill commandnssetkill;
- CommandNSSASetKill commandnssasetkill;
-
- CommandNSSetLanguage commandnssetlanguage;
- CommandNSSASetLanguage commandnssasetlanguage;
-
- CommandNSSetMessage commandnssetmessage;
- CommandNSSASetMessage commandnssasetmessage;
-
- CommandNSSetPassword commandnssetpassword;
- CommandNSSASetPassword commandnssasetpassword;
-
- CommandNSSetSecure commandnssetsecure;
- CommandNSSASetSecure commandnssasetsecure;
-
- CommandNSSASetNoexpire commandnssasetnoexpire;
-
- SerializableExtensibleItem<bool> autoop, killprotect, kill_quick, kill_immed,
- message, secure, noexpire;
-
- struct KeepModes : SerializableExtensibleItem<bool>
- {
- KeepModes(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { }
-
- void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
- {
- SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data);
-
- if (s->GetSerializableType()->GetName() != "NickCore")
- return;
-
- const NickCore *nc = anope_dynamic_static_cast<const NickCore *>(s);
- Anope::string modes;
- for (User::ModeList::const_iterator it = nc->last_modes.begin(); it != nc->last_modes.end(); ++it)
- {
- if (!modes.empty())
- modes += " ";
- modes += it->first;
- if (!it->second.empty())
- modes += "," + it->second;
- }
- data["last_modes"] << modes;
- }
-
- void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
- {
- SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data);
-
- if (s->GetSerializableType()->GetName() != "NickCore")
- return;
-
- NickCore *nc = anope_dynamic_static_cast<NickCore *>(s);
- Anope::string modes;
- data["last_modes"] >> modes;
- nc->last_modes.clear();
- for (spacesepstream sep(modes); sep.GetToken(modes);)
- {
- size_t c = modes.find(',');
- if (c == Anope::string::npos)
- nc->last_modes.insert(std::make_pair(modes, ""));
- else
- nc->last_modes.insert(std::make_pair(modes.substr(0, c), modes.substr(c + 1)));
- }
- }
- } keep_modes;
-
- /* email, passcode */
- PrimitiveExtensibleItem<std::pair<Anope::string, Anope::string > > ns_set_email;
-
- public:
- NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsset(this), commandnssaset(this),
- commandnssetautoop(this), commandnssasetautoop(this),
- commandnssetdisplay(this), commandnssasetdisplay(this),
- commandnssetemail(this), commandnssasetemail(this),
- commandnssetkeepmodes(this), commandnssasetkeepmodes(this),
- commandnssetkill(this), commandnssasetkill(this),
- commandnssetlanguage(this), commandnssasetlanguage(this),
- commandnssetmessage(this), commandnssasetmessage(this),
- commandnssetpassword(this), commandnssasetpassword(this),
- commandnssetsecure(this), commandnssasetsecure(this),
- commandnssasetnoexpire(this),
-
- autoop(this, "AUTOOP"),
- killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"),
- kill_immed(this, "KILL_IMMED"), message(this, "MSG"),
- secure(this, "NS_SECURE"), noexpire(this, "NS_NO_EXPIRE"),
-
- keep_modes(this, "NS_KEEP_MODES"), ns_set_email(this, "ns_set_email")
- {
-
- }
-
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
- {
- NickCore *uac = source.nc;
-
- if (command->name == "nickserv/confirm" && !params.empty() && uac)
- {
- std::pair<Anope::string, Anope::string> *n = ns_set_email.Get(uac);
- if (n)
- {
- if (params[0] == n->second)
- {
- uac->email = n->first;
- Log(LOG_COMMAND, source, command) << "to confirm their email address change to " << uac->email;
- source.Reply(_("Your email address has been changed to \002%s\002."), uac->email.c_str());
- ns_set_email.Unset(uac);
- return EVENT_STOP;
- }
- }
- }
-
- return EVENT_CONTINUE;
- }
-
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override
- {
- if (chan->ci)
- {
- /* Only give modes if autoop is set */
- give_modes &= !user->IsIdentified() || autoop.HasExt(user->Account());
- }
- }
-
- void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
- {
- if (noexpire.HasExt(na))
- expire = false;
- }
-
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
- {
- if (!show_hidden)
- return;
-
- if (kill_immed.HasExt(na->nc))
- info.AddOption(_("Immediate protection"));
- else if (kill_quick.HasExt(na->nc))
- info.AddOption(_("Quick protection"));
- else if (killprotect.HasExt(na->nc))
- info.AddOption(_("Protection"));
- if (secure.HasExt(na->nc))
- info.AddOption(_("Security"));
- if (message.HasExt(na->nc))
- info.AddOption(_("Message mode"));
- if (autoop.HasExt(na->nc))
- info.AddOption(_("Auto-op"));
- if (noexpire.HasExt(na))
- info.AddOption(_("No expire"));
- if (keep_modes.HasExt(na->nc))
- info.AddOption(_("Keep modes"));
- }
-
- void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override
- {
- if (u->IsIdentified() && setter.GetUser() == u)
- u->Account()->last_modes = u->GetModeList();
- }
-
- void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) anope_override
- {
- if (u->IsIdentified() && setter.GetUser() == u)
- u->Account()->last_modes = u->GetModeList();
- }
-
- void OnUserLogin(User *u) anope_override
- {
- if (keep_modes.HasExt(u->Account()))
- {
- User::ModeList modes = u->Account()->last_modes;
- for (User::ModeList::iterator it = modes.begin(); it != modes.end(); ++it)
- {
- UserMode *um = ModeManager::FindUserModeByName(it->first);
- /* if the null user can set the mode, then it's probably safe */
- if (um && um->CanSet(NULL))
- u->SetMode(NULL, it->first, it->second);
- }
- }
- }
-};
-
-MODULE_INIT(NSSet)
diff --git a/modules/commands/ns_status.cpp b/modules/commands/ns_status.cpp
deleted file mode 100644
index 6c04caacb..000000000
--- a/modules/commands/ns_status.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* NickServ core functions
- *
- * (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"
-
-class CommandNSStatus : public Command
-{
- public:
- CommandNSStatus(Module *creator) : Command(creator, "nickserv/status", 0, 16)
- {
- this->SetDesc(_("Returns the owner status of the given nickname"));
- this->SetSyntax(_("[\037nickname\037]"));
- this->AllowUnregistered(true);
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &nick = !params.empty() ? params[0] : source.GetNick();
- const NickAlias *na = NickAlias::Find(nick);
- spacesepstream sep(nick);
- Anope::string nickbuf;
-
- while (sep.GetToken(nickbuf))
- {
- User *u2 = User::Find(nickbuf, true);
- if (!u2) /* Nick is not online */
- source.Reply("STATUS %s %d %s", nickbuf.c_str(), 0, "");
- else if (u2->IsIdentified() && na && na->nc == u2->Account()) /* Nick is identified */
- source.Reply("STATUS %s %d %s", nickbuf.c_str(), 3, u2->Account()->display.c_str());
- else if (u2->IsRecognized()) /* Nick is recognised, but NOT identified */
- source.Reply("STATUS %s %d %s", nickbuf.c_str(), 2, u2->IsIdentified() ? u2->Account()->display.c_str() : "");
- else if (!na) /* Nick is online, but NOT a registered */
- source.Reply("STATUS %s %d %s", nickbuf.c_str(), 0, "");
- else
- /* Nick is not identified for the nick, but they could be logged into an account,
- * so we tell the user about it
- */
- source.Reply("STATUS %s %d %s", nickbuf.c_str(), 1, u2->Account() ? u2->Account()->display.c_str() : "");
- }
- return;
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Returns whether the user using the given nickname is\n"
- "recognized as the owner of the nickname. The response has\n"
- "this format:\n"
- " \n"
- " \037nickname\037 \037status-code\037 \037account\037\n"
- " \n"
- "where \037nickname\037 is the nickname sent with the command,\n"
- "\037status-code\037 is one of the following, and \037account\037\n"
- "is the account they are logged in as.\n"
- " \n"
- " 0 - no such user online \002or\002 nickname not registered\n"
- " 1 - user not recognized as nickname's owner\n"
- " 2 - user recognized as owner via access list only\n"
- " 3 - user recognized as owner via password identification\n"
- " \n"
- "If no nickname is given, your status will be returned."));
- return true;
- }
-};
-
-class NSStatus : public Module
-{
- CommandNSStatus commandnsstatus;
-
- public:
- NSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsstatus(this)
- {
-
- }
-};
-
-MODULE_INIT(NSStatus)
diff --git a/modules/commands/os_oline.cpp b/modules/commands/os_oline.cpp
deleted file mode 100644
index 64917a64c..000000000
--- a/modules/commands/os_oline.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* OperServ core functions
- *
- * (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"
-
-class CommandOSOLine : public Command
-{
- public:
- CommandOSOLine(Module *creator) : Command(creator, "operserv/oline", 2, 2)
- {
- this->SetDesc(_("Give Operflags to a certain user"));
- this->SetSyntax(_("\037nick\037 \037flags\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- const Anope::string &nick = params[0];
- const Anope::string &flag = params[1];
- User *u2 = NULL;
-
- /* let's check whether the user is online */
- if (!(u2 = User::Find(nick, true)))
- source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
- else if (u2 && flag[0] == '+')
- {
- IRCD->SendSVSO(source.service, nick, flag);
- u2->SetMode(source.service, "OPER");
- u2->SendMessage(source.service, _("You are now an IRC Operator."));
- source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str());
- Log(LOG_ADMIN, source, this) << "for " << nick;
- }
- else if (u2 && flag[0] == '-')
- {
- IRCD->SendSVSO(source.service, nick, flag);
- source.Reply(_("Operflags \002%s\002 have been removed from \002%s\002."), flag.c_str(), nick.c_str());
- Log(LOG_ADMIN, source, this) << "for " << nick;
- }
- else
- this->OnSyntaxError(source, "");
-
- return;
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Allows Services Operators to give Operflags to any user.\n"
- "Flags have to be prefixed with a \"+\" or a \"-\". To\n"
- "remove all flags simply type a \"-\" instead of any flags."));
- return true;
- }
-};
-
-class OSOLine : public Module
-{
- CommandOSOLine commandosoline;
-
- public:
- OSOLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandosoline(this)
- {
-
- if (!IRCD || !IRCD->CanSVSO)
- throw ModuleException("Your IRCd does not support OMODE.");
-
- }
-};
-
-MODULE_INIT(OSOLine)
diff --git a/modules/cs_statusupdate.cpp b/modules/cs_statusupdate.cpp
deleted file mode 100644
index 8fc9528a3..000000000
--- a/modules/cs_statusupdate.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "module.h"
-
-class StatusUpdate : public Module
-{
- public:
- StatusUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
- {
-
- }
-
- void OnAccessAdd(ChannelInfo *ci, CommandSource &, ChanAccess *access) anope_override
- {
- if (ci->c)
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
- {
- User *user = it->second->user;
-
- ChannelInfo *next;
- if (user->server != Me && access->Matches(user, user->Account(), next))
- {
- AccessGroup ag = ci->AccessFor(user);
-
- for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i)
- {
- ChannelModeStatus *cms = ModeManager::GetStatusChannelModesByRank()[i];
- if (!ag.HasPriv("AUTO" + cms->name))
- ci->c->RemoveMode(NULL, cms, user->GetUID());
- }
- ci->c->SetCorrectModes(user, true);
- }
- }
- }
-
- void OnAccessDel(ChannelInfo *ci, CommandSource &, ChanAccess *access) anope_override
- {
- if (ci->c)
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
- {
- User *user = it->second->user;
-
- ChannelInfo *next;
- if (user->server != Me && access->Matches(user, user->Account(), next))
- {
- AccessGroup ag = ci->AccessFor(user);
-
- for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i)
- {
- ChannelModeStatus *cms = ModeManager::GetStatusChannelModesByRank()[i];
- if (!ag.HasPriv("AUTO" + cms->name))
- ci->c->RemoveMode(NULL, cms, user->GetUID());
- }
- }
- }
- }
-};
-
-MODULE_INIT(StatusUpdate)
diff --git a/modules/database/db_atheme.cpp b/modules/database/db_atheme.cpp
new file mode 100644
index 000000000..2e25b694e
--- /dev/null
+++ b/modules/database/db_atheme.cpp
@@ -0,0 +1,1615 @@
+/*
+ *
+ * (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 <functional>
+
+#include "module.h"
+#include "modules/bs_badwords.h"
+#include "modules/bs_kick.h"
+#include "modules/cs_entrymsg.h"
+#include "modules/cs_mode.h"
+#include "modules/hs_request.h"
+#include "modules/info.h"
+#include "modules/ns_cert.h"
+#include "modules/os_forbid.h"
+#include "modules/os_oper.h"
+#include "modules/os_session.h"
+#include "modules/suspend.h"
+
+// Handles reading from an Atheme database row.
+class AthemeRow final
+{
+private:
+ // The number of failed reads.
+ unsigned error = 0;
+
+ // The underlying token stream.
+ spacesepstream stream;
+
+public:
+ AthemeRow(const Anope::string &str)
+ : stream(str)
+ {
+ }
+
+ operator bool() const
+ {
+ return !error;
+ }
+
+ // Retrieves the next parameter.
+ Anope::string Get()
+ {
+ Anope::string token;
+ if (!stream.GetToken(token))
+ error++;
+ return token;
+ }
+
+ // Retrieves the next parameter as a number.
+ template<typename Numeric>
+ std::enable_if_t<std::is_arithmetic_v<Numeric>, Numeric> GetNum()
+ {
+ return Anope::Convert<Numeric>(Get(), 0);
+ }
+
+ // Retrieves the entire row.
+ Anope::string GetRow()
+ {
+ return stream.GetString();
+ }
+
+ // Retrieves the remaining data in the row.
+ Anope::string GetRemaining()
+ {
+ auto remaining = stream.GetRemaining();
+ if (remaining.empty())
+ error++;
+ return remaining;
+ }
+
+ bool LogError(Module *mod)
+ {
+ Log(mod) << "Malformed database line (expected " << error << " fields): " << GetRow();
+ return false;
+ }
+};
+
+struct ModeData final
+{
+ char letter;
+ Anope::string name;
+ Anope::string value;
+ bool set;
+
+ ModeData(const Anope::string &n, bool s, const Anope::string &v = "")
+ : letter(0)
+ , name(n)
+ , value(v)
+ , set(s)
+ {
+ }
+
+ ModeData(char l, const Anope::string &v = "")
+ : letter(l)
+ , value(v)
+ , set(true)
+ {
+ }
+
+ Anope::string str() const
+ {
+ std::stringstream buf;
+ buf << '+' << (name.empty() ? letter : name);
+ if (value.empty())
+ buf << ' ' << value;
+ return buf.str();
+ }
+};
+
+struct ChannelData final
+{
+ Anope::unordered_map<AutoKick *> akicks;
+ Anope::string bot;
+ Anope::string info_adder;
+ Anope::string info_message;
+ time_t info_ts = 0;
+ std::vector<ModeData> mlocks;
+ Anope::string suspend_by;
+ Anope::string suspend_reason;
+ time_t suspend_ts = 0;
+};
+
+struct UserData final
+{
+ bool kill = false;
+ 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;
+ bool noexpire = false;
+ Anope::string suspend_by;
+ Anope::string suspend_reason;
+ time_t suspend_ts = 0;
+ Anope::string vhost;
+ Anope::string vhost_creator;
+ Anope::map<Anope::string> vhost_nick;
+ time_t vhost_ts = 0;
+};
+
+namespace
+{
+ // Whether we can safely import clones.
+ bool import_clones = true;
+}
+
+class DBAtheme final
+ : public Module
+{
+private:
+ ServiceReference<AccessProvider> accessprov;
+ PrimitiveExtensibleItem<ChannelData> chandata;
+ std::map<Anope::string, char> flags;
+ PrimitiveExtensibleItem<UserData> userdata;
+ ServiceReference<XLineManager> sglinemgr;
+ ServiceReference<XLineManager> snlinemgr;
+ ServiceReference<XLineManager> sqlinemgr;
+
+ Anope::map<std::function<bool(DBAtheme*,AthemeRow&)>> rowhandlers = {
+ { "AC", &DBAtheme::HandleIgnore },
+ { "AR", &DBAtheme::HandleIgnore },
+ { "BE", &DBAtheme::HandleBE },
+ { "BLE", &DBAtheme::HandleIgnore },
+ { "BOT", &DBAtheme::HandleBOT },
+ { "BOT-COUNT", &DBAtheme::HandleIgnore },
+ { "BW", &DBAtheme::HandleBW },
+ { "CA", &DBAtheme::HandleCA },
+ { "CF", &DBAtheme::HandleIgnore },
+ { "CFCHAN", &DBAtheme::HandleIgnore },
+ { "CFDBV", &DBAtheme::HandleIgnore },
+ { "CFMD", &DBAtheme::HandleIgnore },
+ { "CFOP", &DBAtheme::HandleIgnore },
+ { "CLONES-CD", &DBAtheme::HandleIgnore },
+ { "CLONES-CK", &DBAtheme::HandleIgnore },
+ { "CLONES-DBV", &DBAtheme::HandleCLONESDBV },
+ { "CLONES-EX", &DBAtheme::HandleCLONESEX },
+ { "CLONES-GR", &DBAtheme::HandleIgnore },
+ { "CSREQ", &DBAtheme::HandleIgnore },
+ { "CSREQ", &DBAtheme::HandleIgnore },
+ { "DBV", &DBAtheme::HandleDBV },
+ { "GACL", &DBAtheme::HandleIgnore },
+ { "GDBV", &DBAtheme::HandleIgnore },
+ { "GE", &DBAtheme::HandleIgnore },
+ { "GFA", &DBAtheme::HandleIgnore },
+ { "GRP", &DBAtheme::HandleIgnore },
+ { "GRVER", &DBAtheme::HandleGRVER },
+ { "HE", &DBAtheme::HandleIgnore },
+ { "HO", &DBAtheme::HandleIgnore },
+ { "HR", &DBAtheme::HandleHR },
+ { "JM", &DBAtheme::HandleIgnore },
+ { "KID", &DBAtheme::HandleIgnore },
+ { "KL", &DBAtheme::HandleKL },
+ { "LUID", &DBAtheme::HandleIgnore },
+ { "MC", &DBAtheme::HandleMC },
+ { "MCFP", &DBAtheme::HandleMCFP },
+ { "MDA", &DBAtheme::HandleMDA },
+ { "MDC", &DBAtheme::HandleMDC },
+ { "MDEP", &DBAtheme::HandleIgnore },
+ { "MDG", &DBAtheme::HandleIgnore },
+ { "MDN", &DBAtheme::HandleMDN },
+ { "MDU", &DBAtheme::HandleMDU },
+ { "ME", &DBAtheme::HandleME },
+ { "MI", &DBAtheme::HandleMI },
+ { "MM", &DBAtheme::HandleMM },
+ { "MN", &DBAtheme::HandleMN },
+ { "MU", &DBAtheme::HandleMU },
+ { "NAM", &DBAtheme::HandleNAM },
+ { "QID", &DBAtheme::HandleIgnore },
+ { "QL", &DBAtheme::HandleQL },
+ { "RM", &DBAtheme::HandleIgnore },
+ { "RR", &DBAtheme::HandleIgnore },
+ { "RW", &DBAtheme::HandleIgnore },
+ { "SI", &DBAtheme::HandleIgnore },
+ { "SO", &DBAtheme::HandleSO },
+ { "TS", &DBAtheme::HandleIgnore },
+ { "XID", &DBAtheme::HandleIgnore },
+ { "XL", &DBAtheme::HandleXL },
+ };
+
+ void ApplyAccess(Anope::string &in, char flag, Anope::string &out, std::initializer_list<const char*> privs)
+ {
+ for (const auto *priv : privs)
+ {
+ auto pos = in.find(flag);
+ if (pos != Anope::string::npos)
+ {
+ auto privchar = flags.find(priv);
+ if (privchar != flags.end())
+ {
+ out.push_back(privchar->second);
+ in.erase(pos, 1);
+ }
+ }
+ }
+ }
+
+ void ApplyFlags(Extensible *ext, Anope::string &flags, char flag, const char* extname, bool extend = true)
+ {
+ auto pos = flags.find(flag);
+ auto has_flag = (pos != Anope::string::npos);
+
+ if (has_flag == extend)
+ ext->Extend<bool>(extname);
+ else
+ ext->Shrink<bool>(extname);
+
+ if (has_flag)
+ flags.erase(pos, 1);
+ }
+
+ void ApplyLocks(ChannelInfo *ci, unsigned locks, const Anope::string &limit, const Anope::string &key, bool set)
+ {
+ auto *data = chandata.Require(ci);
+
+ // Start off with the standard mode values.
+ if (locks & 0x1u)
+ data->mlocks.emplace_back("INVITE", set);
+ if (locks & 0x2u)
+ data->mlocks.emplace_back("KEY", set, key);
+ if (locks & 0x4u)
+ data->mlocks.emplace_back("LIMIT", set, limit);
+ if (locks & 0x8u)
+ data->mlocks.emplace_back("MODERATED", set);
+ if (locks & 0x10u)
+ data->mlocks.emplace_back("NOEXTERNAL", set);
+ if (locks & 0x40u)
+ data->mlocks.emplace_back("PRIVATE", set);
+ if (locks & 0x80u)
+ data->mlocks.emplace_back("SECRET", set);
+ if (locks & 0x100u)
+ data->mlocks.emplace_back("TOPIC", set);
+ if (locks & 0x200u)
+ 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 (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);
+ if (locks & 0x10000u)
+ data->mlocks.emplace_back("NONOTICE", set);
+ if (locks & 0x20000u)
+ data->mlocks.emplace_back("NOKICK", set);
+ if (locks & 0x40000u)
+ data->mlocks.emplace_back("STRIPCOLOR", set);
+ if (locks & 0x80000u)
+ data->mlocks.emplace_back("NOKNOCK", set);
+ if (locks & 0x100000u)
+ data->mlocks.emplace_back("ALLINVITE", set);
+ if (locks & 0x200000u)
+ data->mlocks.emplace_back("NOCTCP", set);
+ if (locks & 0x400000u)
+ data->mlocks.emplace_back("AUDITORIUM", set);
+ if (locks & 0x800000u)
+ data->mlocks.emplace_back("SSL", set);
+ if (locks & 0x100000u)
+ data->mlocks.emplace_back("NONICK", set);
+ if (locks & 0x200000u)
+ data->mlocks.emplace_back("CENSOR", set);
+ if (locks & 0x400000u)
+ data->mlocks.emplace_back("BLOCKCAPS", set);
+ if (locks & 0x800000u)
+ data->mlocks.emplace_back("PERM", set);
+ if (locks & 0x2000000u)
+ data->mlocks.emplace_back("DELAYEDJOIN", set);
+ }
+ else if (IRCD->owner->name == "ngircd")
+ {
+ if (locks & 0x1000u)
+ data->mlocks.emplace_back("REGISTEREDONLY", set);
+ if (locks & 0x2000u)
+ data->mlocks.emplace_back("OPERONLY", set);
+ if (locks & 0x4000u)
+ data->mlocks.emplace_back("PERM", set);
+ if (locks & 0x8000u)
+ data->mlocks.emplace_back("SSL", set);
+ }
+ else if (IRCD->owner->name == "solanum")
+ {
+ if (locks & 0x1000u)
+ data->mlocks.emplace_back("BLOCKCOLOR", set);
+ if (locks & 0x2000u)
+ data->mlocks.emplace_back("REGISTEREDONLY", set);
+ if (locks & 0x4000u)
+ data->mlocks.emplace_back("OPMODERATED", set);
+ if (locks & 0x8000u)
+ data->mlocks.emplace_back("ALLINVITE", set);
+ if (locks & 0x10000u)
+ data->mlocks.emplace_back("LBAN", set);
+ if (locks & 0x20000u)
+ data->mlocks.emplace_back("PERM", set);
+ if (locks & 0x40000u)
+ data->mlocks.emplace_back("ALLOWFORWARD", set);
+ if (locks & 0x80000u)
+ data->mlocks.emplace_back("NOFORWARD", set);
+ if (locks & 0x100000u)
+ data->mlocks.emplace_back("NOCTCP", set);
+ if (locks & 0x400000u)
+ data->mlocks.emplace_back("SSL", set);
+ if (locks & 0x800000u)
+ data->mlocks.emplace_back("OPERONLY", set);
+ if (locks & 0x1000000u)
+ data->mlocks.emplace_back("ADMINONLY", set);
+ if (locks & 0x2000000u)
+ data->mlocks.emplace_back("NONOTICE", set);
+ if (locks & 0x4000000u)
+ data->mlocks.emplace_back("PROTECTED", set);
+ if (locks & 0x8000000)
+ data->mlocks.emplace_back("NOFILTER", set);
+ if (locks & 0x10000000U)
+ data->mlocks.emplace_back("REGMODERATED", set);
+ }
+ else if (IRCD->owner->name == "unrealircd")
+ {
+ 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);
+ if (locks & 0x20000u)
+ data->mlocks.emplace_back("NOKICK", set);
+ if (locks & 0x40000u)
+ data->mlocks.emplace_back("STRIPCOLOR", set);
+ if (locks & 0x80000u)
+ data->mlocks.emplace_back("NOKNOCK", set);
+ if (locks & 0x100000u)
+ data->mlocks.emplace_back("NOINVITE", set);
+ if (locks & 0x200000u)
+ data->mlocks.emplace_back("NOCTCP", set);
+ if (locks & 0x800000u)
+ data->mlocks.emplace_back("SSL", set);
+ if (locks & 0x1000000u)
+ data->mlocks.emplace_back("NONICK", set);
+ if (locks & 0x4000000u)
+ data->mlocks.emplace_back("CENSOR", set);
+ if (locks & 0x8000000u)
+ data->mlocks.emplace_back("PERM", set);
+ if (locks & 0x1000000u)
+ data->mlocks.emplace_back("NONOTICE", set);
+ if (locks & 0x2000000u)
+ data->mlocks.emplace_back("DELAYJOIN", set);
+ }
+ else if (IRCD->owner->name != "ratbox")
+ {
+ Log(this) << "Unable to import mode locks for " << IRCD->GetProtocolName();
+ }
+ }
+
+ void ApplyPassword(NickCore *nc, Anope::string &flags, const Anope::string &pass)
+ {
+ auto pos = flags.find('C');
+ if (pos == Anope::string::npos)
+ {
+ // Password is unencrypted so we can use it.
+ Anope::Encrypt(pass, nc->pass);
+ return;
+ }
+
+ // We are processing an encrypted password.
+ flags.erase(pos, 1);
+
+ // Atheme supports several password hashing methods. We can only import
+ // some of them currently.
+ //
+ // anope-enc-sha256 Converted to enc_sha256
+ // argon2 Converted to enc_argon2
+ // base64 Converted to the first encryption algorithm
+ // bcrypt Converted to enc_bcrypt
+ // crypt3-des NO
+ // 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
+ // pbkdf2 NO
+ // pbkdf2v2 NO
+ // rawmd5 Converted to enc_md5
+ // rawsha1 Converted to enc_sha1
+ // rawsha2-256 Converted to enc_sha2
+ // rawsha2-512 Converted to enc_sha2
+ // scrypt NO
+ 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);
+ }
+
+ else if (pass.compare(0, 9, "$argon2d$", 9) == 0)
+ nc->pass = "argon2d:" + pass;
+
+ else if (pass.compare(0, 9, "$argon2i$", 9) == 0)
+ nc->pass = "argon2i:" + pass;
+
+ else if (pass.compare(0, 10, "$argon2id$", 10) == 0)
+ nc->pass = "argon2id:" + pass;
+
+ else if (pass.compare(0, 8, "$base64$", 8) == 0)
+ {
+ Anope::string rawpass;
+ Anope::B64Decode(pass.substr(8), rawpass);
+ 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);
+
+ else if (pass.compare(0, 9, "$rawsha1$", 9) == 0)
+ nc->pass = "sha1:" + pass.substr(9);
+
+ else if (pass.compare(0, 11, "$rawsha256$", 11) == 0)
+ nc->pass = "raw-sha256:" + pass.substr(11);
+
+ else if (pass.compare(0, 11, "$rawsha512$", 11) == 0)
+ nc->pass = "raw-sha512:" + pass.substr(11);
+
+ else if (pass.compare(0, 3, "$1$", 3) == 0 || pass.compare(0, 3, "$5", 3) == 0 || pass.compare(0, 3, "$6", 3) == 0)
+ nc->pass = "posix:" + pass;
+
+ else if (pass.compare(0, 4, "$2a$", 4) == 0 || pass.compare(0, 4, "$2b$", 4) == 0)
+ nc->pass = "bcrypt:" + pass;
+
+ else
+ {
+ // Generate a new password as we can't use the old one.
+ auto maxpasslen = Config->GetModule("nickserv")->Get<unsigned>("maxpasslen", "50");
+ Anope::Encrypt(Anope::Random(maxpasslen), nc->pass);
+ Log(this) << "Unable to convert the password for " << nc->display << " as Anope does not support the format!";
+ }
+
+ }
+
+ bool HandleBE(AthemeRow &row)
+ {
+ // BE <email> <created> <creator> <reason>
+ auto email = row.Get();
+ auto created = row.GetNum<time_t>();
+ auto creator = row.Get();
+ auto reason = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!forbid_service)
+ {
+ Log(this) << "Unable to convert forbidden email " << email << " as os_forbid is not loaded";
+ return true;
+ }
+
+ auto *forbid = forbid_service->CreateForbid();
+ forbid->created = created;
+ forbid->creator = creator;
+ forbid->mask = email;
+ forbid->reason = reason;
+ forbid->type = FT_EMAIL;
+ forbid_service->AddForbid(forbid);
+ return true;
+ }
+
+ bool HandleBOT(AthemeRow &row)
+ {
+ // BOT <nick> <user> <host> <operonly> <created> <real>
+ auto nick = row.Get();
+ auto user = row.Get();
+ auto host = row.Get();
+ auto operonly = row.GetNum<unsigned>();
+ auto created = row.GetNum<time_t>();
+ auto real = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *bi = new BotInfo(nick, user, host, real);
+ bi->oper_only = operonly;
+ bi->created = created;
+ return true;
+ }
+
+ bool HandleBW(AthemeRow &row)
+ {
+ // BW <badword> <added> <creator> <channel> <action>
+ auto badword = row.Get();
+ /* auto added = */ row.GetNum<time_t>();
+ /* auto creator = */ row.Get();
+ auto channel = row.Get();
+ /* auto action = */ row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *ci = ChannelInfo::Find(channel);
+ if (!ci)
+ {
+ Log(this) << "Missing ChannelInfo for BW: " << channel;
+ return false;
+ }
+
+ auto *bw = ci->Require<BadWords>("badwords");
+ if (!bw)
+ {
+ Log(this) << "Unable to import badwords for " << ci->name << " as bs_kick is not loaded";
+ return true;
+ }
+
+ auto *kd = ci->Require<KickerData>("kickerdata");
+ if (kd)
+ {
+ kd->badwords = true;
+ kd->ttb[TTB_BADWORDS] = 0;
+ }
+
+ bw->AddBadWord(badword, BW_ANY);
+ return true;
+ }
+
+ bool HandleCA(AthemeRow &row)
+ {
+ // CA <channel> <account/mask> <flags> <modifiedtime> <setter>
+ auto channel = row.Get();
+ auto mask = row.Get();
+ auto flags = row.Get();
+ auto modifiedtime = row.GetNum<time_t>();
+ auto setter = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *ci = ChannelInfo::Find(channel);
+ if (!ci)
+ {
+ Log(this) << "Missing ChannelInfo for CA: " << channel;
+ return false;
+ }
+
+ auto *nc = NickCore::Find(mask);
+ if (flags.find('b') != Anope::string::npos)
+ {
+ auto *data = chandata.Require(ci);
+ if (nc)
+ data->akicks[mask] = ci->AddAkick(setter, nc, "", modifiedtime, modifiedtime);
+ else
+ data->akicks[mask] = ci->AddAkick(setter, mask, "", modifiedtime, modifiedtime);
+ return true;
+ }
+
+ if (!accessprov)
+ {
+ Log(this) << "Unable to import channel access for " << ci->name << " as cs_flags is not loaded";
+ return true;
+ }
+
+ Anope::string accessflags;
+ ApplyAccess(flags, 'A', accessflags, { "ACCESS_LIST" });
+ ApplyAccess(flags, 'a', accessflags, { "AUTOPROTECT", "PROTECT", "PROTECTME" });
+ ApplyAccess(flags, 'e', accessflags, { "GETKEY", "NOKICK", "UNBANME" });
+ ApplyAccess(flags, 'f', accessflags, { "ACCESS_CHANGE" });
+ ApplyAccess(flags, 'F', accessflags, { "FOUNDER" });
+ ApplyAccess(flags, 'H', accessflags, { "AUTOHALFOP" });
+ ApplyAccess(flags, 'h', accessflags, { "HALFOP", "HALFOPME" });
+ ApplyAccess(flags, 'i', accessflags, { "INVITE" });
+ ApplyAccess(flags, 'O', accessflags, { "AUTOOP" });
+ ApplyAccess(flags, 'o', accessflags, { "OP", "OPME" });
+ ApplyAccess(flags, 'q', accessflags, { "AUTOOWNER", "OWNER", "OWNERME" });
+ ApplyAccess(flags, 'r', accessflags, { "KICK" });
+ ApplyAccess(flags, 's', accessflags, { "SET" });
+ ApplyAccess(flags, 't', accessflags, { "TOPIC" });
+ ApplyAccess(flags, 'V', accessflags, { "AUTOVOICE" });
+ ApplyAccess(flags, 'v', accessflags, { "VOICE", "VOICEME" });
+ if (!accessflags.empty())
+ {
+ auto *access = accessprov->Create();
+ access->SetMask(mask, ci);
+ access->creator = setter;
+ access->description = "Imported from Atheme";
+ access->last_seen = modifiedtime;
+ access->created = modifiedtime;
+ access->AccessUnserialize(accessflags);
+ ci->AddAccess(access);
+ }
+
+ if (flags != "+")
+ Log(this) << "Unable to convert channel access flags " << flags << " for " << mask << " on " << ci->name;
+
+ return true;
+ }
+
+ bool HandleCLONESDBV(AthemeRow &row)
+ {
+ // CLONES-DBV <version>
+ auto version = row.GetNum<unsigned>();
+ if (version != 3)
+ {
+ Log(this) << "Clones database is version " << version << " which is not supported!";
+ import_clones = false;
+ }
+ return true;
+ }
+
+ bool HandleCLONESEX(AthemeRow &row)
+ {
+ if (!import_clones)
+ return HandleIgnore(row);
+
+ // CLONES-EX <ip> <allowed> <warn> <expires> <reason>
+ auto ip = row.Get();
+ auto allowed = row.GetNum<unsigned>();
+ /* auto warn = */ row.GetNum<unsigned>();
+ auto expires = row.GetNum<time_t>();
+ auto reason = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!session_service)
+ {
+ Log(this) << "Unable to import session limit for " << ip << " as os_session is not loaded";
+ return true;
+ }
+
+ auto *exception = session_service->CreateException();
+ exception->mask = ip;
+ exception->limit = allowed;
+ exception->who = "Unknown";
+ exception->time = Anope::CurTime;
+ exception->expires = expires;
+ exception->reason = reason;
+ session_service->AddException(exception);
+ return true;
+ }
+
+ bool HandleDBV(AthemeRow &row)
+ {
+ // DBV <version>
+ auto version = row.GetNum<unsigned>();
+ if (version != 12)
+ {
+ Log(this) << "Database is version " << version << " which is not supported!";
+ return false;
+ }
+ return true;
+ }
+
+ bool HandleGRVER(AthemeRow &row)
+ {
+ // GRVER <version>
+ auto version = row.GetNum<unsigned>();
+ if (version != 1)
+ {
+ Log(this) << "Database grammar is version " << version << " which is not supported!";
+ return false;
+ }
+ return true;
+ }
+
+ bool HandleHR(AthemeRow &row)
+ {
+ // HR <nick> <host> <reqts> <creator>
+ auto nick = row.Get();
+ auto host = row.Get();
+ auto reqts = row.GetNum<time_t>();
+ /* auto creator = */ row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *na = NickAlias::Find(nick);
+ if (!na)
+ {
+ Log(this) << "Missing NickAlias for HR: " << nick;
+ return false;
+ }
+
+ auto *hr = na->Require<HostRequest>("hostrequest");
+ if (!hr)
+ {
+ Log(this) << "Unable to convert host request for " << na->nick << " as hs_request is not loaded";
+ return true;
+ }
+
+ hr->nick = na->nick;
+ hr->ident.clear();
+ hr->host = host;
+ hr->time = reqts;
+ return true;
+ }
+
+ bool HandleKL(AthemeRow &row)
+ {
+ // KL <id> <user> <host> <duration> <settime> <setby> <reason>
+ auto id = row.Get();
+ auto user = row.Get();
+ auto host = row.Get();
+ auto duration = row.GetNum<unsigned>();
+ auto settime = row.GetNum<time_t>();
+ auto setby = row.Get();
+ auto reason = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!sglinemgr)
+ {
+ Log(this) << "Unable to import K-line on " << user << "@" << host << " as operserv is not loaded";
+ return true;
+ }
+
+ auto *xl = new XLine(user + "@" + host, setby, settime + duration, reason);
+ xl->id = id;
+ sglinemgr->AddXLine(xl);
+ return true;
+ }
+
+ bool HandleIgnore(AthemeRow &row)
+ {
+ Log(LOG_DEBUG_3) << "Intentionally ignoring Atheme database row: " << row.GetRow();
+ return true;
+ }
+
+ bool HandleIgnoreMetadata(const Anope::string &target, const Anope::string &key, const Anope::string &value)
+ {
+ Log(LOG_DEBUG_3) << "Intentionally ignoring Atheme database metadata for " << target << ": " << key << " = " << value;
+ return true;
+ }
+
+ bool HandleMC(AthemeRow &row)
+ {
+ // MC <channel> <regtime> <used> <flags> <mlock-on> <mlock-off> <mlock-limit> [<mlock-key>]
+ auto channel = row.Get();
+ auto regtime = row.GetNum<time_t>();
+ auto used = row.GetNum<time_t>();
+ auto flags = row.Get();
+ auto mlock_on = row.GetNum<unsigned>();
+ auto mlock_off = row.GetNum<unsigned>();
+ auto mlock_limit = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto mlock_key = row.Get(); // May not exist.
+
+ auto *ci = new ChannelInfo(channel);
+ ci->time_registered = regtime;
+ ci->last_used = used;
+
+ // No equivalent: elnv
+ ApplyFlags(ci, flags, 'h', "CS_NO_EXPIRE");
+ ApplyFlags(ci, flags, 'k', "KEEPTOPIC");
+ ApplyFlags(ci, flags, 'o', "NOAUTOOP");
+ ApplyFlags(ci, flags, 'p', "CS_PRIVATE");
+ ApplyFlags(ci, flags, 'r', "RESTRICTED");
+ ApplyFlags(ci, flags, 't', "TOPICLOCK");
+ ApplyFlags(ci, flags, 'z', "SECUREOPS");
+
+ auto pos = flags.find('a');
+ if (pos != Anope::string::npos)
+ {
+ ci->SetLevel("ACCESS_CHANGE", 0);
+ flags.erase(pos, 1);
+ }
+
+ pos = flags.find('f');
+ if (pos != Anope::string::npos)
+ {
+ auto *kd = ci->Require<KickerData>("kickerdata");
+ if (kd)
+ {
+ kd->flood = true;
+ kd->floodlines = 10;
+ kd->floodsecs = 60;
+ kd->ttb[TTB_FLOOD] = 0;
+ flags.erase(pos, 1);
+ }
+ else
+ {
+ Log(this) << "Unable to convert the 'f' flag for " << ci->name << " as bs_kick is not loaded";
+ }
+ }
+
+ pos = flags.find('g');
+ if (pos != Anope::string::npos)
+ {
+ auto *bi = Config->GetClient("ChanServ");
+ if (bi)
+ {
+ bi->Assign(nullptr, ci);
+ flags.erase(pos, 1);
+ }
+ else
+ Log(this) << "Unable to convert the 'g' flag for " << ci->name << " as chanserv is not loaded";
+ }
+
+ if (flags != "+")
+ Log(this) << "Unable to convert channel flags " << flags << " for " << ci->name;
+
+ ApplyLocks(ci, mlock_on, mlock_limit, mlock_key, true);
+ ApplyLocks(ci, mlock_off, mlock_limit, mlock_key, false);
+ return true;
+ }
+
+ bool HandleMCFP(AthemeRow &row)
+ {
+ // MCFP <display> <fingerprint>
+ auto display = row.Get();
+ auto fingerprint = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(display);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for MCFP: " << display;
+ return false;
+ }
+
+ auto *cl = nc->Require<NSCertList>("certificates");
+ if (!cl)
+ {
+ Log(this) << "Unable to convert certificate for " << nc->display << " as ns_cert is not loaded";
+ return true;
+ }
+
+ cl->AddCert(fingerprint);
+ return true;
+ }
+
+ bool HandleMDA(AthemeRow &row)
+ {
+ // MDA <channel> <account/mask> <key> <value>
+ auto channel = row.Get();
+ auto mask = row.Get();
+ auto key = row.Get();
+ auto value = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *ci = ChannelInfo::Find(channel);
+ if (!ci)
+ {
+ Log(this) << "Missing ChannelInfo for MDA: " << channel;
+ return false;
+ }
+
+ if (key == "reason")
+ {
+ auto *data = chandata.Require(ci);
+ auto akick = data->akicks.find(mask);
+ if (akick != data->akicks.end())
+ akick->second->reason = value;
+ }
+ else
+ Log(this) << "Unknown channel access metadata for " << mask << " on " << ci->name << ": " << key << " = " << value;
+
+ return true;
+ }
+
+ bool HandleMDC(AthemeRow &row)
+ {
+ // MDC <channel> <key> <value>
+ auto channel = row.Get();
+ auto key = row.Get();
+ auto value = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *ci = ChannelInfo::Find(channel);
+ if (!ci)
+ {
+ Log(this) << "Missing ChannelInfo for MDC: " << channel;
+ return false;
+ }
+
+ auto *data = chandata.Require(ci);
+ if (key == "private:botserv:bot-assigned")
+ data->bot = value;
+ else if (key == "private:botserv:bot-handle-fantasy")
+ ci->Extend<bool>("BS_FANTASY");
+ else if (key == "private:botserv:no-bot")
+ ci->Extend<bool>("BS_NOBOT");
+ else if (key == "private:channelts")
+ return HandleIgnoreMetadata(ci->name, key, value);
+ else if (key == "private:close:closer")
+ data->suspend_by = value;
+ else if (key == "private:close:reason")
+ data->suspend_reason = value;
+ else if (key == "private:close:timestamp")
+ data->suspend_ts = Anope::Convert<time_t>(value, 0);
+ else if (key == "private:entrymsg")
+ {
+ auto *eml = ci->Require<EntryMessageList>("entrymsg");
+ if (!eml)
+ {
+ Log(this) << "Unable to convert entry message for " << ci->name << " as cs_mode is not loaded";
+ return true;
+ }
+
+ auto *msg = eml->Create();
+ msg->chan = ci->name;
+ msg->creator = "Unknown";
+ msg->message = value;
+ msg->when = Anope::CurTime;
+ (*eml)->push_back(msg);
+ }
+ else if (key == "private:klinechan:closer")
+ data->suspend_by = value;
+ else if (key == "private:klinechan:reason")
+ data->suspend_reason = value;
+ else if (key == "private:klinechan:timestamp")
+ data->suspend_ts = Anope::Convert<time_t>(value, 0);
+ else if (key == "private:mark:reason")
+ data->info_message = value;
+ else if (key == "private:mark:setter")
+ data->info_adder = value;
+ else if (key == "private:mark:timestamp")
+ data->info_ts = Anope::Convert<time_t>(value, 0);
+ else if (key == "private:mlockext")
+ {
+ spacesepstream mlocks(value);
+ for (Anope::string mlock; mlocks.GetToken(mlock); )
+ data->mlocks.emplace_back(mlock[0], mlock.substr(1));
+ }
+ else if (key == "private:templates")
+ return HandleIgnoreMetadata(ci->name, key, value);
+ else if (key == "private:topic:setter")
+ ci->last_topic_setter = value;
+ else if (key == "private:topic:text")
+ ci->last_topic = value;
+ else if (key == "private:topic:ts")
+ ci->last_topic_time = Anope::Convert<time_t>(value, 0);
+ else if (key.compare(0, 14, "private:stats:", 14) == 0)
+ return HandleIgnoreMetadata(ci->name, key, value);
+ else
+ Log(this) << "Unknown channel metadata for " << ci->name << ": " << key << " = " << value;
+
+ return true;
+ }
+
+ bool HandleMDN(AthemeRow &row)
+ {
+ // MDN <nick> <key> <value>
+ auto nick = row.Get();
+ auto key = row.Get();
+ auto value = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!forbid_service)
+ {
+ Log(this) << "Unable to convert forbidden nick " << nick << " metadata as os_forbid is not loaded";
+ return true;
+ }
+
+ auto *forbid = forbid_service->FindForbidExact(nick, FT_NICK);
+ if (!forbid)
+ {
+ Log(this) << "Missing forbid for MDN: " << nick;
+ return false;
+ }
+
+ if (key == "private:mark:reason")
+ forbid->reason = value;
+ else if (key == "private:mark:setter")
+ forbid->creator = value;
+ else if (key == "private:mark:timestamp")
+ forbid->created = Anope::Convert<time_t>(value, 0);
+ else
+ Log(this) << "Unknown forbidden nick metadata for " << forbid->mask << ": " << key << " = " << value;
+
+ return true;
+ }
+
+ bool HandleMDU(AthemeRow &row)
+ {
+ // MDU <display> <key> <value>
+ auto display = row.Get();
+ auto key = row.Get();
+ auto value = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(display);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for MDU: " << display;
+ return false;
+ }
+
+ auto *data = userdata.Require(nc);
+ if (key == "private:autojoin")
+ return true; // TODO
+ else if (key == "private:doenforce")
+ data->kill = true;
+ else if (key == "private:enforcetime")
+ {
+ if (!data->kill)
+ return true; // Don't apply this.
+
+ auto kill = Config->GetModule("nickserv")->Get<time_t>("kill", "60s");
+ auto killquick = Config->GetModule("nickserv")->Get<time_t>("killquick", "20s");
+ auto secs = Anope::Convert<time_t>(value, kill);
+ if (secs >= kill)
+ nc->Extend<bool>("KILLPROTECT");
+ else if (secs >= killquick)
+ nc->Shrink<bool>("KILL_QUICK");
+ else
+ nc->Shrink<bool>("KILL_IMMED");
+ }
+ else if (key == "private:freeze:freezer")
+ data->suspend_by = value;
+ else if (key == "private:freeze:reason")
+ data->suspend_reason = value;
+ 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;
+ else if (key == "private:host:vhost")
+ data->last_mask = value;
+ else if (key == "private:lastquit:message")
+ data->last_quit = value;
+ else if (key == "private:loginfail:failnum")
+ return HandleIgnoreMetadata(nc->display, key, value);
+ else if (key == "private:loginfail:lastfailaddr")
+ return HandleIgnoreMetadata(nc->display, key, value);
+ else if (key == "private:loginfail:lastfailtime")
+ return HandleIgnoreMetadata(nc->display, key, value);
+ else if (key == "private:mark:reason")
+ data->info_message = value;
+ else if (key == "private:mark:setter")
+ data->info_adder = value;
+ else if (key == "private:mark:timestamp")
+ data->info_ts = Anope::Convert<time_t>(value, 0);
+ else if (key == "private:swhois")
+ return HandleIgnoreMetadata(nc->display, key, value);
+ else if (key == "private:usercloak")
+ data->vhost = value;
+ else if (key == "private:usercloak-assigner")
+ data->vhost_creator = value;
+ else if (key == "private:usercloak-timestamp")
+ data->vhost_ts = Anope::Convert<time_t>(value, 0);
+ else if (key.compare(0, 18, "private:usercloak:", 18) == 0)
+ data->vhost_nick[key.substr(18)] = value;
+ else
+ Log(this) << "Unknown account metadata for " << nc->display << ": " << key << " = " << value;
+
+ return true;
+ }
+
+ bool HandleME(AthemeRow &row)
+ {
+ // ME <target> <source> <sent> <flags> <text>
+ auto target = row.Get();
+ auto source = row.Get();
+ auto sent = row.GetNum<time_t>();
+ auto flags = row.GetNum<unsigned>();
+ auto text = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(target);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for ME: " << source;
+ return false;
+ }
+
+ auto *m = new Memo();
+ m->mi = &nc->memos;
+ m->owner = nc->display;
+ m->sender = source;
+ m->time = sent;
+ m->text = text;
+ m->unread = flags & 0x1;
+ nc->memos.memos->push_back(m);
+ return true;
+ }
+
+ bool HandleMI(AthemeRow &row)
+ {
+ // MI <display> <ignored>
+ auto display = row.Get();
+ auto ignored = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(display);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for MI: " << display;
+ return false;
+ }
+
+ nc->memos.ignores.push_back(ignored);
+ return true;
+ }
+
+ bool HandleMM(AthemeRow &row)
+ {
+ // MM <id> <setterid> <setteraccount> <markedid> <markedaccount> <setts> <num> <message>
+ /* auto id = */ row.Get();
+ /* auto setterid = */ row.Get();
+ auto setteraccount = row.Get();
+ /* auto markedid = */ row.Get();
+ auto markedaccount = row.Get();
+ auto setts = row.GetNum<time_t>();
+ /* auto num = */ row.Get();
+ auto message = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(markedaccount);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for MM: " << markedaccount;
+ return false;
+ }
+
+ auto *oil = nc->Require<OperInfoList>("operinfo");
+ if (oil)
+ {
+ auto *info = oil->Create();
+ info->target = nc->display;
+ info->info = message;
+ info->adder = setteraccount;
+ info->created = setts;
+ (*oil)->push_back(info);
+ }
+ else
+ {
+ Log(this) << "Unable to convert oper info for " << nc->display << " as os_info is not loaded";
+ }
+ return true;
+ }
+
+ bool HandleMN(AthemeRow &row)
+ {
+ // MU <display> <nick> <regtime> <lastseen>
+ auto display = row.Get();
+ auto nick = row.Get();
+ auto regtime = row.GetNum<time_t>();
+ auto lastseen = row.GetNum<time_t>();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(display);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for MN: " << display;
+ return false;
+ }
+
+ auto *na = new NickAlias(nick, nc);
+ na->time_registered = regtime;
+ na->last_seen = lastseen ? regtime : na->time_registered;
+
+ auto *data = userdata.Get(nc);
+ if (data)
+ {
+ if (!data->last_mask.empty())
+ na->last_usermask = data->last_mask;
+
+ 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->noexpire)
+ na->Extend<bool>("NS_NO_EXPIRE");
+
+ auto vhost = data->vhost;
+ auto nick_vhost = data->vhost_nick.find(nick);
+ if (nick_vhost != data->vhost_nick.end())
+ vhost = nick_vhost->second;
+ if (!vhost.empty())
+ na->SetVHost("", vhost, data->vhost_creator, data->vhost_ts);
+ }
+
+ return true;
+ }
+
+ bool HandleMU(AthemeRow &row)
+ {
+ // MU <id> <display> <pass> <email> <regtime> <lastlogin> <flags> <language>
+ /* auto id = */ row.Get();
+ auto display = row.Get();
+ auto pass = row.Get();
+ auto email = row.Get();
+ auto regtime = row.GetNum<time_t>();
+ /* auto lastlogin = */ row.Get();
+ auto flags = row.Get();
+ auto language = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = new NickCore(display);
+ nc->email = email;
+ nc->time_registered = regtime;
+ ApplyPassword(nc, flags, pass);
+
+ // No equivalent: bglmNQrS
+ ApplyFlags(nc, flags, 'E', "KILLPROTECT");
+ ApplyFlags(nc, flags, 'e', "MEMO_MAIL");
+ ApplyFlags(nc, flags, 'n', "NEVEROP");
+ ApplyFlags(nc, flags, 'o', "AUTOOP", false);
+ ApplyFlags(nc, flags, 'P', "MSG");
+ ApplyFlags(nc, flags, 'p', "NS_PRIVATE");
+ ApplyFlags(nc, flags, 's', "HIDE_EMAIL");
+ ApplyFlags(nc, flags, 'W', "UNCONFIRMED");
+
+ // If an Atheme account was awaiting confirmation but Anope is not
+ // configured to use confirmation then autoconfirm it.
+ const auto &nsregister = Config->GetModule("ns_register")->Get<const Anope::string>("registration");
+ if (nsregister.equals_ci("none"))
+ nc->Shrink<bool>("UNCONFIRMED");
+
+ auto pos = flags.find('h');
+ if (pos != Anope::string::npos)
+ {
+ userdata.Require(nc)->noexpire = true;
+ flags.erase(pos, 1);
+ }
+
+
+ if (flags != "+")
+ Log(this) << "Unable to convert account flags " << flags << " for " << nc->display;
+
+ // No translations yet: bg, cy, da.
+ if (language == "de")
+ nc->language = "de_DE.UTF-8";
+ else if (language == "en")
+ nc->language = "en_US.UTF-8";
+ else if (language == "es")
+ nc->language = "es_ES.UTF-8";
+ else if (language == "fr")
+ nc->language = "fr_FR.UTF-8";
+ else if (language == "ru")
+ nc->language = "ru_RU.UTF-8";
+ else if (language == "tr")
+ nc->language = "tr_TR.UTF-8";
+ else if (language != "default")
+ {
+ Log(this) << "Unable to convert language " << language << " for " << nc->display;
+ }
+
+ return true;
+ }
+
+ bool HandleNAM(AthemeRow &row)
+ {
+ // NAM <nick>
+ auto nick = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!forbid_service)
+ {
+ Log(this) << "Unable to convert forbidden nick " << nick << " as os_forbid is not loaded";
+ return true;
+ }
+
+ auto *forbid = forbid_service->CreateForbid();
+ forbid->creator = "Unknown";
+ forbid->mask = nick;
+ forbid->reason = "Unknown";
+ forbid->type = FT_NICK;
+ forbid_service->AddForbid(forbid);
+ return true;
+ }
+
+ bool HandleQL(AthemeRow &row)
+ {
+ // QL <nick> <host> <duration> <settime> <setby> <reason>
+ auto id = row.Get();
+ auto nick = row.Get();
+ auto duration = row.GetNum<unsigned>();
+ auto settime = row.GetNum<time_t>();
+ auto setby = row.Get();
+ auto reason = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!sglinemgr)
+ {
+ Log(this) << "Unable to import Q-line on " << nick << " as operserv is not loaded";
+ return true;
+ }
+
+ auto *xl = new XLine(nick, setby, settime + duration, reason);
+ xl->id = id;
+ sqlinemgr->AddXLine(xl);
+ return true;
+ }
+
+ bool HandleSO(AthemeRow &row)
+ {
+ // SO <display> <type> <flags>
+ auto display = row.Get();
+ auto type = row.Get();
+ auto flags = row.Get();
+
+ if (!row)
+ return row.LogError(this);
+
+ auto *nc = NickCore::Find(display);
+ if (!nc)
+ {
+ Log(this) << "Missing NickCore for SO: " << display;
+ return false;
+ }
+
+ auto *ot = OperType::Find(type);
+ if (!ot)
+ {
+ // Attempt to convert oper types.
+ if (type == "sra")
+ ot = OperType::Find("Services Root");
+ else if (type == "ircop")
+ ot = OperType::Find("Services Operator");
+ }
+
+ if (!ot)
+ {
+ Log(this) << "Unable to convert operator status for " << nc->display << " as there is no equivalent oper type: " << type;
+ return true;
+ }
+
+ nc->o = new MyOper(nc->display, ot);
+ return true;
+ }
+
+ bool HandleXL(AthemeRow &row)
+ {
+ // XL <id> <real> <duration> <settime> <setby> <reason>
+ auto id = row.Get();
+ auto real = row.Get();
+ auto duration = row.GetNum<unsigned>();
+ auto settime = row.GetNum<time_t>();
+ auto setby = row.Get();
+ auto reason = row.GetRemaining();
+
+ if (!row)
+ return row.LogError(this);
+
+ if (!sglinemgr)
+ {
+ Log(this) << "Unable to import X-line on " << real << " as operserv is not loaded";
+ return true;
+ }
+
+ auto *xl = new XLine(real, setby, settime + duration, reason);
+ xl->id = id;
+ snlinemgr->AddXLine(xl);
+ return true;
+ }
+
+public:
+ DBAtheme(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, DATABASE | VENDOR)
+ , accessprov("AccessProvider", "access/flags")
+ , chandata(this, "ATHEME_CHANDATA")
+ , userdata(this, "ATHEME_USERDATA")
+ , sglinemgr("XLineManager","xlinemanager/sgline")
+ , snlinemgr("XLineManager","xlinemanager/snline")
+ , sqlinemgr("XLineManager","xlinemanager/sqline")
+ {
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ flags.clear();
+ for (int i = 0; i < Config->CountBlock("privilege"); ++i)
+ {
+ Configuration::Block *priv = Config->GetBlock("privilege", i);
+ const Anope::string &name = priv->Get<const Anope::string>("name");
+ const Anope::string &value = priv->Get<const Anope::string>("flag");
+ if (!name.empty() && !value.empty())
+ flags[name] = value[0];
+ }
+ }
+
+ EventReturn OnLoadDatabase() override
+ {
+ const auto dbname = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "atheme.db"));
+ std::ifstream fd(dbname.str());
+ if (!fd.is_open())
+ {
+ Log(this) << "Unable to open " << dbname << " for reading!";
+ return EVENT_STOP;
+ }
+
+ for (Anope::string buf; std::getline(fd, buf.str()); )
+ {
+ AthemeRow row(buf);
+
+ auto rowtype = row.Get();
+ if (!row)
+ continue; // Empty row.
+
+ auto rowhandler = rowhandlers.find(rowtype);
+ if (rowhandler == rowhandlers.end())
+ {
+ Log(this) << "Unknown row type: " << row.GetRow();
+ continue;
+ }
+
+ if (!rowhandler->second(this, row))
+ break;
+ }
+
+ for (const auto &[_, ci] : *RegisteredChannelList)
+ {
+ auto *data = chandata.Get(ci);
+ if (!data)
+ continue;
+
+ if (!data->bot.empty())
+ {
+ auto *bi = BotInfo::Find(data->bot);
+ if (bi)
+ bi->Assign(nullptr, ci);
+ }
+
+ if (!data->info_message.empty())
+ {
+ auto *oil = ci->Require<OperInfoList>("operinfo");
+ if (oil)
+ {
+ auto *info = oil->Create();
+ info->target = ci->name;
+ info->info = data->info_message;
+ info->adder = data->info_adder.empty() ? "Unknown" : data->info_adder;
+ info->created = data->info_ts;
+ (*oil)->push_back(info);
+ }
+ else
+ {
+ Log(this) << "Unable to convert oper info for " << ci->name << " as os_info is not loaded";
+ }
+ }
+
+ if (!data->suspend_reason.empty())
+ {
+ SuspendInfo si;
+ si.by = data->suspend_by.empty() ? "Unknown" : data->suspend_by;
+ si.expires = 0;
+ si.reason = data->suspend_reason;
+ si.what = ci->name;
+ si.when = data->suspend_ts;
+ ci->Extend("CS_SUSPENDED", si);
+ }
+ }
+
+ for (const auto &[_, nc] : *NickCoreList)
+ {
+ auto *data = userdata.Get(nc);
+ if (!data)
+ continue;
+
+ if (!data->info_message.empty())
+ {
+ auto *oil = nc->Require<OperInfoList>("operinfo");
+ if (oil)
+ {
+ auto *info = oil->Create();
+ info->target = nc->display;
+ info->info = data->info_message;
+ info->adder = data->info_adder.empty() ? "Unknown" : data->info_adder;
+ info->created = data->info_ts;
+ (*oil)->push_back(info);
+ }
+ else
+ {
+ Log(this) << "Unable to convert oper info for " << nc->display << " as os_info is not loaded";
+ }
+ }
+
+ if (!data->suspend_reason.empty())
+ {
+ SuspendInfo si;
+ si.by = data->suspend_by.empty() ? "Unknown" : data->suspend_by;
+ si.expires = 0;
+ si.reason = data->suspend_reason;
+ si.what = nc->display;
+ si.when = data->suspend_ts;
+ nc->Extend("NS_SUSPENDED", si);
+ }
+ }
+
+ return EVENT_STOP;
+ }
+
+ void OnUplinkSync(Server *s) override
+ {
+ for (auto &[_, ci] : *RegisteredChannelList)
+ {
+ auto *data = chandata.Get(ci);
+ if (!data)
+ continue;
+
+ auto *ml = ci->Require<ModeLocks>("modelocks");
+ if (!ml)
+ {
+ Log(this) << "Unable to convert mode locks for " << ci->name << " as cs_mode is not loaded";
+ continue;
+ }
+
+ for (const auto &mlock : data->mlocks)
+ {
+ ChannelMode *mh;
+ if (mlock.name.empty())
+ mh = ModeManager::FindChannelModeByChar(mlock.letter);
+ else
+ mh = ModeManager::FindChannelModeByName(mlock.name);
+ if (!mh)
+ {
+ Log(this) << "Unable to find mode while importing mode lock on " << ci->name << ": " << mlock.str();
+ continue;
+ }
+
+ ml->SetMLock(mh, mlock.set, mlock.value, "Unknown");
+ }
+ }
+ Anope::SaveDatabases();
+ }
+};
+
+MODULE_INIT(DBAtheme)
diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp
index d1080b009..9f2559c9e 100644
--- a/modules/database/db_flatfile.cpp
+++ b/modules/database/db_flatfile.cpp
@@ -15,15 +15,14 @@
#include <sys/wait.h>
#endif
-class SaveData : public Serialize::Data
+class SaveData final
+ : public Serialize::Data
{
- public:
+public:
Anope::string last;
- std::fstream *fs;
+ std::fstream *fs = nullptr;
- SaveData() : fs(NULL) { }
-
- std::iostream& operator[](const Anope::string &key) anope_override
+ std::iostream &operator[](const Anope::string &key) override
{
if (key != last)
{
@@ -35,18 +34,17 @@ class SaveData : public Serialize::Data
}
};
-class LoadData : public Serialize::Data
+class LoadData final
+ : public Serialize::Data
{
- public:
- std::fstream *fs;
- unsigned int id;
+public:
+ std::fstream *fs = nullptr;
+ unsigned int id = 0;
std::map<Anope::string, Anope::string> data;
std::stringstream ss;
- bool read;
-
- LoadData() : fs(NULL), id(0), read(false) { }
+ bool read = false;
- std::iostream& operator[](const Anope::string &key) anope_override
+ std::iostream &operator[](const Anope::string &key) override
{
if (!read)
{
@@ -54,12 +52,7 @@ class LoadData : public Serialize::Data
{
if (token.find("ID ") == 0)
{
- try
- {
- this->id = convertTo<unsigned int>(token.substr(3));
- }
- catch (const ConvertException &) { }
-
+ this->id = Anope::Convert(token.substr(3), 0);
continue;
}
else if (token.find("DATA ") != 0)
@@ -78,20 +71,12 @@ class LoadData : public Serialize::Data
return this->ss;
}
- std::set<Anope::string> KeySet() const anope_override
- {
- std::set<Anope::string> keys;
- for (std::map<Anope::string, Anope::string>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- keys.insert(it->first);
- return keys;
- }
-
- size_t Hash() const anope_override
+ size_t Hash() const override
{
size_t hash = 0;
- for (std::map<Anope::string, Anope::string>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- if (!it->second.empty())
- hash ^= Anope::hash_cs()(it->second);
+ for (const auto &[_, value] : this->data)
+ if (!value.empty())
+ hash ^= Anope::hash_cs()(value);
return hash;
}
@@ -103,15 +88,17 @@ class LoadData : public Serialize::Data
}
};
-class DBFlatFile : public Module, public Pipe
+class DBFlatFile final
+ : public Module
+ , public Pipe
{
/* Day the last backup was on */
- int last_day;
+ int last_day = 0;
/* Backup file names */
std::map<Anope::string, std::list<Anope::string> > backups;
- bool loaded;
+ bool loaded = false;
- int child_pid;
+ int child_pid = -1;
void BackupDatabase()
{
@@ -121,69 +108,67 @@ class DBFlatFile : public Module, public Pipe
{
last_day = tm->tm_mday;
- const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
-
std::set<Anope::string> dbs;
dbs.insert(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
- for (unsigned i = 0; i < type_order.size(); ++i)
+ for (const auto &type_order : Serialize::Type::GetTypeOrder())
{
- Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
+ Serialize::Type *stype = Serialize::Type::Find(type_order);
if (stype && stype->GetOwner())
dbs.insert("module_" + stype->GetOwner()->name + ".db");
}
- for (std::set<Anope::string>::const_iterator it = dbs.begin(), it_end = dbs.end(); it != it_end; ++it)
+ for (const auto &db : dbs)
{
- const Anope::string &oldname = Anope::DataDir + "/" + *it;
- Anope::string newname = Anope::DataDir + "/backups/" + *it + "-" + stringify(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday);
+ const auto oldname = Anope::ExpandData(db);
+ const auto newname = Anope::ExpandData("backups/" + db + "-" + Anope::ToString(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", 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 " << *it << " to " << newname;
+ 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 " << *it << " (" << err << ")!";
+ 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 " + *it + " (" + err + ")";
+ Anope::QuitReason = "Unable to back up database " + db + " (" + err + ")";
}
continue;
}
- backups[*it].push_back(newname);
+ backups[db].push_back(newname);
unsigned keepbackups = Config->GetModule(this)->Get<unsigned>("keepbackups");
- if (keepbackups > 0 && backups[*it].size() > keepbackups)
+ if (keepbackups > 0 && backups[db].size() > keepbackups)
{
- unlink(backups[*it].front().c_str());
- backups[*it].pop_front();
+ unlink(backups[db].front().c_str());
+ backups[db].pop_front();
}
}
}
}
- public:
- DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), last_day(0), loaded(false), child_pid(-1)
+public:
+ DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
{
}
#ifndef _WIN32
- void OnRestart() anope_override
+ void OnRestart() override
{
OnShutdown();
}
- void OnShutdown() anope_override
+ void OnShutdown() override
{
if (child_pid > -1)
{
@@ -197,7 +182,7 @@ class DBFlatFile : public Module, public Pipe
}
#endif
- void OnNotify() anope_override
+ void OnNotify() override
{
char buf[512];
int i = this->Read(buf, sizeof(buf) - 1);
@@ -219,12 +204,11 @@ class DBFlatFile : public Module, public Pipe
Anope::Quitting = true;
}
- EventReturn OnLoadDatabase() anope_override
+ EventReturn OnLoadDatabase() override
{
- const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
std::set<Anope::string> tried_dbs;
- const Anope::string &db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
+ const auto db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
if (!fd.is_open())
@@ -242,18 +226,16 @@ class DBFlatFile : public Module, public Pipe
LoadData ld;
ld.fs = &fd;
- for (unsigned i = 0; i < type_order.size(); ++i)
+ for (const auto &type_order : Serialize::Type::GetTypeOrder())
{
- Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
+ Serialize::Type *stype = Serialize::Type::Find(type_order);
if (!stype || stype->GetOwner())
continue;
- std::vector<std::streampos> &pos = positions[stype->GetName()];
-
- for (unsigned j = 0; j < pos.size(); ++j)
+ for (const auto &position : positions[stype->GetName()])
{
fd.clear();
- fd.seekg(pos[j]);
+ fd.seekg(position);
Serializable *obj = stype->Unserialize(NULL, ld);
if (obj != NULL)
@@ -269,7 +251,7 @@ class DBFlatFile : public Module, public Pipe
}
- void OnSaveDatabase() anope_override
+ void OnSaveDatabase() override
{
if (child_pid > -1)
{
@@ -299,18 +281,16 @@ class DBFlatFile : public Module, public Pipe
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 (std::map<Anope::string, Serialize::Type *>::const_iterator it = Serialize::Type::GetTypes().begin(), it_end = Serialize::Type::GetTypes().end(); it != it_end; ++it)
+ for (const auto &[_, s_type] : Serialize::Type::GetTypes())
{
- Serialize::Type *s_type = it->second;
-
if (databases[s_type->GetOwner()])
continue;
Anope::string db_name;
if (s_type->GetOwner())
- db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
+ db_name = Anope::ExpandData("module_" + s_type->GetOwner()->name + ".db");
else
- db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
+ 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);
@@ -320,9 +300,8 @@ class DBFlatFile : public Module, public Pipe
SaveData data;
const std::list<Serializable *> &items = Serializable::GetItems();
- for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it)
+ for (auto *base : items)
{
- Serializable *base = *it;
Serialize::Type *s_type = base->GetSerializableType();
if (!s_type)
continue;
@@ -338,10 +317,9 @@ class DBFlatFile : public Module, public Pipe
*data.fs << "\nEND\n";
}
- for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
+ for (auto &[mod, f] : databases)
{
- std::fstream *f = it->second;
- const Anope::string &db_name = Anope::DataDir + "/" + (it->first ? (it->first->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
+ 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())
{
@@ -376,16 +354,16 @@ class DBFlatFile : public Module, public Pipe
}
/* Load just one type. Done if a module is reloaded during runtime */
- void OnSerializeTypeCreate(Serialize::Type *stype) anope_override
+ void OnSerializeTypeCreate(Serialize::Type *stype) override
{
if (!loaded)
return;
Anope::string db_name;
if (stype->GetOwner())
- db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db";
+ db_name = Anope::ExpandData("module_" + stype->GetOwner()->name + ".db");
else
- db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
+ db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
if (!fd.is_open())
diff --git a/modules/database/db_old.cpp b/modules/database/db_old.cpp
index dd923b2dc..814740a23 100644
--- a/modules/database/db_old.cpp
+++ b/modules/database/db_old.cpp
@@ -35,13 +35,12 @@ else \
#define OLD_BI_PRIVATE 0x0001
#define OLD_NI_KILLPROTECT 0x00000001 /* Kill others who take this nick */
-#define OLD_NI_SECURE 0x00000002 /* Don't recognize unless IDENTIFY'd */
#define OLD_NI_MSG 0x00000004 /* Use PRIVMSGs instead of NOTICEs */
#define OLD_NI_MEMO_HARDMAX 0x00000008 /* Don't allow user to change memo limit */
#define OLD_NI_MEMO_SIGNON 0x00000010 /* Notify of memos at signon and un-away */
#define OLD_NI_MEMO_RECEIVE 0x00000020 /* Notify of new memos when sent */
#define OLD_NI_PRIVATE 0x00000040 /* Don't show in LIST to non-servadmins */
-#define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show E-mail in INFO */
+#define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show email in INFO */
#define OLD_NI_HIDE_MASK 0x00000100 /* Don't show last seen address in INFO */
#define OLD_NI_HIDE_QUIT 0x00000200 /* Don't show last quit message in INFO */
#define OLD_NI_KILL_QUICK 0x00000400 /* Kill in 20 seconds instead of 60 */
@@ -60,7 +59,6 @@ else \
#define OLD_CI_TOPICLOCK 0x00000008
#define OLD_CI_RESTRICTED 0x00000010
#define OLD_CI_PEACE 0x00000020
-#define OLD_CI_SECURE 0x00000040
#define OLD_CI_VERBOTEN 0x00000080
#define OLD_CI_ENCRYPTEDPW 0x00000100
#define OLD_CI_NO_EXPIRE 0x00000200
@@ -94,7 +92,7 @@ else \
#define OLD_NEWS_OPER 1
#define OLD_NEWS_RANDOM 2
-static struct mlock_info
+static struct mlock_info final
{
char c;
uint32_t m;
@@ -146,20 +144,22 @@ enum
static void process_mlock(ChannelInfo *ci, uint32_t lock, bool status, uint32_t *limit, Anope::string *key)
{
ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
- for (unsigned i = 0; i < (sizeof(mlock_infos) / sizeof(mlock_info)); ++i)
- if (lock & mlock_infos[i].m)
+ for (auto &mlock_info : mlock_infos)
+ {
+ if (lock & mlock_info.m)
{
- ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock_infos[i].c);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock_info.c);
if (cm && ml)
{
- if (limit && mlock_infos[i].c == 'l')
- ml->SetMLock(cm, status, stringify(*limit));
- else if (key && mlock_infos[i].c == 'k')
+ if (limit && mlock_info.c == 'l')
+ ml->SetMLock(cm, status, Anope::ToString(*limit));
+ else if (key && mlock_info.c == 'k')
ml->SetMLock(cm, status, *key);
else
ml->SetMLock(cm, status);
}
}
+ }
}
static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -205,7 +205,7 @@ static Anope::string Hex(const char *data, size_t l)
{
const char hextable[] = "0123456789abcdef";
- std::string rv;
+ Anope::string rv;
for (size_t i = 0; i < l; ++i)
{
unsigned char c = data[i];
@@ -252,7 +252,7 @@ static Anope::string GetLevelName(int level)
case 15:
return "NOKICK";
case 16:
- return "FANTASIA";
+ return "FANTASY";
case 17:
return "SAY";
case 18:
@@ -307,7 +307,7 @@ static char *strscpy(char *d, const char *s, size_t len)
return d_orig;
}
-struct dbFILE
+struct dbFILE final
{
int mode; /* 'r' for reading, 'w' for writing */
FILE *fp; /* The normal file descriptor */
@@ -321,7 +321,7 @@ static dbFILE *open_db_read(const char *service, const char *filename, int versi
int myversion;
f = new dbFILE;
- strscpy(f->filename, (Anope::DataDir + "/" + filename).c_str(), sizeof(f->filename));
+ strscpy(f->filename, Anope::ExpandData(filename).c_str(), sizeof(f->filename));
f->mode = 'r';
fp = fopen(f->filename, "rb");
if (!fp)
@@ -390,7 +390,7 @@ static int read_string(Anope::string &str, dbFILE *f)
return -1;
if (len == 0)
return 0;
- char *s = new char[len];
+ auto *s = new char[len];
if (len != fread(s, 1, len, f->fp))
{
delete [] s;
@@ -445,12 +445,12 @@ static void LoadNicks()
Anope::string buffer;
READ(read_string(buffer, f));
- NickCore *nc = new NickCore(buffer);
+ auto *nc = new NickCore(buffer);
- const Anope::string settings[] = { "killprotect", "kill_quick", "ns_secure", "ns_private", "hide_email",
+ const Anope::string settings[] = { "killprotect", "kill_quick", "ns_private", "hide_email",
"hide_mask", "hide_quit", "memo_signon", "memo_receive", "autoop", "msg", "ns_keepmodes" };
- for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j)
- nc->Shrink<bool>(settings[j].upper());
+ for (const auto &setting : settings)
+ nc->Shrink<bool>(setting.upper());
char pwbuf[32];
READ(read_buffer(pwbuf, f));
@@ -481,8 +481,6 @@ static void LoadNicks()
READ(read_uint32(&u32, f));
if (u32 & OLD_NI_KILLPROTECT)
nc->Extend<bool>("KILLPROTECT");
- if (u32 & OLD_NI_SECURE)
- nc->Extend<bool>("NS_SECURE");
if (u32 & OLD_NI_MSG)
nc->Extend<bool>("MSG");
if (u32 & OLD_NI_MEMO_HARDMAX)
@@ -539,24 +537,18 @@ static void LoadNicks()
case LANG_DE:
nc->language = "de_DE.UTF-8";
break;
- case LANG_CAT:
- nc->language = "ca_ES.UTF-8"; // yes, iso639 defines catalan as CA
- break;
case LANG_GR:
nc->language = "el_GR.UTF-8";
break;
case LANG_NL:
nc->language = "nl_NL.UTF-8";
break;
- case LANG_RU:
- nc->language = "ru_RU.UTF-8";
- break;
- case LANG_HUN:
- nc->language = "hu_HU.UTF-8";
- break;
case LANG_PL:
nc->language = "pl_PL.UTF-8";
break;
+ case LANG_CAT:
+ case LANG_HUN:
+ case LANG_RU:
case LANG_EN_US:
case LANG_JA_JIS:
case LANG_JA_EUC:
@@ -569,7 +561,6 @@ static void LoadNicks()
for (uint16_t j = 0; j < u16; ++j)
{
READ(read_string(buffer, f));
- nc->access.push_back(buffer);
}
int16_t i16;
@@ -577,7 +568,7 @@ static void LoadNicks()
READ(read_int16(&nc->memos.memomax, f));
for (int16_t j = 0; j < i16; ++j)
{
- Memo *m = new Memo;
+ auto *m = new Memo;
READ(read_uint32(&u32, f));
uint16_t flags;
READ(read_uint16(&flags, f));
@@ -653,7 +644,7 @@ static void LoadNicks()
continue;
}
- NickAlias *na = new NickAlias(nick, nc);
+ auto *na = new NickAlias(nick, nc);
na->last_usermask = last_usermask;
na->last_realname = last_realname;
na->last_quit = last_quit;
@@ -693,7 +684,7 @@ static void LoadVHosts()
continue;
}
- na->SetVhost(ident, host, creator, vtime);
+ na->SetVHost(ident, host, creator, vtime);
Log() << "Loaded vhost for " << na->nick;
}
@@ -748,12 +739,12 @@ static void LoadChannels()
Anope::string buffer;
char namebuf[64];
READ(read_buffer(namebuf, f));
- ChannelInfo *ci = new ChannelInfo(namebuf);
+ auto *ci = new ChannelInfo(namebuf);
- const Anope::string settings[] = { "keeptopic", "peace", "cs_private", "restricted", "cs_secure", "secureops", "securefounder",
+ const Anope::string settings[] = { "keeptopic", "peace", "cs_private", "restricted", "secureops", "securefounder",
"signkick", "signkick_level", "topiclock", "persist", "noautoop", "cs_keepmodes" };
- for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j)
- ci->Shrink<bool>(settings[j].upper());
+ for (const auto &setting : settings)
+ ci->Shrink<bool>(setting.upper());
READ(read_string(buffer, f));
ci->SetFounder(NickCore::Find(buffer));
@@ -799,8 +790,6 @@ static void LoadChannels()
ci->Extend<bool>("RESTRICTED");
if (tmpu32 & OLD_CI_PEACE)
ci->Extend<bool>("PEACE");
- if (tmpu32 & OLD_CI_SECURE)
- ci->Extend<bool>("CS_SECURE");
if (tmpu32 & OLD_CI_NO_EXPIRE)
ci->Extend<bool>("CS_NO_EXPIRE");
if (tmpu32 & OLD_CI_MEMO_HARDMAX)
@@ -894,7 +883,7 @@ static void LoadChannels()
}
}
else
- access->AccessUnserialize(stringify(level));
+ access->AccessUnserialize(Anope::ToString(level));
}
Anope::string mask;
@@ -948,7 +937,7 @@ static void LoadChannels()
{
READ(read_uint32(&tmpu32, f));
READ(read_uint16(&tmpu16, f));
- Memo *m = new Memo;
+ auto *m = new Memo;
READ(read_int32(&tmp32, f));
m->time = tmp32;
char sbuf[32];
@@ -1104,9 +1093,8 @@ static void LoadOper()
XLineManager *akill, *sqline, *snline, *szline;
akill = sqline = snline = szline = NULL;
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it)
+ for (auto *xl : XLineManager::XLineManagers)
{
- XLineManager *xl = *it;
if (xl->Type() == 'G')
akill = xl;
else if (xl->Type() == 'Q')
@@ -1138,7 +1126,7 @@ static void LoadOper()
if (!akill)
continue;
- XLine *x = new XLine(user + "@" + host, by, expires, reason, XLineManager::GenerateUID());
+ auto *x = new XLine(user + "@" + host, by, expires, reason, XLineManager::GenerateUID());
x->created = seton;
akill->AddXLine(x);
}
@@ -1158,7 +1146,7 @@ static void LoadOper()
if (!snline)
continue;
- XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
+ auto *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
x->created = seton;
snline->AddXLine(x);
}
@@ -1178,7 +1166,7 @@ static void LoadOper()
if (!sqline)
continue;
- XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
+ auto *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
x->created = seton;
sqline->AddXLine(x);
}
@@ -1198,7 +1186,7 @@ static void LoadOper()
if (!szline)
continue;
- XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
+ auto *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
x->created = seton;
szline->AddXLine(x);
}
@@ -1296,12 +1284,13 @@ static void LoadNews()
close_db(f);
}
-class DBOld : public Module
+class DBOld final
+ : public Module
{
PrimitiveExtensibleItem<uint32_t> mlock_on, mlock_off, mlock_limit;
PrimitiveExtensibleItem<Anope::string> mlock_key;
- public:
+public:
DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR),
mlock_on(this, "mlock_on"), mlock_off(this, "mlock_off"), mlock_limit(this, "mlock_limit"), mlock_key(this, "mlock_key")
{
@@ -1313,7 +1302,7 @@ class DBOld : public Module
throw ModuleException("Invalid hash method");
}
- EventReturn OnLoadDatabase() anope_override
+ EventReturn OnLoadDatabase() override
{
LoadNicks();
LoadVHosts();
@@ -1326,11 +1315,10 @@ class DBOld : public Module
return EVENT_STOP;
}
- void OnUplinkSync(Server *s) anope_override
+ void OnUplinkSync(Server *s) override
{
- for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
+ for (auto &[_, ci] : *RegisteredChannelList)
{
- ChannelInfo *ci = it->second;
uint32_t *limit = mlock_limit.Get(ci);
Anope::string *key = mlock_key.Get(ci);
@@ -1354,6 +1342,7 @@ class DBOld : public Module
if (ci->c)
ci->c->CheckModes();
}
+ Anope::SaveDatabases();
}
};
diff --git a/modules/database/db_redis.cpp b/modules/database/db_redis.cpp
index ec9e85fec..a4826349b 100644
--- a/modules/database/db_redis.cpp
+++ b/modules/database/db_redis.cpp
@@ -14,116 +14,118 @@ using namespace Redis;
class DatabaseRedis;
static DatabaseRedis *me;
-class Data : public Serialize::Data
+class Data final
+ : public Serialize::Data
{
- public:
+public:
std::map<Anope::string, std::stringstream *> data;
- ~Data()
+ ~Data() override
{
- for (std::map<Anope::string, std::stringstream *>::iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
- delete it->second;
+ for (auto &[_, stream] : data)
+ delete stream;
}
- std::iostream& operator[](const Anope::string &key) anope_override
+ std::iostream &operator[](const Anope::string &key) override
{
- std::stringstream* &stream = data[key];
+ std::stringstream *&stream = data[key];
if (!stream)
stream = new std::stringstream();
return *stream;
}
- std::set<Anope::string> KeySet() const anope_override
- {
- std::set<Anope::string> keys;
- for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- keys.insert(it->first);
- return keys;
- }
-
- size_t Hash() const anope_override
+ size_t Hash() const override
{
size_t hash = 0;
- for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- if (!it->second->str().empty())
- hash ^= Anope::hash_cs()(it->second->str());
+ for (const auto &[_, value] : this->data)
+ if (!value->str().empty())
+ hash ^= Anope::hash_cs()(value->str());
return hash;
}
};
-class TypeLoader : public Interface
+class TypeLoader final
+ : public Interface
{
Anope::string type;
- public:
+public:
TypeLoader(Module *creator, const Anope::string &t) : Interface(creator), type(t) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class ObjectLoader : public Interface
+class ObjectLoader final
+ : public Interface
{
Anope::string type;
int64_t id;
- public:
+public:
ObjectLoader(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class IDInterface : public Interface
+class IDInterface final
+ : public Interface
{
Reference<Serializable> o;
- public:
+public:
IDInterface(Module *creator, Serializable *obj) : Interface(creator), o(obj) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class Deleter : public Interface
+class Deleter final
+ : public Interface
{
Anope::string type;
int64_t id;
- public:
+public:
Deleter(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class Updater : public Interface
+class Updater final
+ : public Interface
{
Anope::string type;
int64_t id;
- public:
+public:
Updater(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class ModifiedObject : public Interface
+class ModifiedObject final
+ : public Interface
{
Anope::string type;
int64_t id;
- public:
+public:
ModifiedObject(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class SubscriptionListener : public Interface
+class SubscriptionListener final
+ : public Interface
{
- public:
+public:
SubscriptionListener(Module *creator) : Interface(creator) { }
- void OnResult(const Reply &r) anope_override;
+ void OnResult(const Reply &r) override;
};
-class DatabaseRedis : public Module, public Pipe
+class DatabaseRedis final
+ : public Module
+ , public Pipe
{
SubscriptionListener sl;
std::set<Serializable *> updated_items;
- public:
+public:
ServiceReference<Provider> redis;
DatabaseRedis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), sl(this)
@@ -151,33 +153,31 @@ class DatabaseRedis : public Module, public Pipe
obj->UpdateCache(data);
std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
+ args.emplace_back("HGETALL");
+ args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id));
/* Get object attrs to clear before updating */
redis->SendCommand(new Updater(this, t->GetName(), obj->id), args);
}
}
- void OnNotify() anope_override
+ void OnNotify() override
{
- for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it)
+ for (auto *obj : this->updated_items)
{
- Serializable *s = *it;
-
- this->InsertObject(s);
+ this->InsertObject(obj);
}
this->updated_items.clear();
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
this->redis = ServiceReference<Provider>("Redis::Provider", block->Get<const Anope::string>("engine", "redis/main"));
}
- EventReturn OnLoadDatabase() anope_override
+ EventReturn OnLoadDatabase() override
{
if (!redis)
{
@@ -185,10 +185,9 @@ class DatabaseRedis : public Module, public Pipe
return EVENT_CONTINUE;
}
- const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
- for (unsigned i = 0; i < type_order.size(); ++i)
+ for (const auto &type_order : Serialize::Type::GetTypeOrder())
{
- Serialize::Type *sb = Serialize::Type::Find(type_order[i]);
+ Serialize::Type *sb = Serialize::Type::Find(type_order);
this->OnSerializeTypeCreate(sb);
}
@@ -205,25 +204,25 @@ class DatabaseRedis : public Module, public Pipe
return EVENT_STOP;
}
- void OnSerializeTypeCreate(Serialize::Type *sb) anope_override
+ void OnSerializeTypeCreate(Serialize::Type *sb) override
{
if (!redis)
return;
std::vector<Anope::string> args;
- args.push_back("SMEMBERS");
+ args.emplace_back("SMEMBERS");
args.push_back("ids:" + sb->GetName());
redis->SendCommand(new TypeLoader(this, sb->GetName()), args);
}
- void OnSerializableConstruct(Serializable *obj) anope_override
+ void OnSerializableConstruct(Serializable *obj) override
{
this->updated_items.insert(obj);
this->Notify();
}
- void OnSerializableDestruct(Serializable *obj) anope_override
+ void OnSerializableDestruct(Serializable *obj) override
{
Serialize::Type *t = obj->GetSerializableType();
@@ -240,8 +239,8 @@ class DatabaseRedis : public Module, public Pipe
}
std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
+ args.emplace_back("HGETALL");
+ args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id));
/* Get all of the attributes for this object */
redis->SendCommand(new Deleter(this, t->GetName(), obj->id), args);
@@ -251,7 +250,7 @@ class DatabaseRedis : public Module, public Pipe
this->Notify();
}
- void OnSerializableUpdate(Serializable *obj) anope_override
+ void OnSerializableUpdate(Serializable *obj) override
{
this->updated_items.insert(obj);
this->Notify();
@@ -266,26 +265,19 @@ void TypeLoader::OnResult(const Reply &r)
return;
}
- for (unsigned i = 0; i < r.multi_bulk.size(); ++i)
+ for (auto *reply : r.multi_bulk)
{
- const Reply *reply = r.multi_bulk[i];
-
if (reply->type != Reply::BULK)
continue;
- int64_t id;
- try
- {
- id = convertTo<int64_t>(reply->bulk);
- }
- catch (const ConvertException &)
- {
+ auto i = Anope::TryConvert<int64_t>(reply->bulk);
+ if (!i)
continue;
- }
+ auto id = i.value();
std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + this->type + ":" + stringify(id));
+ args.emplace_back("HGETALL");
+ args.push_back("hash:" + this->type + ":" + Anope::ToString(id));
me->redis->SendCommand(new ObjectLoader(me, this->type, id), args);
}
@@ -313,7 +305,7 @@ void ObjectLoader::OnResult(const Reply &r)
data[key->bulk] << value->bulk;
}
- Serializable* &obj = st->objects[this->id];
+ Serializable *&obj = st->objects[this->id];
obj = st->Unserialize(obj, data);
if (obj)
{
@@ -332,7 +324,7 @@ void IDInterface::OnResult(const Reply &r)
return;
}
- Serializable* &obj = o->GetSerializableType()->objects[r.i];
+ Serializable *&obj = o->GetSerializableType()->objects[r.i];
if (obj)
/* This shouldn't be possible */
obj->id = 0;
@@ -358,16 +350,16 @@ void Deleter::OnResult(const Reply &r)
me->redis->StartTransaction();
std::vector<Anope::string> args;
- args.push_back("DEL");
- args.push_back("hash:" + this->type + ":" + stringify(this->id));
+ args.emplace_back("DEL");
+ args.push_back("hash:" + this->type + ":" + Anope::ToString(this->id));
/* Delete hash object */
me->redis->SendCommand(NULL, args);
args.clear();
- args.push_back("SREM");
+ args.emplace_back("SREM");
args.push_back("ids:" + this->type);
- args.push_back(stringify(this->id));
+ args.push_back(Anope::ToString(this->id));
/* Delete id from ids set */
me->redis->SendCommand(NULL, args);
@@ -378,9 +370,9 @@ void Deleter::OnResult(const Reply &r)
*value = r.multi_bulk[i + 1];
args.clear();
- args.push_back("SREM");
+ args.emplace_back("SREM");
args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
- args.push_back(stringify(this->id));
+ args.push_back(Anope::ToString(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -421,9 +413,9 @@ void Updater::OnResult(const Reply &r)
*value = r.multi_bulk[i + 1];
std::vector<Anope::string> args;
- args.push_back("SREM");
+ args.emplace_back("SREM");
args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
- args.push_back(stringify(this->id));
+ args.push_back(Anope::ToString(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -431,29 +423,25 @@ void Updater::OnResult(const Reply &r)
/* Add object id to id set for this type */
std::vector<Anope::string> args;
- args.push_back("SADD");
+ args.emplace_back("SADD");
args.push_back("ids:" + this->type);
- args.push_back(stringify(obj->id));
+ args.push_back(Anope::ToString(obj->id));
me->redis->SendCommand(NULL, args);
args.clear();
- args.push_back("HMSET");
- args.push_back("hash:" + this->type + ":" + stringify(obj->id));
+ args.emplace_back("HMSET");
+ args.push_back("hash:" + this->type + ":" + Anope::ToString(obj->id));
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (const auto &[key, value] : data.data)
{
- const Anope::string &key = it->first;
- std::stringstream *value = it->second;
-
args.push_back(key);
- args.push_back(value->str());
+ args.emplace_back(value->str());
std::vector<Anope::string> args2;
- args2.push_back("SADD");
+ args2.emplace_back("SADD");
args2.push_back("value:" + this->type + ":" + key + ":" + value->str());
- args2.push_back(stringify(obj->id));
+ args2.push_back(Anope::ToString(obj->id));
/* Add to value -> object id set */
me->redis->SendCommand(NULL, args2);
@@ -504,16 +492,11 @@ void SubscriptionListener::OnResult(const Reply &r)
if (s_type == NULL)
return;
- uint64_t obj_id;
- try
- {
- obj_id = convertTo<uint64_t>(id);
- }
- catch (const ConvertException &)
- {
+ auto oid = Anope::TryConvert<uint64_t>(id);
+ if (!oid.has_value())
return;
- }
+ auto obj_id = oid.value();
if (op == "hset" || op == "hdel")
{
Serializable *s = s_type->objects[obj_id];
@@ -528,7 +511,7 @@ void SubscriptionListener::OnResult(const Reply &r)
Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type;
std::vector<Anope::string> args;
- args.push_back("HGETALL");
+ args.emplace_back("HGETALL");
args.push_back("hash:" + type + ":" + id);
me->redis->SendCommand(new ModifiedObject(me, type, obj_id), args);
@@ -536,7 +519,7 @@ void SubscriptionListener::OnResult(const Reply &r)
}
else if (op == "del")
{
- Serializable* &s = s_type->objects[obj_id];
+ Serializable *&s = s_type->objects[obj_id];
if (s == NULL)
return;
@@ -549,14 +532,10 @@ void SubscriptionListener::OnResult(const Reply &r)
/* Transaction start */
me->redis->StartTransaction();
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (const auto &[k, value] : data.data)
{
- const Anope::string &k = it->first;
- std::stringstream *value = it->second;
-
std::vector<Anope::string> args;
- args.push_back("SREM");
+ args.emplace_back("SREM");
args.push_back("value:" + type + ":" + k + ":" + value->str());
args.push_back(id);
@@ -565,9 +544,9 @@ void SubscriptionListener::OnResult(const Reply &r)
}
std::vector<Anope::string> args;
- args.push_back("SREM");
+ args.emplace_back("SREM");
args.push_back("ids:" + type);
- args.push_back(stringify(s->id));
+ args.push_back(Anope::ToString(s->id));
/* Delete object from id set */
me->redis->SendCommand(NULL, args);
@@ -590,7 +569,7 @@ void ModifiedObject::OnResult(const Reply &r)
return;
}
- Serializable* &obj = st->objects[this->id];
+ Serializable *&obj = st->objects[this->id];
/* Transaction start */
me->redis->StartTransaction();
@@ -602,16 +581,12 @@ void ModifiedObject::OnResult(const Reply &r)
obj->Serialize(data);
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (auto &[key, value] : data.data)
{
- const Anope::string &key = it->first;
- std::stringstream *value = it->second;
-
std::vector<Anope::string> args;
- args.push_back("SREM");
+ args.emplace_back("SREM");
args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str());
- args.push_back(stringify(this->id));
+ args.push_back(Anope::ToString(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -635,25 +610,21 @@ void ModifiedObject::OnResult(const Reply &r)
obj->UpdateCache(data);
/* Insert new object values */
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (const auto &[key, value] : data.data)
{
- const Anope::string &key = it->first;
- std::stringstream *value = it->second;
-
std::vector<Anope::string> args;
- args.push_back("SADD");
+ args.emplace_back("SADD");
args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str());
- args.push_back(stringify(obj->id));
+ args.push_back(Anope::ToString(obj->id));
/* Add to value -> object id set */
me->redis->SendCommand(NULL, args);
}
std::vector<Anope::string> args;
- args.push_back("SADD");
+ args.emplace_back("SADD");
args.push_back("ids:" + st->GetName());
- args.push_back(stringify(obj->id));
+ args.push_back(Anope::ToString(obj->id));
/* Add to type -> id set */
me->redis->SendCommand(NULL, args);
diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp
index c643017b3..bfcd59a3d 100644
--- a/modules/database/db_sql.cpp
+++ b/modules/database/db_sql.cpp
@@ -14,17 +14,18 @@
using namespace SQL;
-class SQLSQLInterface : public Interface
+class SQLSQLInterface
+ : public Interface
{
- public:
+public:
SQLSQLInterface(Module *o) : Interface(o) { }
- void OnResult(const Result &r) anope_override
+ void OnResult(const Result &r) override
{
Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
}
- void OnError(const Result &r) anope_override
+ void OnError(const Result &r) override
{
if (!r.GetQuery().query.empty())
Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
@@ -33,14 +34,15 @@ class SQLSQLInterface : public Interface
}
};
-class ResultSQLSQLInterface : public SQLSQLInterface
+class ResultSQLSQLInterface final
+ : public SQLSQLInterface
{
Reference<Serializable> obj;
public:
ResultSQLSQLInterface(Module *o, Serializable *ob) : SQLSQLInterface(o), obj(ob) { }
- void OnResult(const Result &r) anope_override
+ void OnResult(const Result &r) override
{
SQLSQLInterface::OnResult(r);
if (r.GetID() > 0 && this->obj)
@@ -48,14 +50,16 @@ public:
delete this;
}
- void OnError(const Result &r) anope_override
+ void OnError(const Result &r) override
{
SQLSQLInterface::OnError(r);
delete this;
}
};
-class DBSQL : public Module, public Pipe
+class DBSQL final
+ : public Module
+ , public Pipe
{
ServiceReference<Provider> sql;
SQLSQLInterface sqlinterface;
@@ -63,10 +67,15 @@ class DBSQL : public Module, public Pipe
bool import;
std::set<Serializable *> updated_items;
- bool shutting_down;
- bool loading_databases;
- bool loaded;
- bool imported;
+ bool shutting_down = false;
+ bool loading_databases = false;
+ bool loaded = false;
+ bool imported = false;
+
+ Anope::string GetTableName(Serialize::Type *s_type)
+ {
+ return this->prefix + s_type->GetName();
+ }
void RunBackground(const Query &q, Interface *iface = NULL)
{
@@ -89,8 +98,8 @@ class DBSQL : public Module, public Pipe
this->sql->RunQuery(q);
}
- public:
- DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), sql("", ""), sqlinterface(this), shutting_down(false), loading_databases(false), loaded(false), imported(false)
+public:
+ DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), sql("", ""), sqlinterface(this)
{
@@ -98,12 +107,10 @@ class DBSQL : public Module, public Pipe
throw ModuleException("db_sql can not be loaded after db_sql_live");
}
- void OnNotify() anope_override
+ void OnNotify() override
{
- for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it)
+ for (auto *obj : this->updated_items)
{
- Serializable *obj = *it;
-
if (this->sql)
{
Data data;
@@ -122,20 +129,20 @@ class DBSQL : public Module, public Pipe
if (!s_type)
continue;
- std::vector<Query> create = this->sql->CreateTable(this->prefix + s_type->GetName(), data);
- Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, data);
+ auto create = this->sql->CreateTable(GetTableName(s_type), data);
+ auto insert = this->sql->BuildInsert(GetTableName(s_type), obj->id, data);
if (this->imported)
{
- for (unsigned i = 0; i < create.size(); ++i)
- this->RunBackground(create[i]);
+ for (const auto &query : create)
+ this->RunBackground(query);
this->RunBackground(insert, new ResultSQLSQLInterface(this, obj));
}
else
{
- for (unsigned i = 0; i < create.size(); ++i)
- this->sql->RunQuery(create[i]);
+ for (const auto &query : create)
+ this->sql->RunQuery(query);
/* We are importing objects from another database module, so don't do asynchronous
* queries in case the core has to shut down, it will cut short the import
@@ -151,7 +158,7 @@ class DBSQL : public Module, public Pipe
this->imported = true;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
this->sql = ServiceReference<Provider>("SQL::Provider", block->Get<const Anope::string>("engine"));
@@ -159,7 +166,7 @@ class DBSQL : public Module, public Pipe
this->import = block->Get<bool>("import");
}
- void OnPostInit() anope_override
+ void OnPostInit() override
{
// If we are importing from flatfile we need to force a socket engine
// flush to ensure it actually gets written to the database before we
@@ -167,18 +174,18 @@ class DBSQL : public Module, public Pipe
SocketEngine::Process();
}
- void OnShutdown() anope_override
+ void OnShutdown() override
{
this->shutting_down = true;
this->OnNotify();
}
- void OnRestart() anope_override
+ void OnRestart() override
{
this->OnShutdown();
}
- EventReturn OnLoadDatabase() anope_override
+ EventReturn OnLoadDatabase() override
{
if (!this->sql)
{
@@ -188,10 +195,9 @@ class DBSQL : public Module, public Pipe
this->loading_databases = true;
- const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
- for (unsigned i = 0; i < type_order.size(); ++i)
+ for (const auto &type_order : Serialize::Type::GetTypeOrder())
{
- Serialize::Type *sb = Serialize::Type::Find(type_order[i]);
+ Serialize::Type *sb = Serialize::Type::Find(type_order);
this->OnSerializeTypeCreate(sb);
}
@@ -201,7 +207,7 @@ class DBSQL : public Module, public Pipe
return EVENT_STOP;
}
- void OnSerializableConstruct(Serializable *obj) anope_override
+ void OnSerializableConstruct(Serializable *obj) override
{
if (this->shutting_down || this->loading_databases)
return;
@@ -210,17 +216,17 @@ class DBSQL : public Module, public Pipe
this->Notify();
}
- void OnSerializableDestruct(Serializable *obj) anope_override
+ void OnSerializableDestruct(Serializable *obj) override
{
if (this->shutting_down)
return;
Serialize::Type *s_type = obj->GetSerializableType();
if (s_type && obj->id > 0)
- this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
+ this->RunBackground("DELETE FROM `" + GetTableName(s_type) + "` WHERE `id` = " + Anope::ToString(obj->id));
this->updated_items.erase(obj);
}
- void OnSerializableUpdate(Serializable *obj) anope_override
+ void OnSerializableUpdate(Serializable *obj) override
{
if (this->shutting_down || obj->IsTSCached())
return;
@@ -231,35 +237,30 @@ class DBSQL : public Module, public Pipe
this->Notify();
}
- void OnSerializeTypeCreate(Serialize::Type *sb) anope_override
+ void OnSerializeTypeCreate(Serialize::Type *sb) override
{
if (!this->loading_databases && !this->loaded)
return;
- Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
+ Query query("SELECT * FROM `" + GetTableName(sb) + "`");
Result res = this->sql->RunQuery(query);
for (int j = 0; j < res.Rows(); ++j)
{
Data data;
- const std::map<Anope::string, Anope::string> &row = res.Row(j);
- for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit)
- data[rit->first] << rit->second;
+ for (const auto &[key, value] : res.Row(j))
+ data[key] << value;
Serializable *obj = sb->Unserialize(NULL, data);
- try
- {
- if (obj)
- obj->id = convertTo<unsigned int>(res.Get(j, "id"));
- }
- catch (const ConvertException &)
- {
- Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
- }
-
if (obj)
{
+ auto oid = Anope::TryConvert<unsigned int>(res.Get(j, "id"));
+ if (oid.has_value())
+ obj->id = oid.value();
+ else
+ Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
+
/* The Unserialize operation is destructive so rebuild the data for UpdateCache.
* Also the old data may contain columns that we don't use, so we reserialize the
* object to know for sure our cache is consistent
diff --git a/modules/database/db_sql_live.cpp b/modules/database/db_sql_live.cpp
index e8fa9fa2f..3a02bd0c5 100644
--- a/modules/database/db_sql_live.cpp
+++ b/modules/database/db_sql_live.cpp
@@ -11,9 +11,11 @@
using namespace SQL;
-class DBMySQL : public Module, public Pipe
+class DBMySQL final
+ : public Module
+ , public Pipe
{
- private:
+private:
Anope::string prefix;
ServiceReference<Provider> SQL;
time_t lastwarn;
@@ -35,7 +37,7 @@ class DBMySQL : public Module, public Pipe
}
else
{
- if (Anope::CurTime - Config->GetBlock("options")->Get<time_t>("updatetimeout", "5m") > lastwarn)
+ if (Anope::CurTime - Config->GetBlock("options")->Get<time_t>("updatetimeout", "2m") > lastwarn)
{
Log() << "Unable to locate SQL reference, going to readonly...";
Anope::ReadOnly = this->ro = true;
@@ -51,13 +53,12 @@ class DBMySQL : public Module, public Pipe
return init && SQL;
}
- void RunQuery(const Query &query)
+ Anope::string GetTableName(Serialize::Type *s_type)
{
- /* Can this be threaded? */
- this->RunQueryResult(query);
+ return this->prefix + s_type->GetName();
}
- Result RunQueryResult(const Query &query)
+ Result RunQuery(const Query &query)
{
if (this->CheckSQL())
{
@@ -71,7 +72,7 @@ class DBMySQL : public Module, public Pipe
throw SQL::Exception("No SQL!");
}
- public:
+public:
DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), SQL("", "")
{
this->lastwarn = 0;
@@ -83,15 +84,13 @@ class DBMySQL : public Module, public Pipe
throw ModuleException("If db_sql_live is loaded it must be the first database module loaded.");
}
- void OnNotify() anope_override
+ void OnNotify() override
{
if (!this->CheckInit())
return;
- for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it)
+ for (auto *obj : this->updated_items)
{
- Serializable *obj = *it;
-
if (obj && this->SQL)
{
Data data;
@@ -106,11 +105,11 @@ class DBMySQL : public Module, public Pipe
if (!s_type)
continue;
- std::vector<Query> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), data);
- for (unsigned i = 0; i < create.size(); ++i)
- this->RunQueryResult(create[i]);
+ auto create = this->SQL->CreateTable(GetTableName(s_type), data);
+ for (const auto &query : create)
+ this->RunQuery(query);
- Result res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, data));
+ auto res = this->RunQuery(this->SQL->BuildInsert(GetTableName(s_type), obj->id, data));
if (res.GetID() && obj->id != res.GetID())
{
/* In this case obj is new, so place it into the object map */
@@ -123,30 +122,30 @@ class DBMySQL : public Module, public Pipe
this->updated_items.clear();
}
- EventReturn OnLoadDatabase() anope_override
+ EventReturn OnLoadDatabase() override
{
init = true;
return EVENT_STOP;
}
- void OnShutdown() anope_override
+ void OnShutdown() override
{
init = false;
}
- void OnRestart() anope_override
+ void OnRestart() override
{
init = false;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
this->SQL = ServiceReference<Provider>("SQL::Provider", block->Get<const Anope::string>("engine"));
this->prefix = block->Get<const Anope::string>("prefix", "anope_db_");
}
- void OnSerializableConstruct(Serializable *obj) anope_override
+ void OnSerializableConstruct(Serializable *obj) override
{
if (!this->CheckInit())
return;
@@ -155,7 +154,7 @@ class DBMySQL : public Module, public Pipe
this->Notify();
}
- void OnSerializableDestruct(Serializable *obj) anope_override
+ void OnSerializableDestruct(Serializable *obj) override
{
if (!this->CheckInit())
return;
@@ -163,39 +162,38 @@ class DBMySQL : public Module, public Pipe
if (s_type)
{
if (obj->id > 0)
- this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
+ this->RunQuery("DELETE FROM `" + GetTableName(s_type) + "` WHERE `id` = " + Anope::ToString(obj->id));
s_type->objects.erase(obj->id);
}
this->updated_items.erase(obj);
}
- void OnSerializeCheck(Serialize::Type *obj) anope_override
+ void OnSerializeCheck(Serialize::Type *obj) override
{
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
return;
- Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
+ Query query("SELECT * FROM `" + GetTableName(obj) + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
obj->UpdateTimestamp();
- Result res = this->RunQueryResult(query);
+ Result res = this->RunQuery(query);
bool clear_null = false;
for (int i = 0; i < res.Rows(); ++i)
{
const std::map<Anope::string, Anope::string> &row = res.Row(i);
- unsigned int id;
- try
- {
- id = convertTo<unsigned int>(res.Get(i, "id"));
- }
- catch (const ConvertException &)
+
+
+ auto oid = Anope::TryConvert<unsigned int>(res.Get(i, "id"));
+ if (!oid.has_value())
{
Log(LOG_DEBUG) << "Unable to convert id from " << obj->GetName();
continue;
}
+ auto id = oid.value();
if (res.Get(i, "timestamp").empty())
{
clear_null = true;
@@ -207,8 +205,8 @@ class DBMySQL : public Module, public Pipe
{
Data data;
- for (std::map<Anope::string, Anope::string>::const_iterator it = row.begin(), it_end = row.end(); it != it_end; ++it)
- data[it->first] << it->second;
+ for (const auto &[key, value] : row)
+ data[key] << value;
Serializable *s = NULL;
std::map<uint64_t, Serializable *>::iterator it = obj->objects.find(id);
@@ -237,7 +235,7 @@ class DBMySQL : public Module, public Pipe
else
{
if (!s)
- this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id));
+ this->RunQuery("UPDATE `" + GetTableName(obj) + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
else
delete s;
}
@@ -246,12 +244,12 @@ class DBMySQL : public Module, public Pipe
if (clear_null)
{
- query = "DELETE FROM `" + this->prefix + obj->GetName() + "` WHERE `timestamp` IS NULL";
+ query = "DELETE FROM `" + GetTableName(obj) + "` WHERE `timestamp` IS NULL";
this->RunQuery(query);
}
}
- void OnSerializableUpdate(Serializable *obj) anope_override
+ void OnSerializableUpdate(Serializable *obj) override
{
if (!this->CheckInit() || obj->IsTSCached())
return;
diff --git a/modules/m_dns.cpp b/modules/dns.cpp
index e21bf876a..f94854058 100644
--- a/modules/m_dns.cpp
+++ b/modules/dns.cpp
@@ -23,14 +23,15 @@ namespace
/** A full packet sent or received to/from the nameserver
*/
-class Packet : public Query
+class Packet final
+ : public Query
{
static bool IsValidName(const Anope::string &name)
{
return name.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-") == Anope::string::npos;
}
- void PackName(unsigned char *output, unsigned short output_size, unsigned short &pos, const Anope::string &name)
+ static void PackName(unsigned char *output, unsigned short output_size, unsigned short &pos, const Anope::string &name)
{
if (pos + name.length() + 2 > output_size)
throw SocketException("Unable to pack name");
@@ -50,7 +51,7 @@ class Packet : public Query
output[pos++] = 0;
}
- Anope::string UnpackName(const unsigned char *input, unsigned short input_size, unsigned short &pos)
+ static Anope::string UnpackName(const unsigned char *input, unsigned short input_size, unsigned short &pos)
{
Anope::string name;
unsigned short pos_ptr = pos, lowest_ptr = input_size;
@@ -71,7 +72,7 @@ class Packet : public Query
throw SocketException("Unable to unpack name - bogus compression header");
/* Place pos at the second byte of the first (farthest) compression pointer */
- if (compressed == false)
+ if (!compressed)
{
++pos;
compressed = true;
@@ -94,7 +95,7 @@ class Packet : public Query
name += input[pos_ptr + i];
pos_ptr += offset + 1;
- if (compressed == false)
+ if (!compressed)
/* Move up pos */
pos = pos_ptr;
}
@@ -200,7 +201,7 @@ class Packet : public Query
return record;
}
- public:
+public:
static const int POINTER = 0xC0;
static const int LABEL = 0x3F;
static const int HEADER_LENGTH = 12;
@@ -209,11 +210,11 @@ class Packet : public Query
/* Source or destination of the packet */
sockaddrs addr;
/* ID for this packet */
- unsigned short id;
+ unsigned short id = 0;
/* Flags on the packet */
- unsigned short flags;
+ unsigned short flags = 0;
- Packet(Manager *m, sockaddrs *a) : manager(m), id(0), flags(0)
+ Packet(Manager *m, sockaddrs *a) : manager(m)
{
if (a)
addr = *a;
@@ -286,10 +287,8 @@ class Packet : public Query
output[pos++] = this->additional.size() >> 8;
output[pos++] = this->additional.size() & 0xFF;
- for (unsigned i = 0; i < this->questions.size(); ++i)
+ for (auto &q : this->questions)
{
- Question &q = this->questions[i];
-
if (q.type == QUERY_PTR)
{
sockaddrs ip(q.name);
@@ -324,11 +323,10 @@ class Packet : public Query
}
std::vector<ResourceRecord> types[] = { this->answers, this->authorities, this->additional };
- for (int i = 0; i < 3; ++i)
- for (unsigned j = 0; j < types[i].size(); ++j)
+ for (auto &type : types)
+ {
+ for (const auto &rr : type)
{
- ResourceRecord &rr = types[i][j];
-
this->PackName(output, output_size, pos, rr.name);
if (pos + 8 >= output_size)
@@ -443,6 +441,7 @@ class Packet : public Query
break;
}
}
+ }
return pos;
}
@@ -450,52 +449,62 @@ class Packet : public Query
namespace DNS
{
- class ReplySocket : public virtual Socket
+ class ReplySocket
+ : public virtual Socket
{
- public:
- virtual ~ReplySocket() { }
+ public:
+ ~ReplySocket() override = default;
virtual void Reply(Packet *p) = 0;
};
}
/* Listens for TCP requests */
-class TCPSocket : public ListenSocket
+class TCPSocket final
+ : public ListenSocket
{
Manager *manager;
- public:
+public:
/* A TCP client */
- class Client : public ClientSocket, public Timer, public ReplySocket
+ class Client final
+ : public ClientSocket
+ , public Timer
+ , public ReplySocket
{
Manager *manager;
- Packet *packet;
+ Packet *packet = nullptr;
unsigned char packet_buffer[524];
- int length;
-
- public:
- Client(Manager *m, TCPSocket *l, int fd, const sockaddrs &addr) : Socket(fd, l->IsIPv6()), ClientSocket(l, addr), Timer(5),
- manager(m), packet(NULL), length(0)
+ int length = 0;
+
+ public:
+ Client(Manager *m, TCPSocket *l, int fd, const sockaddrs &addr)
+ : Socket(fd, l->GetFamily())
+ , ClientSocket(l, addr)
+ , Timer(5)
+ , manager(m)
{
Log(LOG_DEBUG_2) << "Resolver: New client from " << addr.addr();
}
- ~Client()
+ ~Client() override
{
Log(LOG_DEBUG_2) << "Resolver: Exiting client from " << clientaddr.addr();
delete packet;
}
/* Times out after a few seconds */
- void Tick(time_t) anope_override { }
+ void Tick() override
+ {
+ }
- void Reply(Packet *p) anope_override
+ void Reply(Packet *p) override
{
delete packet;
packet = p;
SocketEngine::Change(this, true, SF_WRITABLE);
}
- bool ProcessRead() anope_override
+ bool ProcessRead() override
{
Log(LOG_DEBUG_2) << "Resolver: Reading from DNS TCP socket";
@@ -515,7 +524,7 @@ class TCPSocket : public ListenSocket
return true;
}
- bool ProcessWrite() anope_override
+ bool ProcessWrite() override
{
Log(LOG_DEBUG_2) << "Resolver: Writing to DNS TCP socket";
@@ -543,30 +552,31 @@ class TCPSocket : public ListenSocket
}
};
- TCPSocket(Manager *m, const Anope::string &ip, int port) : Socket(-1, ip.find(':') != Anope::string::npos), ListenSocket(ip, port, ip.find(':') != Anope::string::npos), manager(m) { }
+ TCPSocket(Manager *m, const Anope::string &ip, int port) : Socket(-1, ip.find(':') == Anope::string::npos ? AF_INET : AF_INET6), ListenSocket(ip, port, ip.find(':') != Anope::string::npos), manager(m) { }
- ClientSocket *OnAccept(int fd, const sockaddrs &addr) anope_override
+ ClientSocket *OnAccept(int fd, const sockaddrs &addr) override
{
return new Client(this->manager, this, fd, addr);
}
};
/* Listens for UDP requests */
-class UDPSocket : public ReplySocket
+class UDPSocket final
+ : public ReplySocket
{
Manager *manager;
std::deque<Packet *> packets;
- public:
- UDPSocket(Manager *m, const Anope::string &ip, int port) : Socket(-1, ip.find(':') != Anope::string::npos, SOCK_DGRAM), manager(m) { }
+public:
+ UDPSocket(Manager *m, const Anope::string &ip, int port) : Socket(-1, ip.find(':') == Anope::string::npos ? AF_INET : AF_INET6, SOCK_DGRAM), manager(m) { }
- ~UDPSocket()
+ ~UDPSocket() override
{
- for (unsigned i = 0; i < packets.size(); ++i)
- delete packets[i];
+ for (const auto *packet : packets)
+ delete packet;
}
- void Reply(Packet *p) anope_override
+ void Reply(Packet *p) override
{
packets.push_back(p);
SocketEngine::Change(this, true, SF_WRITABLE);
@@ -574,7 +584,7 @@ class UDPSocket : public ReplySocket
std::deque<Packet *>& GetPackets() { return packets; }
- bool ProcessRead() anope_override
+ bool ProcessRead() override
{
Log(LOG_DEBUG_2) << "Resolver: Reading from DNS UDP socket";
@@ -585,7 +595,7 @@ class UDPSocket : public ReplySocket
return this->manager->HandlePacket(this, packet_buffer, length, &from_server);
}
- bool ProcessWrite() anope_override
+ bool ProcessWrite() override
{
Log(LOG_DEBUG_2) << "Resolver: Writing to DNS UDP socket";
@@ -612,17 +622,18 @@ class UDPSocket : public ReplySocket
}
};
-class NotifySocket : public Socket
+class NotifySocket final
+ : public Socket
{
Packet *packet;
- public:
- NotifySocket(bool v6, Packet *p) : Socket(-1, v6, SOCK_DGRAM), packet(p)
+public:
+ NotifySocket(int family, Packet *p) : Socket(-1, family, SOCK_DGRAM), packet(p)
{
SocketEngine::Change(this, false, SF_READABLE);
SocketEngine::Change(this, true, SF_WRITABLE);
}
- bool ProcessWrite() anope_override
+ bool ProcessWrite() override
{
if (!packet)
return false;
@@ -645,29 +656,34 @@ class NotifySocket : public Socket
}
};
-class MyManager : public Manager, public Timer
+class MyManager final
+ : public Manager
+ , public Timer
{
uint32_t serial;
- typedef TR1NS::unordered_map<Question, Query, Question::hash> cache_map;
+ typedef std::unordered_map<Question, Query, Question::hash> cache_map;
cache_map cache;
- TCPSocket *tcpsock;
- UDPSocket *udpsock;
+ TCPSocket *tcpsock = nullptr;
+ UDPSocket *udpsock = nullptr;
- bool listen;
+ bool listen = false;
sockaddrs addrs;
std::vector<std::pair<Anope::string, short> > notify;
- public:
+public:
std::map<unsigned short, Request *> requests;
- MyManager(Module *creator) : Manager(creator), Timer(300, Anope::CurTime, true), serial(Anope::CurTime), tcpsock(NULL), udpsock(NULL),
- listen(false), cur_id(rand())
+ MyManager(Module *creator)
+ : Manager(creator)
+ , Timer(300, true)
+ , serial(Anope::CurTime)
+ , cur_id(Anope::RandomNumber())
{
}
- ~MyManager()
+ ~MyManager() override
{
delete udpsock;
delete tcpsock;
@@ -717,7 +733,7 @@ class MyManager : public Manager, public Timer
notify = n;
}
- private:
+private:
unsigned short cur_id;
unsigned short GetID()
@@ -732,8 +748,8 @@ class MyManager : public Manager, public Timer
return cur_id;
}
- public:
- void Process(Request *req) anope_override
+public:
+ void Process(Request *req) override
{
Log(LOG_DEBUG_2) << "Resolver: Processing request to lookup " << req->name << ", of type " << req->type;
@@ -752,7 +768,7 @@ class MyManager : public Manager, public Timer
req->SetSecs(timeout);
- Packet *p = new Packet(this, &this->addrs);
+ auto *p = new Packet(this, &this->addrs);
p->flags = QUERYFLAGS_RD;
p->id = req->id;
p->questions.push_back(*req);
@@ -760,12 +776,12 @@ class MyManager : public Manager, public Timer
this->udpsock->Reply(p);
}
- void RemoveRequest(Request *req) anope_override
+ void RemoveRequest(Request *req) override
{
this->requests.erase(req->id);
}
- bool HandlePacket(ReplySocket *s, const unsigned char *const packet_buffer, int length, sockaddrs *from) anope_override
+ bool HandlePacket(ReplySocket *s, const unsigned char *const packet_buffer, int length, sockaddrs *from) override
{
if (length < Packet::HEADER_LENGTH)
return true;
@@ -792,7 +808,7 @@ class MyManager : public Manager, public Timer
return true;
}
- Packet *packet = new Packet(recv_packet);
+ auto *packet = new Packet(recv_packet);
packet->flags |= QUERYFLAGS_QR; /* This is a response */
packet->flags |= QUERYFLAGS_AA; /* And we are authoritative */
@@ -800,10 +816,8 @@ class MyManager : public Manager, public Timer
packet->authorities.clear();
packet->additional.clear();
- for (unsigned i = 0; i < recv_packet.questions.size(); ++i)
+ for (auto &q : recv_packet.questions)
{
- const Question& q = recv_packet.questions[i];
-
if (q.type == QUERY_AXFR || q.type == QUERY_SOA)
{
ResourceRecord rr(q.name, QUERY_SOA);
@@ -826,10 +840,8 @@ class MyManager : public Manager, public Timer
FOREACH_MOD(OnDnsRequest, (recv_packet, packet));
- for (unsigned i = 0; i < recv_packet.questions.size(); ++i)
+ for (auto &q : recv_packet.questions)
{
- const Question& q = recv_packet.questions[i];
-
if (q.type == QUERY_AXFR)
{
ResourceRecord rr(q.name, QUERY_SOA);
@@ -920,25 +932,22 @@ class MyManager : public Manager, public Timer
return true;
}
- void UpdateSerial() anope_override
+ void UpdateSerial() override
{
serial = Anope::CurTime;
}
- void Notify(const Anope::string &zone) anope_override
+ void Notify(const Anope::string &zone) override
{
/* notify slaves of the update */
- for (unsigned i = 0; i < notify.size(); ++i)
+ for (const auto &[ip, port] : notify)
{
- const Anope::string &ip = notify[i].first;
- short port = notify[i].second;
-
sockaddrs addr;
addr.pton(ip.find(':') != Anope::string::npos ? AF_INET6 : AF_INET, ip, port);
if (!addr.valid())
return;
- Packet *packet = new Packet(this, &addr);
+ auto *packet = new Packet(this, &addr);
packet->flags = QUERYFLAGS_AA | QUERYFLAGS_OPCODE_NOTIFY;
try
{
@@ -950,18 +959,18 @@ class MyManager : public Manager, public Timer
continue;
}
- packet->questions.push_back(Question(zone, QUERY_SOA));
+ packet->questions.emplace_back(zone, QUERY_SOA);
- new NotifySocket(ip.find(':') != Anope::string::npos, packet);
+ new NotifySocket(ip.find(':') == Anope::string::npos ? AF_INET : AF_INET6, packet);
}
}
- uint32_t GetSerial() const anope_override
+ uint32_t GetSerial() const override
{
return serial;
}
- void Tick(time_t now) anope_override
+ void Tick() override
{
Log(LOG_DEBUG_2) << "Resolver: Purging DNS cache";
@@ -972,12 +981,12 @@ class MyManager : public Manager, public Timer
it_next = it;
++it_next;
- if (req.created + static_cast<time_t>(req.ttl) < now)
+ if (req.created + static_cast<time_t>(req.ttl) < Anope::CurTime)
this->cache.erase(it);
}
}
- private:
+private:
/** Add a record to the dns cache
* @param r The record
*/
@@ -1007,7 +1016,8 @@ class MyManager : public Manager, public Timer
};
-class ModuleDNS : public Module
+class ModuleDNS final
+ : public Module
{
MyManager manager;
@@ -1017,13 +1027,13 @@ class ModuleDNS : public Module
std::vector<std::pair<Anope::string, short> > notify;
- public:
+public:
ModuleDNS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), manager(this)
{
}
- ~ModuleDNS()
+ ~ModuleDNS() override
{
for (std::map<int, Socket *>::const_iterator it = SocketEngine::Sockets.begin(), it_end = SocketEngine::Sockets.end(); it != it_end;)
{
@@ -1035,7 +1045,7 @@ class ModuleDNS : public Module
}
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
@@ -1053,7 +1063,7 @@ class ModuleDNS : public Module
Anope::string nip = n->Get<Anope::string>("ip");
short nport = n->Get<short>("port");
- notify.push_back(std::make_pair(nip, nport));
+ notify.emplace_back(nip, nport);
}
if (Anope::IsFile(nameserver))
@@ -1101,7 +1111,7 @@ class ModuleDNS : public Module
}
}
- void OnModuleUnload(User *u, Module *m) anope_override
+ void OnModuleUnload(User *u, Module *m) override
{
for (std::map<unsigned short, Request *>::iterator it = this->manager.requests.begin(), it_end = this->manager.requests.end(); it != it_end;)
{
diff --git a/modules/m_dnsbl.cpp b/modules/dnsbl.cpp
index 82cbc4f3a..deedd85e2 100644
--- a/modules/m_dnsbl.cpp
+++ b/modules/dnsbl.cpp
@@ -14,43 +14,42 @@ using namespace DNS;
static ServiceReference<XLineManager> akills("XLineManager", "xlinemanager/sgline");
static ServiceReference<Manager> dnsmanager("DNS::Manager", "dns/manager");
-struct Blacklist
+struct Blacklist final
{
- struct Reply
+ struct Reply final
{
- int code;
+ int code = 0;
Anope::string reason;
- bool allow_account;
+ bool allow_account = false;
- Reply() : code(0), allow_account(false) { }
+ Reply() = default;
};
Anope::string name;
- time_t bantime;
+ time_t bantime = 0;
Anope::string reason;
std::vector<Reply> replies;
- Blacklist() : bantime(0) { }
-
- Reply *Find(int code)
+ const Reply *Find(int code)
{
- for (unsigned int i = 0; i < replies.size(); ++i)
- if (replies[i].code == code)
- return &replies[i];
+ for (const auto &reply : replies)
+ if (reply.code == code)
+ return &reply;
return NULL;
}
};
-class DNSBLResolver : public Request
+class DNSBLResolver final
+ : public Request
{
Reference<User> user;
Blacklist blacklist;
bool add_to_akill;
- public:
+public:
DNSBLResolver(Module *c, User *u, const Blacklist &b, const Anope::string &host, bool add_akill) : Request(dnsmanager, c, host, QUERY_A, true), user(u), blacklist(b), add_to_akill(add_akill) { }
- void OnLookupComplete(const Query *record) anope_override
+ void OnLookupComplete(const Query *record) override
{
if (!user || user->Quitting())
return;
@@ -64,7 +63,7 @@ class DNSBLResolver : public Request
sresult.pton(AF_INET, ans_record.rdata);
int result = sresult.sa4.sin_addr.s_addr >> 24;
- Blacklist::Reply *reply = blacklist.Find(result);
+ const Blacklist::Reply *reply = blacklist.Find(result);
if (!blacklist.replies.empty() && !reply)
return;
@@ -82,7 +81,7 @@ class DNSBLResolver : public Request
BotInfo *OperServ = Config->GetClient("OperServ");
Log(creator, "dnsbl", OperServ) << user->GetMask() << " (" << addr << ") appears in " << this->blacklist.name;
- XLine *x = new XLine("*@" + addr, OperServ ? OperServ->nick : "m_dnsbl", Anope::CurTime + this->blacklist.bantime, reason, XLineManager::GenerateUID());
+ auto *x = new XLine("*@" + addr, OperServ ? OperServ->nick : "dnsbl", Anope::CurTime + this->blacklist.bantime, reason, XLineManager::GenerateUID());
if (this->add_to_akill && akills)
{
akills->AddXLine(x);
@@ -96,7 +95,8 @@ class DNSBLResolver : public Request
}
};
-class ModuleDNSBL : public Module
+class ModuleDNSBL final
+ : public Module
{
std::vector<Blacklist> blacklists;
std::set<cidr> exempts;
@@ -104,13 +104,13 @@ class ModuleDNSBL : public Module
bool check_on_netburst;
bool add_to_akill;
- public:
+public:
ModuleDNSBL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
this->check_on_connect = block->Get<bool>("check_on_connect");
@@ -152,7 +152,7 @@ class ModuleDNSBL : public Module
}
}
- void OnUserConnect(User *user, bool &exempt) anope_override
+ void OnUserConnect(User *user, bool &exempt) override
{
if (exempt || user->Quitting() || (!this->check_on_connect && !Me->IsSynced()) || !dnsmanager)
return;
@@ -175,10 +175,8 @@ class ModuleDNSBL : public Module
Anope::string reverse = user->ip.reverse();
- for (unsigned i = 0; i < this->blacklists.size(); ++i)
+ for (const auto &b : this->blacklists)
{
- const Blacklist &b = this->blacklists[i];
-
Anope::string dnsbl_host = reverse + "." + b.name;
DNSBLResolver *res = NULL;
try
diff --git a/modules/encryption/enc_bcrypt.cpp b/modules/encryption/enc_bcrypt.cpp
index fd8171454..648f95834 100644
--- a/modules/encryption/enc_bcrypt.cpp
+++ b/modules/encryption/enc_bcrypt.cpp
@@ -6,959 +6,181 @@
* This program is free but copyrighted software; see the file COPYING for
* details.
*
- * Most of the code in this file is taken from
- * https://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz
-*/
-
-/*
- * The crypt_blowfish homepage is:
- *
- * http://www.openwall.com/crypt/
- *
- * This code comes from John the Ripper password cracker, with reentrant
- * and crypt(3) interfaces added, but optimizations specific to password
- * cracking removed.
- *
- * Written by Solar Designer <solar at openwall.com> in 1998-2014.
- * No copyright is claimed, and the software is hereby placed in the public
- * domain. In case this attempt to disclaim copyright and place the software
- * in the public domain is deemed null and void, then the software is
- * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
- * general public under the following terms:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted.
- *
- * There's ABSOLUTELY NO WARRANTY, express or implied.
- *
- * It is my intent that you should be able to use this on your system,
- * as part of a software package, or anywhere else to improve security,
- * ensure compatibility, or for any other purpose. I would appreciate
- * it if you give credit where it is due and keep your modifications in
- * the public domain as well, but I don't require that in order to let
- * you place this code and any modifications you make under a license
- * of your choice.
- *
- * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
- * "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses
- * some of his ideas. The password hashing algorithm was designed by David
- * Mazieres <dm at lcs.mit.edu>. For information on the level of
- * compatibility for bcrypt hash prefixes other than "$2b$", please refer to
- * the comments in BF_set_key() below and to the included crypt(3) man page.
- *
- * There's a paper on the algorithm that explains its design decisions:
- *
- * http://www.usenix.org/events/usenix99/provos.html
- *
- * Some of the tricks in BF_ROUND might be inspired by Eric Young's
- * Blowfish library (I can't be sure if I would think of something if I
- * hadn't seen his code).
*/
-#include <string.h>
-
-#ifdef __i386__
-#define BF_SCALE 1
-#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
-#define BF_SCALE 1
-#else
-#define BF_SCALE 0
-#endif
-typedef unsigned int BF_word;
-typedef signed int BF_word_signed;
+#include <climits>
+#include <random>
-/* Number of Blowfish rounds, this is also hardcoded into a few places */
-#define BF_N 16
+#include "bcrypt/crypt_blowfish.c"
-typedef BF_word BF_key[BF_N + 2];
-
-typedef struct {
- BF_word S[4][0x100];
- BF_key P;
-} BF_ctx;
+#include "module.h"
+#include "modules/encryption.h"
-/*
- * Magic IV for 64 Blowfish encryptions that we do at the end.
- * The string is "OrpheanBeholderScryDoubt" on big-endian.
- */
-static BF_word BF_magic_w[6] = {
- 0x4F727068, 0x65616E42, 0x65686F6C,
- 0x64657253, 0x63727944, 0x6F756274
-};
+class BCryptContext final
+ : public Encryption::Context
+{
+private:
+ Anope::string buffer;
-/*
- * P-box and S-box tables initialized with digits of Pi.
- */
-static BF_ctx BF_init_state = {
+ Anope::string GenerateSalt()
{
+ static std::random_device device;
+ static std::mt19937 engine(device());
+ static std::uniform_int_distribution<int> dist(CHAR_MIN, CHAR_MAX);
+ char entropy[16];
+ for (size_t i = 0; i < sizeof(entropy); ++i)
+ entropy[i] = static_cast<char>(dist(engine));
+
+ char salt[32];
+ if (!_crypt_gensalt_blowfish_rn("$2a$", rounds, entropy, sizeof(entropy), salt, sizeof(salt)))
{
- 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
- 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
- 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
- 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
- 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
- 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
- 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
- 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
- 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
- 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
- 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
- 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
- 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
- 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
- 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
- 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
- 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
- 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
- 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
- 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
- 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
- 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
- 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
- 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
- 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
- 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
- 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
- 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
- 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
- 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
- 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
- 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
- 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
- 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
- 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
- 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
- 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
- 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
- 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
- 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
- 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
- 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
- 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
- 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
- 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
- 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
- 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
- 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
- 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
- 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
- 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
- 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
- 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
- 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
- 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
- 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
- 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
- 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
- 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
- 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
- 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
- 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
- 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
- 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
- }, {
- 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
- 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
- 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
- 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
- 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
- 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
- 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
- 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
- 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
- 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
- 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
- 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
- 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
- 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
- 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
- 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
- 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
- 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
- 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
- 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
- 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
- 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
- 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
- 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
- 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
- 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
- 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
- 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
- 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
- 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
- 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
- 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
- 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
- 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
- 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
- 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
- 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
- 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
- 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
- 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
- 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
- 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
- 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
- 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
- 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
- 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
- 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
- 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
- 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
- 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
- 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
- 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
- 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
- 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
- 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
- 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
- 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
- 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
- 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
- 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
- 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
- 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
- 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
- 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
- }, {
- 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
- 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
- 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
- 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
- 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
- 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
- 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
- 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
- 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
- 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
- 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
- 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
- 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
- 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
- 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
- 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
- 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
- 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
- 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
- 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
- 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
- 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
- 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
- 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
- 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
- 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
- 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
- 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
- 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
- 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
- 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
- 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
- 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
- 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
- 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
- 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
- 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
- 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
- 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
- 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
- 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
- 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
- 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
- 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
- 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
- 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
- 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
- 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
- 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
- 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
- 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
- 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
- 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
- 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
- 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
- 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
- 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
- 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
- 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
- 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
- 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
- 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
- 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
- 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
- }, {
- 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
- 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
- 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
- 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
- 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
- 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
- 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
- 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
- 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
- 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
- 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
- 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
- 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
- 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
- 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
- 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
- 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
- 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
- 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
- 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
- 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
- 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
- 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
- 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
- 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
- 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
- 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
- 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
- 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
- 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
- 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
- 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
- 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
- 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
- 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
- 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
- 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
- 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
- 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
- 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
- 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
- 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
- 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
- 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
- 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
- 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
- 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
- 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
- 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
- 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
- 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
- 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
- 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
- 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
- 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
- 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
- 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
- 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
- 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
- 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
- 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
- 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
- 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
- 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+ Log(LOG_DEBUG) << "Unable to generate a salt for Bcrypt: " << strerror(errno);
+ return {};
}
- }, {
- 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
- 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
- 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
- 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
- 0x9216d5d9, 0x8979fb1b
+ return salt;
}
-};
-
-static unsigned char BF_itoa64[64 + 1] =
- "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-
-static unsigned char BF_atoi64[0x60] = {
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
- 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
- 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
-};
-
-#define BF_safe_atoi64(dst, src) \
-{ \
- tmp = (unsigned char)(src); \
- if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
- tmp = BF_atoi64[tmp]; \
- if (tmp > 63) return -1; \
- (dst) = tmp; \
-}
-
-static int BF_decode(BF_word *dst, const char *src, int size)
-{
- unsigned char *dptr = (unsigned char *)dst;
- unsigned char *end = dptr + size;
- const unsigned char *sptr = (const unsigned char *)src;
- unsigned int tmp, c1, c2, c3, c4;
- do {
- BF_safe_atoi64(c1, *sptr++);
- BF_safe_atoi64(c2, *sptr++);
- *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
- if (dptr >= end) break;
+public:
+ static unsigned long rounds;
- BF_safe_atoi64(c3, *sptr++);
- *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
- if (dptr >= end) break;
-
- BF_safe_atoi64(c4, *sptr++);
- *dptr++ = ((c3 & 0x03) << 6) | c4;
- } while (dptr < end);
-
- return 0;
-}
-
-static void BF_encode(char *dst, const BF_word *src, int size)
-{
- const unsigned char *sptr = (const unsigned char *)src;
- const unsigned char *end = sptr + size;
- unsigned char *dptr = (unsigned char *)dst;
- unsigned int c1, c2;
-
- do {
- c1 = *sptr++;
- *dptr++ = BF_itoa64[c1 >> 2];
- c1 = (c1 & 0x03) << 4;
- if (sptr >= end) {
- *dptr++ = BF_itoa64[c1];
- break;
- }
-
- c2 = *sptr++;
- c1 |= c2 >> 4;
- *dptr++ = BF_itoa64[c1];
- c1 = (c2 & 0x0f) << 2;
- if (sptr >= end) {
- *dptr++ = BF_itoa64[c1];
- break;
- }
-
- c2 = *sptr++;
- c1 |= c2 >> 6;
- *dptr++ = BF_itoa64[c1];
- *dptr++ = BF_itoa64[c2 & 0x3f];
- } while (sptr < end);
-}
-
-static void BF_swap(BF_word *x, int count)
-{
- static int endianness_check = 1;
- char *is_little_endian = (char *)&endianness_check;
- BF_word tmp;
-
- if (*is_little_endian)
- do {
- tmp = *x;
- tmp = (tmp << 16) | (tmp >> 16);
- *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
- } while (--count);
-}
-
-#if BF_SCALE
-/* Architectures which can shift addresses left by 2 bits with no extra cost */
-#define BF_ROUND(L, R, N) \
- tmp1 = L & 0xFF; \
- tmp2 = L >> 8; \
- tmp2 &= 0xFF; \
- tmp3 = L >> 16; \
- tmp3 &= 0xFF; \
- tmp4 = L >> 24; \
- tmp1 = data.ctx.S[3][tmp1]; \
- tmp2 = data.ctx.S[2][tmp2]; \
- tmp3 = data.ctx.S[1][tmp3]; \
- tmp3 += data.ctx.S[0][tmp4]; \
- tmp3 ^= tmp2; \
- R ^= data.ctx.P[N + 1]; \
- tmp3 += tmp1; \
- R ^= tmp3;
-#else
-/* Architectures with no complicated addressing modes supported */
-#define BF_INDEX(S, i) \
- (*((BF_word *)(((unsigned char *)S) + (i))))
-#define BF_ROUND(L, R, N) \
- tmp1 = L & 0xFF; \
- tmp1 <<= 2; \
- tmp2 = L >> 6; \
- tmp2 &= 0x3FC; \
- tmp3 = L >> 14; \
- tmp3 &= 0x3FC; \
- tmp4 = L >> 22; \
- tmp4 &= 0x3FC; \
- tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
- tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
- tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
- tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
- tmp3 ^= tmp2; \
- R ^= data.ctx.P[N + 1]; \
- tmp3 += tmp1; \
- R ^= tmp3;
-#endif
-
-/*
- * Encrypt one block, BF_N is hardcoded here.
- */
-#define BF_ENCRYPT \
- L ^= data.ctx.P[0]; \
- BF_ROUND(L, R, 0); \
- BF_ROUND(R, L, 1); \
- BF_ROUND(L, R, 2); \
- BF_ROUND(R, L, 3); \
- BF_ROUND(L, R, 4); \
- BF_ROUND(R, L, 5); \
- BF_ROUND(L, R, 6); \
- BF_ROUND(R, L, 7); \
- BF_ROUND(L, R, 8); \
- BF_ROUND(R, L, 9); \
- BF_ROUND(L, R, 10); \
- BF_ROUND(R, L, 11); \
- BF_ROUND(L, R, 12); \
- BF_ROUND(R, L, 13); \
- BF_ROUND(L, R, 14); \
- BF_ROUND(R, L, 15); \
- tmp4 = R; \
- R = L; \
- L = tmp4 ^ data.ctx.P[BF_N + 1];
-
-#define BF_body() \
- L = R = 0; \
- ptr = data.ctx.P; \
- do { \
- ptr += 2; \
- BF_ENCRYPT; \
- *(ptr - 2) = L; \
- *(ptr - 1) = R; \
- } while (ptr < &data.ctx.P[BF_N + 2]); \
-\
- ptr = data.ctx.S[0]; \
- do { \
- ptr += 2; \
- BF_ENCRYPT; \
- *(ptr - 2) = L; \
- *(ptr - 1) = R; \
- } while (ptr < &data.ctx.S[3][0xFF]);
-
-static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
- unsigned char flags)
-{
- const char *ptr = key;
- unsigned int bug, i, j;
- BF_word safety, sign, diff, tmp[2];
-
-/*
- * There was a sign extension bug in older revisions of this function. While
- * we would have liked to simply fix the bug and move on, we have to provide
- * a backwards compatibility feature (essentially the bug) for some systems and
- * a safety measure for some others. The latter is needed because for certain
- * multiple inputs to the buggy algorithm there exist easily found inputs to
- * the correct algorithm that produce the same hash. Thus, we optionally
- * deviate from the correct algorithm just enough to avoid such collisions.
- * While the bug itself affected the majority of passwords containing
- * characters with the 8th bit set (although only a percentage of those in a
- * collision-producing way), the anti-collision safety measure affects
- * only a subset of passwords containing the '\xff' character (not even all of
- * those passwords, just some of them). This character is not found in valid
- * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
- * Thus, the safety measure is unlikely to cause much annoyance, and is a
- * reasonable tradeoff to use when authenticating against existing hashes that
- * are not reliably known to have been computed with the correct algorithm.
- *
- * We use an approach that tries to minimize side-channel leaks of password
- * information - that is, we mostly use fixed-cost bitwise operations instead
- * of branches or table lookups. (One conditional branch based on password
- * length remains. It is not part of the bug aftermath, though, and is
- * difficult and possibly unreasonable to avoid given the use of C strings by
- * the caller, which results in similar timing leaks anyway.)
- *
- * For actual implementation, we set an array index in the variable "bug"
- * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
- * variable "safety" (bit 16 is set when the safety measure is requested).
- * Valid combinations of settings are:
- *
- * Prefix "$2a$": bug = 0, safety = 0x10000
- * Prefix "$2b$": bug = 0, safety = 0
- * Prefix "$2x$": bug = 1, safety = 0
- * Prefix "$2y$": bug = 0, safety = 0
- */
- bug = (unsigned int)flags & 1;
- safety = ((BF_word)flags & 2) << 15;
-
- sign = diff = 0;
-
- for (i = 0; i < BF_N + 2; i++) {
- tmp[0] = tmp[1] = 0;
- for (j = 0; j < 4; j++) {
- tmp[0] <<= 8;
- tmp[0] |= (unsigned char)*ptr; /* correct */
- tmp[1] <<= 8;
- tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
-/*
- * Sign extension in the first char has no effect - nothing to overwrite yet,
- * and those extra 24 bits will be fully shifted out of the 32-bit word. For
- * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
- * extension in tmp[1] occurs. Once this flag is set, it remains set.
- */
- if (j)
- sign |= tmp[1] & 0x80;
- if (!*ptr)
- ptr = key;
- else
- ptr++;
+ static Anope::string Hash(const Anope::string &data, const Anope::string &salt)
+ {
+ char hash[64];
+ if (!_crypt_blowfish_rn(data.c_str(), salt.c_str(), hash, sizeof(hash)))
+ {
+ Log(LOG_DEBUG) << "Unable to generate a hash for Bcrypt: " << strerror(errno);
+ return {};
}
- diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
-
- expanded[i] = tmp[bug];
- initial[i] = BF_init_state.P[i] ^ tmp[bug];
- }
-
-/*
- * At this point, "diff" is zero iff the correct and buggy algorithms produced
- * exactly the same result. If so and if "sign" is non-zero, which indicates
- * that there was a non-benign sign extension, this means that we have a
- * collision between the correctly computed hash for this password and a set of
- * passwords that could be supplied to the buggy algorithm. Our safety measure
- * is meant to protect from such many-buggy to one-correct collisions, by
- * deviating from the correct algorithm in such cases. Let's check for this.
- */
- diff |= diff >> 16; /* still zero iff exact match */
- diff &= 0xffff; /* ditto */
- diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
- sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
- sign &= ~diff & safety; /* action needed? */
-
-/*
- * If we have determined that we need to deviate from the correct algorithm,
- * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
- * let's stick to it now. It came out of the approach we used above, and it's
- * not any worse than any other choice we could make.)
- *
- * It is crucial that we don't do the same to the expanded key used in the main
- * Eksblowfish loop. By doing it to only one of these two, we deviate from a
- * state that could be directly specified by a password to the buggy algorithm
- * (and to the fully correct one as well, but that's a side-effect).
- */
- initial[0] ^= sign;
-}
-
-static const unsigned char flags_by_subtype[26] =
- {2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
-
-static char *BF_crypt(const char *key, const char *setting,
- char *output, int size,
- BF_word min)
-{
- struct {
- BF_ctx ctx;
- BF_key expanded_key;
- union {
- BF_word salt[4];
- BF_word output[6];
- } binary;
- } data;
- BF_word L, R;
- BF_word tmp1, tmp2, tmp3, tmp4;
- BF_word *ptr;
- BF_word count;
- int i;
-
- if (size < 7 + 22 + 31 + 1) {
- return NULL;
- }
-
- if (setting[0] != '$' ||
- setting[1] != '2' ||
- setting[2] < 'a' || setting[2] > 'z' ||
- !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
- setting[3] != '$' ||
- setting[4] < '0' || setting[4] > '3' ||
- setting[5] < '0' || setting[5] > '9' ||
- (setting[4] == '3' && setting[5] > '1') ||
- setting[6] != '$') {
- return NULL;
- }
-
- count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
- if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
- return NULL;
+ return hash;
}
- BF_swap(data.binary.salt, 4);
- BF_set_key(key, data.expanded_key, data.ctx.P,
- flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
-
- memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
-
- L = R = 0;
- for (i = 0; i < BF_N + 2; i += 2) {
- L ^= data.binary.salt[i & 2];
- R ^= data.binary.salt[(i & 2) + 1];
- BF_ENCRYPT;
- data.ctx.P[i] = L;
- data.ctx.P[i + 1] = R;
+ void Update(const unsigned char *data, size_t len) override
+ {
+ buffer.append(reinterpret_cast<const char *>(data), len);
}
- ptr = data.ctx.S[0];
- do {
- ptr += 4;
- L ^= data.binary.salt[(BF_N + 2) & 3];
- R ^= data.binary.salt[(BF_N + 3) & 3];
- BF_ENCRYPT;
- *(ptr - 4) = L;
- *(ptr - 3) = R;
-
- L ^= data.binary.salt[(BF_N + 4) & 3];
- R ^= data.binary.salt[(BF_N + 5) & 3];
- BF_ENCRYPT;
- *(ptr - 2) = L;
- *(ptr - 1) = R;
- } while (ptr < &data.ctx.S[3][0xFF]);
-
- do {
- int done;
-
- for (i = 0; i < BF_N + 2; i += 2) {
- data.ctx.P[i] ^= data.expanded_key[i];
- data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
- }
-
- done = 0;
- do {
- BF_body();
- if (done)
- break;
- done = 1;
-
- tmp1 = data.binary.salt[0];
- tmp2 = data.binary.salt[1];
- tmp3 = data.binary.salt[2];
- tmp4 = data.binary.salt[3];
- for (i = 0; i < BF_N; i += 4) {
- data.ctx.P[i] ^= tmp1;
- data.ctx.P[i + 1] ^= tmp2;
- data.ctx.P[i + 2] ^= tmp3;
- data.ctx.P[i + 3] ^= tmp4;
- }
- data.ctx.P[16] ^= tmp1;
- data.ctx.P[17] ^= tmp2;
- } while (1);
- } while (--count);
-
- for (i = 0; i < 6; i += 2) {
- L = BF_magic_w[i];
- R = BF_magic_w[i + 1];
-
- count = 64;
- do {
- BF_ENCRYPT;
- } while (--count);
-
- data.binary.output[i] = L;
- data.binary.output[i + 1] = R;
+ Anope::string Finalize() override
+ {
+ auto salt = GenerateSalt();
+ if (salt.empty())
+ return {};
+ return Hash(this->buffer, salt);
}
+};
- memcpy(output, setting, 7 + 22 - 1);
- output[7 + 22 - 1] = BF_itoa64[(int)
- BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
-
-/* This has to be bug-compatible with the original implementation, so
- * only encode 23 of the 24 bytes. :-) */
- BF_swap(data.binary.output, 6);
- BF_encode(&output[7 + 22], data.binary.output, 23);
- output[7 + 22 + 31] = '\0';
-
- return output;
-}
-
-int _crypt_output_magic(const char *setting, char *output, int size)
-{
- if (size < 3)
- return -1;
-
- output[0] = '*';
- output[1] = '0';
- output[2] = '\0';
-
- if (setting[0] == '*' && setting[1] == '0')
- output[1] = '1';
-
- return 0;
-}
-
-/*
- * Please preserve the runtime self-test. It serves two purposes at once:
- *
- * 1. We really can't afford the risk of producing incompatible hashes e.g.
- * when there's something like gcc bug 26587 again, whereas an application or
- * library integrating this code might not also integrate our external tests or
- * it might not run them after every build. Even if it does, the miscompile
- * might only occur on the production build, but not on a testing build (such
- * as because of different optimization settings). It is painful to recover
- * from incorrectly-computed hashes - merely fixing whatever broke is not
- * enough. Thus, a proactive measure like this self-test is needed.
- *
- * 2. We don't want to leave sensitive data from our actual password hash
- * computation on the stack or in registers. Previous revisions of the code
- * would do explicit cleanups, but simply running the self-test after hash
- * computation is more reliable.
- *
- * The performance cost of this quick self-test is around 0.6% at the "$2a$08"
- * setting.
- */
-char *_crypt_blowfish_rn(const char *key, const char *setting,
- char *output, int size)
-{
- _crypt_output_magic(setting, output, size);
- return BF_crypt(key, setting, output, size, 16);
-}
+unsigned long BCryptContext::rounds = 10;
-char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
- const char *input, int size, char *output, int output_size)
+class BCryptProvider final
+ : public Encryption::Provider
{
- if (size < 16 || output_size < 7 + 22 + 1 ||
- (count && (count < 4 || count > 31)) ||
- prefix[0] != '$' || prefix[1] != '2' ||
- (prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) {
- if (output_size > 0) output[0] = '\0';
- return NULL;
+public:
+ BCryptProvider(Module *creator)
+ : Encryption::Provider(creator, "bcrypt", 0, 0)
+ {
}
- if (!count) count = 5;
-
- output[0] = '$';
- output[1] = '2';
- output[2] = prefix[2];
- output[3] = '$';
- output[4] = '0' + count / 10;
- output[5] = '0' + count % 10;
- output[6] = '$';
-
- BF_encode(&output[7], (const BF_word *)input, 16);
- output[7 + 22] = '\0';
-
- return output;
-}
-
-// Start Anope-specific code
-
-#include "module.h"
-#include "modules/encryption.h"
-
-class EBCRYPT : public Module
-{
- unsigned int rounds;
-
- Anope::string Salt()
+ bool Compare(const Anope::string &hash, const Anope::string &plain) override
{
- char entropy[16];
- for (unsigned int i = 0; i < sizeof(entropy); i++)
- entropy[i] = static_cast<char>(rand() % 0xFF);
+ auto newhash = BCryptContext::Hash(plain, hash);
+ return !newhash.empty() && hash.equals_cs(newhash);
+ }
- char salt[32];
- if (!_crypt_gensalt_blowfish_rn("$2a$", rounds, entropy, sizeof(entropy), salt, sizeof(salt)))
- return "";
- return salt;
+ std::unique_ptr<Encryption::Context> CreateContext() override
+ {
+ return std::make_unique<BCryptContext>();
}
- Anope::string Generate(const Anope::string& data, const Anope::string& salt)
+ Anope::string ToPrintable(const Anope::string &hash) override
{
- char hash[64];
- _crypt_blowfish_rn(data.c_str(), salt.c_str(), hash, sizeof(hash));
+ // The crypt_blowfish library does not expose a raw form.
return hash;
}
+};
- bool Compare(const Anope::string& string, const Anope::string& hash)
- {
- Anope::string ret = Generate(string, hash);
- if (ret.empty())
- return false;
- return (ret == hash);
- }
+class EBCrypt final
+ : public Module
+{
+private:
+ BCryptProvider bcryptprovider;
- public:
- EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
- rounds(10)
+public:
+ EBCrypt(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
+ , bcryptprovider(this)
{
- // Test a pre-calculated hash
- bool test = Compare("Test!", "$2a$10$x9AQFAQScY0v9KF2suqkEOepsHFrG.CXHbIXI.1F28SfSUb56A/7K");
-
- Anope::string salt;
- Anope::string hash;
- // Make sure it's working
- if (!test || (salt = Salt()).empty() || (hash = Generate("Test!", salt)).empty() || !Compare("Test!", hash))
- throw ModuleException("BCrypt could not load!");
+ bcryptprovider.Check({
+ { "$2a$10$c9lUAuJmTYXEfNuLOiyIp.lZTMM.Rw5qsSAyZhvGT9EC3JevkUuOu", "" },
+ { "$2a$10$YV4jDSGs0ZtQbpL6IHtNO.lt5Q.uzghIohCcnERQVBGyw7QJMfyhe", "The quick brown fox jumps over the lazy dog" },
+ });
}
- EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
+ EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
- dest = "bcrypt:" + Generate(src, Salt());
+ // Bcrypt can not generate passwords longer than 71 characters.
+ if (src.length() > 71)
+ return EVENT_CONTINUE;
+
+ dest = "bcrypt:" + bcryptprovider.Encrypt(src);
Log(LOG_DEBUG_2) << "(enc_bcrypt) hashed password from [" << src << "] to [" << dest << "]";
return EVENT_ALLOW;
}
- void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
- const NickAlias *na = NickAlias::Find(req->GetAccount());
- if (na == NULL)
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
return;
- NickCore *nc = na->nc;
- size_t pos = nc->pass.find(':');
+ NickCore *nc = na->nc;
+ auto pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
+
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
- if (hash_method != "bcrypt")
+ if (!hash_method.equals_cs("bcrypt"))
return;
- if (Compare(req->GetPassword(), nc->pass.substr(7)))
+ Anope::string hash_value(nc->pass.begin() + pos + 1, nc->pass.end());
+ if (bcryptprovider.Compare(hash_value, req->GetPassword()))
{
- /* if we are NOT the first module in the list,
- * we want to re-encrypt the pass with the new encryption
- */
-
- unsigned int hashrounds = 0;
- try
- {
- size_t roundspos = nc->pass.find('$', 11);
- if (roundspos == Anope::string::npos)
- throw ConvertException("Could not find hashrounds");
-
- hashrounds = convertTo<unsigned int>(nc->pass.substr(11, roundspos - 11));
- }
- catch (const ConvertException &)
- {
- Log(this) << "Could not get the round size of a hash. This is probably a bug. Hash: " << nc->pass;
- }
-
- if (ModuleManager::FindFirstOf(ENCRYPTION) != this || (hashrounds && hashrounds != rounds))
+ unsigned long rounds = 0;
+
+ // Try to extract the rounds count to check if we need to
+ // re-encrypt the password.
+ pos = hash_value.find('$', 4);
+ if (pos != Anope::string::npos)
+ rounds = Anope::Convert<unsigned long>(hash_value.substr(4, pos - 4), 0);
+
+ if (!rounds)
+ Log(LOG_DEBUG) << "Unable to determine the rounds of a bcrypt hash: " << hash_value;
+
+ // If we are NOT the first encryption module or the Bcrypt rounds
+ // are different we want to re-encrypt the password with the primary
+ // encryption method.
+ if (ModuleManager::FindFirstOf(ENCRYPTION) != this || (rounds && rounds != BCryptContext::rounds))
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
}
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
- Configuration::Block *block = conf->GetModule(this);
- rounds = block->Get<unsigned int>("rounds", "10");
+ auto *block = conf->GetModule(this);
- if (rounds == 0)
+ auto rounds = block->Get<unsigned long>("rounds", "10");
+ if (rounds < 10 || rounds > 32)
{
- rounds = 10;
- Log(this) << "Rounds can't be 0! Setting ignored.";
- }
- else if (rounds < 10)
- {
- Log(this) << "10 to 12 rounds is recommended.";
- }
- else if (rounds >= 32)
- {
- rounds = 10;
- Log(this) << "The maximum number of rounds supported is 31. Ignoring setting and using 10.";
- }
- else if (rounds >= 14)
- {
- Log(this) << "Are you sure you want to use " << stringify(rounds) << " in your bcrypt settings? This is very CPU intensive! Recommended rounds is 10-12.";
+ Log(this) << "Bcrypt rounds MUST be between 10 and 32 inclusive; using 10 instead of " << rounds << '.';
+ BCryptContext::rounds = 10;
+ return;
}
+
+ if (rounds > 14)
+ Log(this) << "Bcrypt rounds higher than 14 are very CPU intensive; are you sure you want to use " << rounds << '?';
+ BCryptContext::rounds = rounds;
}
};
-MODULE_INIT(EBCRYPT)
+MODULE_INIT(EBCrypt)
diff --git a/modules/encryption/enc_md5.cpp b/modules/encryption/enc_md5.cpp
index 0c56e8957..85bc88828 100644
--- a/modules/encryption/enc_md5.cpp
+++ b/modules/encryption/enc_md5.cpp
@@ -5,7 +5,7 @@
* Contact us at team@anope.org
*
* Taken from IRC Services and is copyright (c) 1996-2002 Andrew Church.
- * E-mail: <achurch@achurch.org>
+ * Email: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
@@ -14,377 +14,73 @@
#include "module.h"
#include "modules/encryption.h"
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
+#include "md5/md5.c"
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-static unsigned char PADDING[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-inline static unsigned F(unsigned x, unsigned y, unsigned z) { return (x & y) | (~x & z); }
-inline static unsigned G(unsigned x, unsigned y, unsigned z) { return (x & z) | (y & ~z); }
-inline static unsigned H(unsigned x, unsigned y, unsigned z) { return x ^ y ^ z; }
-inline static unsigned I(unsigned x, unsigned y, unsigned z) { return y ^ (x | ~z); }
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-inline static unsigned ROTATE_LEFT(unsigned x, unsigned n) { return (x << n) | (x >> (32 - n)); }
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
- * Rotation is separate from addition to prevent recomputation.
- */
-inline static void FF(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
-{
- a += F(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
-}
-inline static void GG(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
-{
- a += G(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
-}
-inline static void HH(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
-{
- a += H(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
-}
-inline static void II(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
-{
- a += I(b, c, d) + x + ac;
- a = ROTATE_LEFT(a, s);
- a += b;
-}
-
-static const uint32_t md5_iv[4] =
-{
- 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
-};
-
-class MD5Context : public Encryption::Context
+class MD5Context final
+ : public Encryption::Context
{
- unsigned state[4]; /* state (ABCD) */
- unsigned count[2]; /* number of bits, modulo 2^64 (lsb first) */
- unsigned char buffer[64]; /* input buffer */
- unsigned char digest[16]; /* final digest */
-
- /* Constants for MD5Transform routine.
- */
- enum
- {
- S11 = 7,
- S12 = 12,
- S13 = 17,
- S14 = 22,
- S21 = 5,
- S22 = 9,
- S23 = 14,
- S24 = 20,
- S31 = 4,
- S32 = 11,
- S33 = 16,
- S34 = 23,
- S41 = 6,
- S42 = 10,
- S43 = 15,
- S44 = 21
- };
-
- /* MD5 basic transformation. Transforms state based on block.
- */
- void Transform(const unsigned char block[64])
- {
- unsigned a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
- Decode(x, block, 64);
-
- /* Round 1 */
- FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
- FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
- FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
- FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
- FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
- FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
- FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
- FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
- FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
- FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
- FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
- GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
- GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
- GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
- GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
- GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
- GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
- GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
- GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
- GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
- GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
- HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
- HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
- HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
- HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
- HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
- HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
- HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
- HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
- HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
- II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
- II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
- II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
- II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
- II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
- II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
- II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
- II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
- II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-
- /* Zeroize sensitive information. */
- memset(x, 0, sizeof(x));
- }
-
- /* Encodes input (unsigned) into output (unsigned char). Assumes len is
- * a multiple of 4.
- */
- void Encode(unsigned char *output, unsigned *input, unsigned len)
- {
- for (unsigned i = 0, j = 0; j < len; ++i, j += 4)
- {
- output[j] = static_cast<unsigned char>(input[i] & 0xff);
- output[j + 1] = static_cast<unsigned char>((input[i] >> 8) & 0xff);
- output[j + 2] = static_cast<unsigned char>((input[i] >> 16) & 0xff);
- output[j + 3] = static_cast<unsigned char>((input[i] >> 24) & 0xff);
- }
- }
-
- /* Decodes input (unsigned char) into output (unsigned). Assumes len is
- * a multiple of 4.
- */
- void Decode(unsigned *output, const unsigned char *input, unsigned len)
- {
- for (unsigned i = 0, j = 0; j < len; ++i, j += 4)
- output[i] = static_cast<unsigned>(input[j]) | (static_cast<unsigned>(input[j + 1]) << 8) | (static_cast<unsigned>(input[j + 2]) << 16) | (static_cast<unsigned>(input[j + 3]) << 24);
- }
-
- public:
- MD5Context(Encryption::IV *iv = NULL)
- {
- if (iv != NULL)
- {
- if (iv->second != 4)
- throw CoreException("Invalid IV size");
- /* Load magic initialization constants. */
- for (int i = 0; i < 4; ++i)
- this->state[i] = iv->first[i];
- }
- else
- for (int i = 0; i < 4; ++i)
- this->state[i] = md5_iv[i];
+private:
+ MD5_CTX context;
- this->count[0] = this->count[1] = 0;
- memset(this->buffer, 0, sizeof(this->buffer));
- }
-
- /* MD5 block update operation. Continues an MD5 message-digest
- * operation, processing another message block, and updating the
- * context.
- */
- void Update(const unsigned char *input, size_t len) anope_override
+public:
+ MD5Context()
{
- unsigned i, index, partLen;
-
- /* Compute number of bytes mod 64 */
- index = (this->count[0] >> 3) & 0x3F;
-
- /* Update number of bits */
- if ((this->count[0] += len << 3) < (len << 3))
- ++this->count[1];
- this->count[1] += len >> 29;
-
- partLen = 64 - index;
-
- /* Transform as many times as possible. */
- if (len >= partLen)
- {
- memcpy(&this->buffer[index], input, partLen);
- this->Transform(this->buffer);
-
- for (i = partLen; i + 63 < len; i += 64)
- this->Transform(&input[i]);
-
- index = 0;
- }
- else
- i = 0;
-
- /* Buffer remaining input */
- memcpy(&this->buffer[index], &input[i], len - i);
+ MD5_Init(&context);
}
- /* MD5 finalization. Ends an MD5 message-digest opera
- * the message digest and zeroizing the context.
- */
- void Finalize() anope_override
+ void Update(const unsigned char *input, size_t len) override
{
- unsigned char bits[8];
- unsigned index, padLen;
-
- /* Save number of bits */
- this->Encode(bits, this->count, 8);
-
- /* Pad out to 56 mod 64. */
- index = (this->count[0] >> 3) & 0x3f;
- padLen = index < 56 ? 56 - index : 120 - index;
- this->Update(PADDING, padLen);
-
- /* Append length (before padding) */
- this->Update(bits, 8);
- /* Store state in digest */
- this->Encode(digest, this->state, 16);
-
- /* Zeroize sensitive information. */
- memset(this->state, 0, sizeof(this->state));
- memset(this->count, 0, sizeof(this->count));
- memset(this->buffer, 0, sizeof(this->buffer));
+ MD5_Update(&context, input, len);
}
- Encryption::Hash GetFinalizedHash() anope_override
+ Anope::string Finalize() override
{
- Encryption::Hash hash;
- hash.first = this->digest;
- hash.second = sizeof(this->digest);
- return hash;
+ unsigned char digest[16];
+ MD5_Final(digest, &context);
+ return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest));
}
};
-class MD5Provider : public Encryption::Provider
+class EMD5 final
+ : public Module
{
- public:
- MD5Provider(Module *creator) : Encryption::Provider(creator, "md5") { }
+private:
+ Encryption::SimpleProvider<MD5Context> md5provider;
- Encryption::Context *CreateContext(Encryption::IV *iv) anope_override
- {
- return new MD5Context(iv);
- }
-
- Encryption::IV GetDefaultIV() anope_override
- {
- Encryption::IV iv;
- iv.first = md5_iv;
- iv.second = sizeof(md5_iv) / sizeof(uint32_t);
- return iv;
- }
-};
-
-class EMD5 : public Module
-{
- MD5Provider md5provider;
-
- public:
- EMD5(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
- md5provider(this)
+public:
+ EMD5(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
+ , md5provider(this, "md5", 16, 64)
{
+ if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
+ throw ModuleException("enc_md5 is deprecated and can not be used as a primary encryption method");
+ md5provider.Check({
+ { "d41d8cd98f00b204e9800998ecf8427e", "" },
+ { "9e107d9d372bb6826bd81d3542a419d6", "The quick brown fox jumps over the lazy dog" },
+ });
}
- EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
- MD5Context context;
-
- context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
- context.Finalize();
-
- Encryption::Hash hash = context.GetFinalizedHash();
-
- Anope::string buf = "md5:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second);
-
- Log(LOG_DEBUG_2) << "(enc_md5) hashed password from [" << src << "] to [" << buf << "]";
- dest = buf;
- return EVENT_ALLOW;
- }
-
- void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
- {
- const NickAlias *na = NickAlias::Find(req->GetAccount());
- if (na == NULL)
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
return;
- NickCore *nc = na->nc;
- size_t pos = nc->pass.find(':');
+ NickCore *nc = na->nc;
+ auto 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("md5"))
return;
- Anope::string buf;
- this->OnEncrypt(req->GetPassword(), buf);
- if (nc->pass.equals_cs(buf))
+ auto enc = "md5:" + Anope::Hex(md5provider.Encrypt(req->GetPassword()));
+ if (nc->pass.equals_cs(enc))
{
- /* if we are NOT the first module in the list,
- * we want to re-encrypt the pass with the new encryption
- */
+ // 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);
diff --git a/modules/encryption/enc_none.cpp b/modules/encryption/enc_none.cpp
index f798718a2..0fcb6b15b 100644
--- a/modules/encryption/enc_none.cpp
+++ b/modules/encryption/enc_none.cpp
@@ -9,56 +9,39 @@
#include "module.h"
-class ENone : public Module
+class ENone final
+ : public Module
{
- public:
- ENone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR)
+public:
+ ENone(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
{
-
- }
-
- EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
- {
- Anope::string buf = "plain:";
- Anope::string cpass;
- Anope::B64Encode(src, cpass);
- buf += cpass;
- Log(LOG_DEBUG_2) << "(enc_none) hashed password from [" << src << "] to [" << buf << "]";
- dest = buf;
- return EVENT_ALLOW;
- }
-
- EventReturn OnDecrypt(const Anope::string &hashm, const Anope::string &src, Anope::string &dest) anope_override
- {
- if (!hashm.equals_cs("plain"))
- return EVENT_CONTINUE;
- size_t pos = src.find(':');
- Anope::string buf = src.substr(pos + 1);
- Anope::B64Decode(buf, dest);
- return EVENT_ALLOW;
+ if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
+ throw ModuleException("enc_none is deprecated and can not be used as a primary encryption method");
}
- void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
- const NickAlias *na = NickAlias::Find(req->GetAccount());
- if (na == NULL)
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
return;
- NickCore *nc = na->nc;
- size_t pos = nc->pass.find(':');
+ NickCore *nc = na->nc;
+ auto 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("plain"))
return;
- Anope::string buf;
- this->OnEncrypt(req->GetPassword(), buf);
- if (nc->pass.equals_cs(buf))
+ Anope::string b64pass;
+ Anope::B64Encode(req->GetPassword(), b64pass);
+ auto enc = "plain:" + b64pass;
+ if (nc->pass.equals_cs(enc))
{
- /* if we are NOT the first module in the list,
- * we want to re-encrypt the pass with the new encryption
- */
+ // 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);
diff --git a/modules/encryption/enc_old.cpp b/modules/encryption/enc_old.cpp
index a6f887a09..068318b82 100644
--- a/modules/encryption/enc_old.cpp
+++ b/modules/encryption/enc_old.cpp
@@ -12,94 +12,70 @@
#include "module.h"
#include "modules/encryption.h"
-static ServiceReference<Encryption::Provider> md5("Encryption::Provider", "md5");
-
-class OldMD5Provider : public Encryption::Provider
+class EOld final
+ : public Module
{
- public:
- OldMD5Provider(Module *creator) : Encryption::Provider(creator, "oldmd5") { }
+private:
+ ServiceReference<Encryption::Provider> md5;
- Encryption::Context *CreateContext(Encryption::IV *iv) anope_override
+ Anope::string EncryptInternal(const Anope::string &src)
{
- if (md5)
- return md5->CreateContext(iv);
- return NULL;
+ 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));
}
- Encryption::IV GetDefaultIV() anope_override
+ inline static char XTOI(char c)
{
- if (md5)
- return md5->GetDefaultIV();
- return Encryption::IV(static_cast<const uint32_t *>(NULL), 0);
+ return c > 9 ? c - 'A' + 10 : c - '0';
}
-};
-
-class EOld : public Module
-{
- OldMD5Provider oldmd5provider;
- 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),
- oldmd5provider(this)
+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");
-
- }
-
- EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
- {
- if (!md5)
- return EVENT_CONTINUE;
-
- Encryption::Context *context = md5->CreateContext();
- context->Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
- context->Finalize();
-
- Encryption::Hash hash = context->GetFinalizedHash();
-
- char digest[32], digest2[16];
- memset(digest, 0, sizeof(digest));
- if (hash.second > sizeof(digest))
- throw CoreException("Hash too large");
- memcpy(digest, hash.first, hash.second);
-
- for (int i = 0; i < 32; i += 2)
- digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
-
- Anope::string buf = "oldmd5:" + Anope::Hex(digest2, sizeof(digest2));
-
- Log(LOG_DEBUG_2) << "(enc_old) hashed password from [" << src << "] to [" << buf << "]";
- dest = buf;
- delete context;
- return EVENT_ALLOW;
}
- void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
- const NickAlias *na = NickAlias::Find(req->GetAccount());
- if (na == NULL)
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
return;
- NickCore *nc = na->nc;
+ 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;
- Anope::string buf;
- this->OnEncrypt(req->GetPassword(), buf);
- if (nc->pass.equals_cs(buf))
+ auto enc = EncryptInternal(req->GetPassword());
+ if (!enc.empty() && nc->pass.equals_cs(enc))
{
- /* if we are NOT the first module in the list,
- * we want to re-encrypt the pass with the new encryption
- */
+ // 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);
diff --git a/modules/encryption/enc_sha1.cpp b/modules/encryption/enc_sha1.cpp
index 6a0352246..7d25df6ff 100644
--- a/modules/encryption/enc_sha1.cpp
+++ b/modules/encryption/enc_sha1.cpp
@@ -54,12 +54,12 @@ static const uint32_t sha1_iv[5] =
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
};
-class SHA1Context : public Encryption::Context
+class SHA1Context final
+ : public Encryption::Context
{
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
- unsigned char digest[20];
void Transform(const unsigned char buf[64])
{
@@ -106,26 +106,17 @@ class SHA1Context : public Encryption::Context
a = b = c = d = e = 0;
}
- public:
- SHA1Context(Encryption::IV *iv = NULL)
+public:
+ SHA1Context()
{
- if (iv != NULL)
- {
- if (iv->second != 5)
- throw CoreException("Invalid IV size");
- for (int i = 0; i < 5; ++i)
- this->state[i] = iv->first[i];
- }
- else
- for (int i = 0; i < 5; ++i)
- this->state[i] = sha1_iv[i];
+ for (int i = 0; i < 5; ++i)
+ this->state[i] = sha1_iv[i];
this->count[0] = this->count[1] = 0;
memset(this->buffer, 0, sizeof(this->buffer));
- memset(this->digest, 0, sizeof(this->digest));
}
- void Update(const unsigned char *data, size_t len) anope_override
+ void Update(const unsigned char *data, size_t len) override
{
uint32_t i, j;
@@ -146,7 +137,7 @@ class SHA1Context : public Encryption::Context
memcpy(&this->buffer[j], &data[i], len - i);
}
- void Finalize() anope_override
+ Anope::string Finalize() override
{
uint32_t i;
unsigned char finalcount[8];
@@ -157,8 +148,10 @@ class SHA1Context : public Encryption::Context
while ((this->count[0] & 504) != 448)
this->Update(reinterpret_cast<const unsigned char *>("\0"), 1);
this->Update(finalcount, 8); /* Should cause a SHA1Transform() */
+ unsigned char digest[20];
+ memset(digest, 0, sizeof(digest));
for (i = 0; i < 20; ++i)
- this->digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
+ digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
/* Wipe variables */
memset(this->buffer, 0, sizeof(this->buffer));
@@ -167,81 +160,51 @@ class SHA1Context : public Encryption::Context
memset(&finalcount, 0, sizeof(finalcount));
this->Transform(this->buffer);
- }
-
- Encryption::Hash GetFinalizedHash() anope_override
- {
- Encryption::Hash hash;
- hash.first = this->digest;
- hash.second = sizeof(this->digest);
- return hash;
- }
-};
-
-class SHA1Provider : public Encryption::Provider
-{
- public:
- SHA1Provider(Module *creator) : Encryption::Provider(creator, "sha1") { }
-
- Encryption::Context *CreateContext(Encryption::IV *iv) anope_override
- {
- return new SHA1Context(iv);
- }
- Encryption::IV GetDefaultIV() anope_override
- {
- Encryption::IV iv;
- iv.first = sha1_iv;
- iv.second = sizeof(sha1_iv) / sizeof(uint32_t);
- return iv;
+ return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest));
}
};
-class ESHA1 : public Module
+class ESHA1 final
+ : public Module
{
- SHA1Provider sha1provider;
-
- public:
- ESHA1(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
- sha1provider(this)
- {
-
- }
+private:
+ Encryption::SimpleProvider<SHA1Context> sha1provider;
- EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
+public:
+ ESHA1(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
+ , sha1provider(this, "sha1", 20, 64)
{
- SHA1Context context;
+ if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
+ throw ModuleException("enc_sha1 is deprecated and can not be used as a primary encryption method");
- context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
- context.Finalize();
-
- Encryption::Hash hash = context.GetFinalizedHash();
-
- Anope::string buf = "sha1:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second);
-
- Log(LOG_DEBUG_2) << "(enc_sha1) hashed password from [" << src << "] to [" << buf << "]";
- dest = buf;
- return EVENT_ALLOW;
+ sha1provider.Check({
+ { "da39a3ee5e6b4b0d3255bfef95601890afd80709", "" },
+ { "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", "The quick brown fox jumps over the lazy dog" },
+ });
}
- void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
- const NickAlias *na = NickAlias::Find(req->GetAccount());
- if (na == NULL)
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
return;
- NickCore *nc = na->nc;
- size_t pos = nc->pass.find(':');
+ NickCore *nc = na->nc;
+ auto 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("sha1"))
return;
- Anope::string buf;
- this->OnEncrypt(req->GetPassword(), buf);
- if (nc->pass.equals_cs(buf))
+ auto enc = "sha1:" + Anope::Hex(sha1provider.Encrypt(req->GetPassword()));
+ if (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);
diff --git a/modules/encryption/enc_sha2.cpp b/modules/encryption/enc_sha2.cpp
new file mode 100644
index 000000000..11c0e76f6
--- /dev/null
+++ b/modules/encryption/enc_sha2.cpp
@@ -0,0 +1,215 @@
+/* Module for providing SHA-2 hashing
+ *
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * This program is free but copyrighted software; see the file COPYING for
+ * details.
+ *
+ */
+
+#include <climits>
+#include <random>
+
+#include "sha2/sha2.c"
+
+#include "module.h"
+#include "modules/encryption.h"
+
+template <typename SHAContext,
+ void (* SHAInit)(SHAContext *),
+ void (* SHAUpdate)(SHAContext *, const unsigned char *, unsigned int),
+ void (* SHAFinal)(SHAContext *, unsigned char *)>
+class SHA2Context final
+ : public Encryption::Context
+{
+private:
+ SHAContext context;
+ const size_t digest_size;
+
+public:
+ SHA2Context(size_t ds)
+ : digest_size(ds)
+ {
+ SHAInit(&context);
+ }
+
+ void Update(const unsigned char *data, size_t len) override
+ {
+ SHAUpdate(&context, data, len);
+ }
+
+ Anope::string Finalize() override
+ {
+ std::vector<unsigned char> digest(digest_size);
+ SHAFinal(&context, digest.data());
+ return Anope::string(reinterpret_cast<const char *>(digest.data()), digest.size());
+ }
+};
+
+template <typename SHAContext,
+ void (* SHAInit)(SHAContext *),
+ void (* SHAUpdate)(SHAContext *, const unsigned char *, unsigned int),
+ void (* SHAFinal)(SHAContext *, unsigned char *)>
+class SHA2Provider final
+ : public Encryption::Provider
+{
+public:
+ SHA2Provider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
+ : Encryption::Provider(creator, algorithm, bs, ds)
+ {
+ }
+
+ std::unique_ptr<Encryption::Context> CreateContext() override
+ {
+ return std::make_unique<SHA2Context<SHAContext, SHAInit, SHAUpdate, SHAFinal>>(this->digest_size);
+ }
+};
+
+class ESHA2 final
+ : public Module
+{
+private:
+ Encryption::Provider *defaultprovider = nullptr;
+ SHA2Provider<sha224_ctx, sha224_init, sha224_update, sha224_final> sha224provider;
+ SHA2Provider<sha256_ctx, sha256_init, sha256_update, sha256_final> sha256provider;
+ SHA2Provider<sha384_ctx, sha384_init, sha384_update, sha384_final> sha384provider;
+ SHA2Provider<sha512_ctx, sha512_init, sha512_update, sha512_final> sha512provider;
+
+ Anope::string GenerateKey(size_t keylen)
+ {
+ static std::random_device device;
+ static std::mt19937 engine(device());
+ static std::uniform_int_distribution<int> dist(CHAR_MIN, CHAR_MAX);
+ Anope::string keybuf(keylen, ' ');
+ for (size_t i = 0; i < keylen; ++i)
+ keybuf[i] = static_cast<char>(dist(engine));
+ return keybuf;
+ }
+
+ Encryption::Provider *GetAlgorithm(const Anope::string &algorithm)
+ {
+ if (algorithm == "sha224")
+ return &sha224provider;
+ if (algorithm == "sha256")
+ return &sha256provider;
+ if (algorithm == "sha384")
+ return &sha384provider;
+ if (algorithm == "sha512")
+ return &sha512provider;
+ return nullptr;
+ }
+
+public:
+ ESHA2(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
+ , sha224provider(this, "sha224", SHA224_BLOCK_SIZE, SHA224_DIGEST_SIZE)
+ , sha256provider(this, "sha256", SHA256_BLOCK_SIZE, SHA256_DIGEST_SIZE)
+ , sha384provider(this, "sha384", SHA384_BLOCK_SIZE, SHA384_DIGEST_SIZE)
+ , sha512provider(this, "sha512", SHA512_BLOCK_SIZE, SHA512_DIGEST_SIZE)
+ {
+ sha224provider.Check({
+ { "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "" },
+ { "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525", "The quick brown fox jumps over the lazy dog" },
+ });
+ sha256provider.Check({
+ { "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "" },
+ { "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", "The quick brown fox jumps over the lazy dog" },
+ });
+ sha384provider.Check({
+ { "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", "" },
+ { "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1", "The quick brown fox jumps over the lazy dog" },
+ });
+ sha512provider.Check({
+ { "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "" },
+ { "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", "The quick brown fox jumps over the lazy dog" },
+ });
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ this->defaultprovider = GetAlgorithm(Config->GetModule(this)->Get<const Anope::string>("algorithm", "sha256"));
+ }
+
+ EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
+ {
+ if (!defaultprovider)
+ return EVENT_CONTINUE;
+
+ auto key = GenerateKey(defaultprovider->digest_size);
+ auto hmac = defaultprovider->HMAC(key, src);
+ auto enc = "hmac-" + defaultprovider->name + ":" + Anope::Hex(hmac) + ":" + Anope::Hex(key);
+ Log(LOG_DEBUG_2) << "(enc_sha2) hashed password from [" << src << "] to [" << enc << "]";
+ dest = enc;
+ return EVENT_ALLOW;
+ }
+
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
+ {
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
+ return;
+
+ NickCore *nc = na->nc;
+ auto apos = nc->pass.find(':');
+ if (apos == Anope::string::npos)
+ return;
+
+ Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + apos);
+ bool is_hmac = !hash_method.compare(0, 5, "hmac-", 5);
+ if (!is_hmac && hash_method.compare(0, 4, "raw-", 4))
+ return; // Not a SHA-2 password.
+
+ auto *provider = GetAlgorithm(hash_method.substr(is_hmac ? 5 : 4));
+ if (!provider)
+ return; // Not a hash for this module.
+
+ auto valid = false;
+ if (is_hmac)
+ {
+ auto bpos = nc->pass.find(':', apos + 1);
+ if (bpos == Anope::string::npos)
+ return; // No HMAC key.
+
+ // If you are using PHP you can validate passwords like this:
+ //
+ // <?php
+ // function check_pass($user_pass, $anope_pass) {
+ // [$algo, $hash, $key] = explode(':', $anope_pass);
+ // $hash_algo = substr($algo, 5);
+ // $unhex_key = hex2bin($key);
+ // $user_hash = hash_hmac($hash_algo, $user_pass, $unhex_key);
+ // return hash_equals($hash, $user_hash);
+ // }
+ //
+ // $anope_pass = "hmac-sha256:5f7f039818f6e10be84dab0f49610a387d3818b2c883eacdc1778c66a7cecf3b:1a924a3b05a11d7bf3c752d820391dbe01fb7e5d83f7400765de987c3fbb0ec3";
+ // var_dump(check_pass("test12345", $anope_pass)); // valid
+ // var_dump(check_pass("test123456789", $anope_pass)); // invalid
+
+ Anope::string pass_hex(nc->pass.begin() + apos + 1, nc->pass.begin() + bpos);
+ Anope::string key_hex(nc->pass.begin() + bpos + 1, nc->pass.end());
+ Anope::string key;
+ Anope::Unhex(key_hex, key);
+
+ auto enc = Anope::Hex(provider->HMAC(key, req->GetPassword()));
+ valid = pass_hex.equals_cs(enc);
+ }
+ else
+ {
+ Anope::string pass_hex(nc->pass.begin() + apos + 1, nc->pass.end());
+ valid = provider->Compare(pass_hex, req->GetPassword());
+ }
+
+ if (valid)
+ {
+ // If we are NOT the first encryption module, the password is a raw
+ // hash, or the algorithm is different we want to re-encrypt the
+ // password with the primary encryption method.
+ if (ModuleManager::FindFirstOf(ENCRYPTION) != this || !is_hmac || provider != defaultprovider)
+ Anope::Encrypt(req->GetPassword(), nc->pass);
+ req->Success(this);
+ }
+ }
+};
+
+MODULE_INIT(ESHA2)
diff --git a/modules/encryption/enc_sha256.cpp b/modules/encryption/enc_sha256.cpp
index 04ff70653..7a75723cf 100644
--- a/modules/encryption/enc_sha256.cpp
+++ b/modules/encryption/enc_sha256.cpp
@@ -1,252 +1,29 @@
/* This module generates and compares password hashes using SHA256 algorithms.
*
- * If an intruder gets access to your system or uses a brute force attack,
- * salt will not provide much value.
- * IMPORTANT: DATA HASHES CANNOT BE "DECRYPTED" BACK TO PLAIN TEXT.
- *
- * Modified for Anope.
* (C) 2003-2025 Anope Team
* Contact us at team@anope.org
*
- * Taken from InspIRCd (https://www.inspircd.org/),
- * see https://wiki.inspircd.org/Credits
+ * This program is free but copyrighted software; see the file COPYING for
+ * details.
*
- * This program is free but copyrighted software; see
- * the file COPYING for details.
*/
-/* FIPS 180-2 SHA-224/256/384/512 implementation
- * Last update: 05/23/2005
- * Issue date: 04/30/2005
- *
- * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+#include "sha2/sha2.c"
#include "module.h"
-#include "modules/encryption.h"
-
-static const unsigned SHA256_DIGEST_SIZE = 256 / 8;
-static const unsigned SHA256_BLOCK_SIZE = 512 / 8;
-
-inline static uint32_t SHFR(uint32_t x, uint32_t n) { return x >> n; }
-inline static uint32_t ROTR(uint32_t x, uint32_t n) { return (x >> n) | (x << ((sizeof(x) << 3) - n)); }
-inline static uint32_t CH(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (~x & z); }
-inline static uint32_t MAJ(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (x & z) ^ (y & z); }
-
-inline static uint32_t SHA256_F1(uint32_t x) { return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); }
-inline static uint32_t SHA256_F2(uint32_t x) { return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); }
-inline static uint32_t SHA256_F3(uint32_t x) { return ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3); }
-inline static uint32_t SHA256_F4(uint32_t x) { return ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10); }
-
-inline static void UNPACK32(unsigned x, unsigned char *str)
-{
- str[3] = static_cast<uint8_t>(x);
- str[2] = static_cast<uint8_t>(x >> 8);
- str[1] = static_cast<uint8_t>(x >> 16);
- str[0] = static_cast<uint8_t>(x >> 24);
-}
-
-inline static void PACK32(unsigned char *str, uint32_t &x)
-{
- x = static_cast<uint32_t>(str[3]) | static_cast<uint32_t>(str[2]) << 8 | static_cast<uint32_t>(str[1]) << 16 | static_cast<uint32_t>(str[0]) << 24;
-}
-
-/* Macros used for loops unrolling */
-
-inline static void SHA256_SCR(uint32_t w[64], int i)
-{
- w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16];
-}
-
-static const uint32_t sha256_h0[8] =
-{
- 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
- 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
-};
-
-static const uint32_t sha256_k[64] =
-{
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-/** An sha256 context
- */
-class SHA256Context : public Encryption::Context
+class ESHA256 final
+ : public Module
{
- void Transform(unsigned char *message, unsigned block_nb)
- {
- uint32_t w[64], wv[8];
- unsigned char *sub_block;
- for (unsigned i = 1; i <= block_nb; ++i)
- {
- int j;
- sub_block = message + ((i - 1) << 6);
-
- for (j = 0; j < 16; ++j)
- PACK32(&sub_block[j << 2], w[j]);
- for (j = 16; j < 64; ++j)
- SHA256_SCR(w, j);
- for (j = 0; j < 8; ++j)
- wv[j] = this->h[j];
- for (j = 0; j < 64; ++j)
- {
- uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
- uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
- wv[7] = wv[6];
- wv[6] = wv[5];
- wv[5] = wv[4];
- wv[4] = wv[3] + t1;
- wv[3] = wv[2];
- wv[2] = wv[1];
- wv[1] = wv[0];
- wv[0] = t1 + t2;
- }
- for (j = 0; j < 8; ++j)
- this->h[j] += wv[j];
- }
- }
-
- unsigned tot_len;
- unsigned len;
- unsigned char block[2 * SHA256_BLOCK_SIZE];
- uint32_t h[8];
- unsigned char digest[SHA256_DIGEST_SIZE];
-
- public:
- SHA256Context(Encryption::IV *iv)
- {
- if (iv != NULL)
- {
- if (iv->second != 8)
- throw CoreException("Invalid IV size");
- for (int i = 0; i < 8; ++i)
- this->h[i] = iv->first[i];
- }
- else
- for (int i = 0; i < 8; ++i)
- this->h[i] = sha256_h0[i];
-
- this->tot_len = 0;
- this->len = 0;
- memset(this->block, 0, sizeof(this->block));
- memset(this->digest, 0, sizeof(this->digest));
- }
-
- void Update(const unsigned char *message, size_t mlen) anope_override
- {
- unsigned tmp_len = SHA256_BLOCK_SIZE - this->len, rem_len = mlen < tmp_len ? mlen : tmp_len;
-
- memcpy(&this->block[this->len], message, rem_len);
- if (this->len + mlen < SHA256_BLOCK_SIZE)
- {
- this->len += mlen;
- return;
- }
- unsigned new_len = mlen - rem_len, block_nb = new_len / SHA256_BLOCK_SIZE;
- unsigned char *shifted_message = new unsigned char[mlen - rem_len];
- memcpy(shifted_message, message + rem_len, mlen - rem_len);
- this->Transform(this->block, 1);
- this->Transform(shifted_message, block_nb);
- rem_len = new_len % SHA256_BLOCK_SIZE;
- memcpy(this->block, &shifted_message[block_nb << 6], rem_len);
- delete [] shifted_message;
- this->len = rem_len;
- this->tot_len += (block_nb + 1) << 6;
- }
-
- void Finalize() anope_override
- {
- unsigned block_nb = 1 + ((SHA256_BLOCK_SIZE - 9) < (this->len % SHA256_BLOCK_SIZE));
- unsigned len_b = (this->tot_len + this->len) << 3;
- unsigned pm_len = block_nb << 6;
- memset(this->block + this->len, 0, pm_len - this->len);
- this->block[this->len] = 0x80;
- UNPACK32(len_b, this->block + pm_len - 4);
- this->Transform(this->block, block_nb);
- for (int i = 0 ; i < 8; ++i)
- UNPACK32(this->h[i], &this->digest[i << 2]);
- }
-
- Encryption::Hash GetFinalizedHash() anope_override
- {
- Encryption::Hash hash;
- hash.first = this->digest;
- hash.second = SHA256_DIGEST_SIZE;
- return hash;
- }
-};
-
-class SHA256Provider : public Encryption::Provider
-{
- public:
- SHA256Provider(Module *creator) : Encryption::Provider(creator, "sha256") { }
-
- Encryption::Context *CreateContext(Encryption::IV *iv) anope_override
- {
- return new SHA256Context(iv);
- }
-
- Encryption::IV GetDefaultIV() anope_override
- {
- Encryption::IV iv;
- iv.first = sha256_h0;
- iv.second = sizeof(sha256_h0) / sizeof(uint32_t);
- return iv;
- }
-};
-
-class ESHA256 : public Module
-{
- SHA256Provider sha256provider;
-
+private:
unsigned iv[8];
bool use_iv;
/* initializes the IV with a new random value */
void NewRandomIV()
{
- for (int i = 0; i < 8; ++i)
- iv[i] = static_cast<uint32_t>(rand());
+ for (auto &ivsegment : iv)
+ ivsegment = static_cast<uint32_t>(Anope::RandomNumber());
}
/* returns the IV as base64-encrypted string */
@@ -268,62 +45,59 @@ class ESHA256 : public Module
char buf2[33];
Anope::Unhex(buf, buf2, sizeof(buf2));
for (int i = 0 ; i < 8; ++i)
- PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), iv[i]);
- }
-
- public:
- ESHA256(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
- sha256provider(this)
- {
-
-
- use_iv = false;
+ PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), &iv[i]);
}
- EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
+ Anope::string EncryptInternal(const Anope::string &src)
{
if (!use_iv)
NewRandomIV();
else
use_iv = false;
- Encryption::IV initialization(this->iv, 8);
- SHA256Context ctx(&initialization);
- ctx.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
- ctx.Finalize();
+ sha256_ctx ctx;
+ sha256_init(&ctx);
+ for (size_t i = 0; i < 8; ++i)
+ ctx.h[i] = iv[i];
+ sha256_update(&ctx, reinterpret_cast<const unsigned char *>(src.data()), src.length());
+ unsigned char digest[SHA256_DIGEST_SIZE];
+ sha256_final(&ctx, digest);
+ Anope::string hash(reinterpret_cast<const char *>(&digest), sizeof(digest));
- Encryption::Hash hash = ctx.GetFinalizedHash();
+ return "sha256:" + Anope::Hex(hash) + ":" + GetIVString();
+ }
- std::stringstream buf;
- buf << "sha256:" << Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second) << ":" << GetIVString();
- Log(LOG_DEBUG_2) << "(enc_sha256) hashed password from [" << src << "] to [" << buf.str() << " ]";
- dest = buf.str();
- return EVENT_ALLOW;
+public:
+ ESHA256(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, 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");
}
- void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
- const NickAlias *na = NickAlias::Find(req->GetAccount());
- if (na == NULL)
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
return;
- NickCore *nc = na->nc;
- size_t pos = nc->pass.find(':');
+ NickCore *nc = na->nc;
+ auto 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("sha256"))
return;
GetIVFromPass(nc->pass);
use_iv = true;
- Anope::string buf;
- this->OnEncrypt(req->GetPassword(), buf);
- if (nc->pass.equals_cs(buf))
+ auto enc = EncryptInternal(req->GetPassword());
+ if (nc->pass.equals_cs(enc))
{
- /* if we are NOT the first module in the list,
- * we want to re-encrypt the pass with the new encryption
- */
+ // 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);
diff --git a/modules/extra/enc_argon2.cpp b/modules/extra/enc_argon2.cpp
new file mode 100644
index 000000000..8d6f27d9b
--- /dev/null
+++ b/modules/extra/enc_argon2.cpp
@@ -0,0 +1,210 @@
+/* Module for providing Argon2 hashing
+ *
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * This program is free but copyrighted software; see the file COPYING for
+ * details.
+ *
+ */
+
+/* RequiredLibraries: argon2 */
+/* RequiredWindowsLibraries: argon2 */
+
+#include <climits>
+#include <random>
+
+#include <argon2.h>
+
+#include "module.h"
+#include "modules/encryption.h"
+
+class Argon2Context final
+ : public Encryption::Context
+{
+private:
+ Anope::string buffer;
+ argon2_type type;
+
+ Anope::string GenerateSalt()
+ {
+ static std::random_device device;
+ static std::mt19937 engine(device());
+ static std::uniform_int_distribution<int> dist(CHAR_MIN, CHAR_MAX);
+ Anope::string saltbuf(this->salt_length, ' ');
+ for (size_t i = 0; i < this->salt_length; ++i)
+ saltbuf[i] = static_cast<char>(dist(engine));
+ return saltbuf;
+ }
+
+public:
+ static uint32_t memory_cost;
+ static uint32_t time_cost;
+ static uint32_t parallelism;
+ static uint32_t hash_length;
+ static uint32_t salt_length;
+
+ Argon2Context(argon2_type at)
+ : type(at)
+ {
+ }
+
+ void Update(const unsigned char *data, size_t len) override
+ {
+ buffer.append(reinterpret_cast<const char *>(data), len);
+ }
+
+ Anope::string Finalize() override
+ {
+ auto salt = GenerateSalt();
+
+ // Calculate the size of and allocate the output buffer.
+ auto length = argon2_encodedlen(this->time_cost, this->memory_cost, this->parallelism,
+ this->salt_length, this->hash_length, this->type);
+
+ std::vector<char> digest(length);
+ auto result = argon2_hash(this->time_cost, this->memory_cost, this->parallelism,
+ buffer.c_str(), buffer.length(), salt.c_str(), salt.length(), nullptr,
+ this->hash_length, digest.data(), digest.size(), this->type,
+ ARGON2_VERSION_NUMBER);
+
+ if (result == ARGON2_OK)
+ return Anope::string(digest.data(), digest.size());
+
+ Log(LOG_DEBUG_2) << "Argon2 error: " << argon2_error_message(result);
+ return {};
+ }
+};
+
+uint32_t Argon2Context::memory_cost;
+uint32_t Argon2Context::time_cost;
+uint32_t Argon2Context::parallelism;
+uint32_t Argon2Context::hash_length;
+uint32_t Argon2Context::salt_length;
+
+class Argon2Provider final
+ : public Encryption::Provider
+{
+private:
+ argon2_type type;
+
+public:
+ Argon2Provider(Module *creator, argon2_type at)
+ : Encryption::Provider(creator, argon2_type2string(at, 0), 0, 0)
+ , type(at)
+ {
+ }
+
+ bool Compare(const Anope::string &hash, const Anope::string &plain) override
+ {
+ return argon2_verify(hash.c_str(), plain.c_str(), plain.length(), this->type) == ARGON2_OK;
+ }
+
+ std::unique_ptr<Encryption::Context> CreateContext() override
+ {
+ return std::make_unique<Argon2Context>(this->type);
+ }
+
+ Anope::string ToPrintable(const Anope::string &hash) override
+ {
+ // We have no way to make this printable without the creating context
+ // so we always return the printed form.
+ return hash;
+ }
+};
+
+class EArgon2 final
+ : public Module
+{
+private:
+ Encryption::Provider *defaultprovider = nullptr;
+ Argon2Provider argon2dprovider;
+ Argon2Provider argon2iprovider;
+ Argon2Provider argon2idprovider;
+
+ Encryption::Provider *GetAlgorithm(const Anope::string &algorithm)
+ {
+ if (algorithm == "argon2d")
+ return &argon2dprovider;
+ if (algorithm == "argon2i")
+ return &argon2iprovider;
+ if (algorithm == "argon2id")
+ return &argon2idprovider;
+ return nullptr;
+ }
+
+public:
+ EArgon2(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
+ , argon2dprovider(this, Argon2_d)
+ , argon2iprovider(this, Argon2_i)
+ , argon2idprovider(this, Argon2_id)
+ {
+ argon2dprovider.Check({
+ { "$argon2d$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$fNS8JrvE8EqKwQ", "" },
+ { "$argon2d$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$hTvpprMF0TwszQ", "The quick brown fox jumps over the lazy dog" },
+ });
+ argon2iprovider.Check({
+ { "$argon2i$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$neE6hYxRp4TCJA", "" },
+ { "$argon2i$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$/JAt4FdP1MFD+A", "The quick brown fox jumps over the lazy dog" },
+ });
+ argon2idprovider.Check({
+ { "$argon2id$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$wuNeHixFDS6Tkg", "" },
+ { "$argon2id$v=19$m=10,t=10,p=1$VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw$Po8RcmxZ7vHmdg", "The quick brown fox jumps over the lazy dog" },
+ });
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ const auto *block = Config->GetModule(this);
+ this->defaultprovider = GetAlgorithm(block->Get<const Anope::string>("algorithm", "argon2id"));
+ Argon2Context::memory_cost = block->Get<uint32_t>("memory_cost", "131072");
+ Argon2Context::time_cost = block->Get<uint32_t>("time_cost", "3");
+ Argon2Context::parallelism = block->Get<uint32_t>("parallelism", "1");
+ Argon2Context::hash_length = block->Get<uint32_t>("hash_length", "32");
+ Argon2Context::salt_length = block->Get<uint32_t>("salt_length", "32");
+ }
+
+ EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
+ {
+ if (!defaultprovider)
+ return EVENT_CONTINUE;
+
+ auto hash = defaultprovider->Encrypt(src);
+ auto enc = defaultprovider->name + ":" + hash;
+ Log(LOG_DEBUG_2) << "(enc_argon2) hashed password from [" << src << "] to [" << enc << "]";
+ dest = enc;
+ return EVENT_ALLOW;
+
+ }
+
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
+ {
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
+ return;
+
+ NickCore *nc = na->nc;
+ auto pos = nc->pass.find(':');
+ if (pos == Anope::string::npos)
+ return;
+
+ Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
+ auto provider = GetAlgorithm(hash_method);
+ if (!provider)
+ return; // Not a hash for this module.
+
+ Anope::string hash_value(nc->pass.begin() + pos + 1, nc->pass.end());
+ if (provider->Compare(hash_value, req->GetPassword()))
+ {
+ // If we are NOT the first encryption module or the algorithm is
+ // different we want to re-encrypt the password with the primary
+ // encryption method.
+ if (ModuleManager::FindFirstOf(ENCRYPTION) != this || provider != defaultprovider)
+ Anope::Encrypt(req->GetPassword(), nc->pass);
+ req->Success(this);
+ }
+ }
+};
+
+MODULE_INIT(EArgon2)
diff --git a/modules/extra/enc_posix.cpp b/modules/extra/enc_posix.cpp
new file mode 100644
index 000000000..acf65d95b
--- /dev/null
+++ b/modules/extra/enc_posix.cpp
@@ -0,0 +1,53 @@
+/* Module for providing POSIX crypt() hashing
+ *
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * This program is free but copyrighted software; see the file COPYING for
+ * details.
+ *
+ */
+
+/* RequiredLibraries: crypt */
+
+#include "module.h"
+
+class EPOSIX final
+ : public Module
+{
+public:
+ EPOSIX(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, ENCRYPTION | VENDOR)
+ {
+ if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
+ throw ModuleException("enc_posix can not be used as a primary encryption method");
+ }
+
+ void OnCheckAuthentication(User *, IdentifyRequest *req) override
+ {
+ const auto *na = NickAlias::Find(req->GetAccount());
+ if (!na)
+ return;
+
+ NickCore *nc = na->nc;
+ auto 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("posix"))
+ return;
+
+ Anope::string pass_hash(nc->pass.begin() + pos + 1, nc->pass.end());
+ if (pass_hash.equals_cs(crypt(req->GetPassword().c_str(), pass_hash.c_str())))
+ {
+ // 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(EPOSIX)
diff --git a/modules/extra/m_ldap.cpp b/modules/extra/ldap.cpp
index ebb2e81b2..ec2b88a39 100644
--- a/modules/extra/m_ldap.cpp
+++ b/modules/extra/ldap.cpp
@@ -14,6 +14,9 @@
#include "module.h"
#include "modules/ldap.h"
+#include <condition_variable>
+#include <mutex>
+
#ifdef _WIN32
# include <Winldap.h>
# include <WinBer.h>
@@ -44,21 +47,18 @@ static Pipe *me;
class LDAPRequest
{
- public:
+public:
LDAPService *service;
LDAPInterface *inter;
- LDAPMessage *message; /* message returned by ldap_ */
- LDAPResult *result; /* final result */
+ LDAPMessage *message = nullptr; /* message returned by ldap_ */
+ LDAPResult *result = nullptr; /* final result */
struct timeval tv;
- QueryType type;
+ QueryType type = QUERY_UNKNOWN;
LDAPRequest(LDAPService *s, LDAPInterface *i)
: service(s)
, inter(i)
- , message(NULL)
- , result(NULL)
{
- type = QUERY_UNKNOWN;
tv.tv_sec = 0;
tv.tv_usec = 100000;
}
@@ -75,11 +75,12 @@ class LDAPRequest
virtual int run() = 0;
};
-class LDAPBind : public LDAPRequest
+class LDAPBind final
+ : public LDAPRequest
{
Anope::string who, pass;
- public:
+public:
LDAPBind(LDAPService *s, LDAPInterface *i, const Anope::string &w, const Anope::string &p)
: LDAPRequest(s, i)
, who(w)
@@ -88,15 +89,16 @@ class LDAPBind : public LDAPRequest
type = QUERY_BIND;
}
- int run() anope_override;
+ int run() override;
};
-class LDAPSearchRequest : public LDAPRequest
+class LDAPSearchRequest final
+ : public LDAPRequest
{
Anope::string base;
Anope::string filter;
- public:
+public:
LDAPSearchRequest(LDAPService *s, LDAPInterface *i, const Anope::string &b, const Anope::string &f)
: LDAPRequest(s, i)
, base(b)
@@ -105,15 +107,16 @@ class LDAPSearchRequest : public LDAPRequest
type = QUERY_SEARCH;
}
- int run() anope_override;
+ int run() override;
};
-class LDAPAdd : public LDAPRequest
+class LDAPAdd final
+ : public LDAPRequest
{
Anope::string dn;
LDAPMods attributes;
- public:
+public:
LDAPAdd(LDAPService *s, LDAPInterface *i, const Anope::string &d, const LDAPMods &attr)
: LDAPRequest(s, i)
, dn(d)
@@ -122,14 +125,15 @@ class LDAPAdd : public LDAPRequest
type = QUERY_ADD;
}
- int run() anope_override;
+ int run() override;
};
-class LDAPDel : public LDAPRequest
+class LDAPDel final
+ : public LDAPRequest
{
Anope::string dn;
- public:
+public:
LDAPDel(LDAPService *s, LDAPInterface *i, const Anope::string &d)
: LDAPRequest(s, i)
, dn(d)
@@ -137,15 +141,16 @@ class LDAPDel : public LDAPRequest
type = QUERY_DELETE;
}
- int run() anope_override;
+ int run() override;
};
-class LDAPModify : public LDAPRequest
+class LDAPModify final
+ : public LDAPRequest
{
Anope::string base;
LDAPMods attributes;
- public:
+public:
LDAPModify(LDAPService *s, LDAPInterface *i, const Anope::string &b, const LDAPMods &attr)
: LDAPRequest(s, i)
, base(b)
@@ -154,10 +159,12 @@ class LDAPModify : public LDAPRequest
type = QUERY_MODIFY;
}
- int run() anope_override;
+ int run() override;
};
-class LDAPService : public LDAPProvider, public Thread, public Condition
+class LDAPService final
+ : public LDAPProvider
+ , public Thread
{
Anope::string server;
Anope::string admin_binddn;
@@ -165,9 +172,12 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
LDAP *con;
- time_t last_connect;
+ time_t last_connect = 0;
+
+public:
+ std::condition_variable_any condvar;
+ std::mutex mutex;
- public:
static LDAPMod **BuildMods(const LDAPMods &attributes)
{
LDAPMod **mods = new LDAPMod*[attributes.size() + 1];
@@ -207,10 +217,10 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
delete [] mods;
}
- private:
+private:
#ifdef _WIN32
// Windows LDAP does not implement this so we need to do it.
- int ldap_initialize(LDAP** ldap, const char* url)
+ int ldap_initialize(LDAP **ldap, const char *url)
{
URL_COMPONENTS urlComponents;
memset(&urlComponents, 0, sizeof(urlComponents));
@@ -296,18 +306,18 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
void QueueRequest(LDAPRequest *r)
{
- this->Lock();
+ this->mutex.lock();
this->queries.push_back(r);
- this->Wakeup();
- this->Unlock();
+ this->condvar.notify_all();
+ this->mutex.unlock();
}
- public:
+public:
typedef std::vector<LDAPRequest *> query_queue;
query_queue queries, results;
- Mutex process_mutex; /* held when processing requests not in either queue */
+ std::mutex process_mutex; /* held when processing requests not in either queue */
- LDAPService(Module *o, const Anope::string &n, const Anope::string &s, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, n), server(s), admin_binddn(b), admin_pass(p), last_connect(0)
+ LDAPService(Module *o, const Anope::string &n, const Anope::string &s, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, n), server(s), admin_binddn(b), admin_pass(p)
{
Connect();
}
@@ -316,12 +326,10 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
{
/* At this point the thread has stopped so we don't need to hold process_mutex */
- this->Lock();
+ this->mutex.lock();
- for (unsigned int i = 0; i < this->queries.size(); ++i)
+ for (auto *req : this->queries)
{
- LDAPRequest *req = this->queries[i];
-
/* queries have no results yet */
req->result = new LDAPResult();
req->result->type = req->type;
@@ -333,10 +341,8 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
}
this->queries.clear();
- for (unsigned int i = 0; i < this->results.size(); ++i)
+ for (const auto *req : this->queries)
{
- LDAPRequest *req = this->results[i];
-
/* even though this may have already finished successfully we return that it didn't */
req->result->error = "LDAP Interface is going away";
if (req->inter)
@@ -345,50 +351,50 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
delete req;
}
- this->Unlock();
+ this->mutex.unlock();
ldap_unbind_ext(this->con, NULL, NULL);
}
- void BindAsAdmin(LDAPInterface *i) anope_override
+ void BindAsAdmin(LDAPInterface *i) override
{
this->Bind(i, this->admin_binddn, this->admin_pass);
}
- void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) anope_override
+ void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) override
{
- LDAPBind *b = new LDAPBind(this, i, who, pass);
+ auto *b = new LDAPBind(this, i, who, pass);
QueueRequest(b);
}
- void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) anope_override
+ void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) override
{
if (i == NULL)
throw LDAPException("No interface");
- LDAPSearchRequest *s = new LDAPSearchRequest(this, i, base, filter);
+ auto *s = new LDAPSearchRequest(this, i, base, filter);
QueueRequest(s);
}
- void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) anope_override
+ void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) override
{
- LDAPAdd *add = new LDAPAdd(this, i, dn, attributes);
+ auto *add = new LDAPAdd(this, i, dn, attributes);
QueueRequest(add);
}
- void Del(LDAPInterface *i, const Anope::string &dn) anope_override
+ void Del(LDAPInterface *i, const Anope::string &dn) override
{
- LDAPDel *del = new LDAPDel(this, i, dn);
+ auto *del = new LDAPDel(this, i, dn);
QueueRequest(del);
}
- void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) anope_override
+ void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) override
{
- LDAPModify *mod = new LDAPModify(this, i, base, attributes);
+ auto *mod = new LDAPModify(this, i, base, attributes);
QueueRequest(mod);
}
- private:
+private:
void BuildReply(int res, LDAPRequest *req)
{
LDAPResult *ldap_result = req->result = new LDAPResult();
@@ -444,22 +450,21 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
void SendRequests()
{
- process_mutex.Lock();
+ process_mutex.lock();
query_queue q;
- this->Lock();
+ this->mutex.lock();
queries.swap(q);
- this->Unlock();
+ this->mutex.unlock();
if (q.empty())
{
- process_mutex.Unlock();
+ process_mutex.unlock();
return;
}
- for (unsigned int i = 0; i < q.size(); ++i)
+ for (auto *req : q)
{
- LDAPRequest *req = q[i];
int ret = req->run();
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
@@ -478,42 +483,44 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
BuildReply(ret, req);
- this->Lock();
+ this->mutex.lock();
results.push_back(req);
- this->Unlock();
+ this->mutex.unlock();
}
me->Notify();
- process_mutex.Unlock();
+ process_mutex.unlock();
}
- public:
- void Run() anope_override
+public:
+ void Run() override
{
while (!this->GetExitState())
{
- this->Lock();
+ this->mutex.lock();
/* Queries can be non empty if one is pushed during SendRequests() */
if (queries.empty())
- this->Wait();
- this->Unlock();
+ this->condvar.wait(this->mutex);
+ this->mutex.unlock();
SendRequests();
}
}
- LDAP* GetConnection()
+ LDAP *GetConnection()
{
return con;
}
};
-class ModuleLDAP : public Module, public Pipe
+class ModuleLDAP final
+ : public Module
+ , public Pipe
{
std::map<Anope::string, LDAPService *> LDAPServices;
- public:
+public:
ModuleLDAP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
@@ -525,14 +532,14 @@ class ModuleLDAP : public Module, public Pipe
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
{
it->second->SetExitState();
- it->second->Wakeup();
+ it->second->condvar.notify_all();
it->second->Join();
delete it->second;
}
LDAPServices.clear();
}
- void OnReload(Configuration::Conf *config) anope_override
+ void OnReload(Configuration::Conf *config) override
{
Configuration::Block *conf = config->GetModule(this);
@@ -553,7 +560,7 @@ class ModuleLDAP : public Module, public Pipe
Log(LOG_NORMAL, "ldap") << "LDAP: Removing server connection " << cname;
s->SetExitState();
- s->Wakeup();
+ s->condvar.notify_all();
s->Join();
delete s;
this->LDAPServices.erase(cname);
@@ -574,9 +581,9 @@ class ModuleLDAP : public Module, public Pipe
try
{
- LDAPService *ss = new LDAPService(this, connname, server, admin_binddn, admin_password);
+ auto *ss = new LDAPService(this, connname, server, admin_binddn, admin_password);
ss->Start();
- this->LDAPServices.insert(std::make_pair(connname, ss));
+ this->LDAPServices.emplace(connname, ss);
Log(LOG_NORMAL, "ldap") << "LDAP: Successfully initialized server " << connname << " (" << server << ")";
}
@@ -588,14 +595,14 @@ class ModuleLDAP : public Module, public Pipe
}
}
- void OnModuleUnload(User *, Module *m) anope_override
+ void OnModuleUnload(User *, Module *m) override
{
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
{
LDAPService *s = it->second;
- s->process_mutex.Lock();
- s->Lock();
+ s->process_mutex.lock();
+ s->mutex.lock();
for (unsigned int i = s->queries.size(); i > 0; --i)
{
@@ -620,25 +627,24 @@ class ModuleLDAP : public Module, public Pipe
}
}
- s->Unlock();
- s->process_mutex.Unlock();
+ s->mutex.unlock();
+ s->process_mutex.unlock();
}
}
- void OnNotify() anope_override
+ void OnNotify() override
{
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
{
LDAPService *s = it->second;
LDAPService::query_queue results;
- s->Lock();
+ s->mutex.lock();
results.swap(s->results);
- s->Unlock();
+ s->mutex.unlock();
- for (unsigned int i = 0; i < results.size(); ++i)
+ for (const auto *req : results)
{
- LDAPRequest *req = results[i];
LDAPInterface *li = req->inter;
LDAPResult *r = req->result;
diff --git a/modules/extra/m_regex_pcre.cpp b/modules/extra/m_regex_pcre.cpp
deleted file mode 100644
index 6b54e4aba..000000000
--- a/modules/extra/m_regex_pcre.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *
- * (C) 2012-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-/* RequiredLibraries: pcre */
-/* RequiredWindowsLibraries: libpcre */
-
-#include "module.h"
-#include <pcre.h>
-
-class PCRERegex : public Regex
-{
- pcre *regex;
-
- public:
- PCRERegex(const Anope::string &expr) : Regex(expr)
- {
- const char *error;
- int erroffset;
- this->regex = pcre_compile(expr.c_str(), PCRE_CASELESS, &error, &erroffset, NULL);
- if (!this->regex)
- throw RegexException("Error in regex " + expr + " at offset " + stringify(erroffset) + ": " + error);
- }
-
- ~PCRERegex()
- {
- pcre_free(this->regex);
- }
-
- bool Matches(const Anope::string &str)
- {
- return pcre_exec(this->regex, NULL, str.c_str(), str.length(), 0, 0, NULL, 0) > -1;
- }
-};
-
-class PCRERegexProvider : public RegexProvider
-{
- public:
- PCRERegexProvider(Module *creator) : RegexProvider(creator, "regex/pcre") { }
-
- Regex *Compile(const Anope::string &expression) anope_override
- {
- return new PCRERegex(expression);
- }
-};
-
-class ModuleRegexPCRE : public Module
-{
- PCRERegexProvider pcre_regex_provider;
-
- public:
- ModuleRegexPCRE(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
- pcre_regex_provider(this)
- {
- this->SetPermanent(true);
- }
-
- ~ModuleRegexPCRE()
- {
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(); it != XLineManager::XLineManagers.end(); ++it)
- {
- XLineManager *xlm = *it;
- const std::vector<XLine *> &xlines = xlm->GetList();
-
- for (unsigned int i = 0; i < xlines.size(); ++i)
- {
- XLine *x = xlines[i];
-
- if (x->regex && dynamic_cast<PCRERegex *>(x->regex))
- {
- delete x->regex;
- x->regex = NULL;
- }
- }
- }
- }
-};
-
-MODULE_INIT(ModuleRegexPCRE)
diff --git a/modules/extra/m_mysql.cpp b/modules/extra/mysql.cpp
index d448d1aa4..027291991 100644
--- a/modules/extra/m_mysql.cpp
+++ b/modules/extra/mysql.cpp
@@ -11,13 +11,16 @@
#include "module.h"
#include "modules/sql.h"
-#define NO_CLIENT_LONG_LONG
+
#ifdef WIN32
# include <mysql.h>
#else
# include <mysql/mysql.h>
#endif
+#include <condition_variable>
+#include <mutex>
+
using namespace SQL;
/** Non blocking threaded MySQL API, based loosely from InspIRCd's m_mysql.cpp
@@ -34,7 +37,7 @@ class MySQLService;
/** A query request
*/
-struct QueryRequest
+struct QueryRequest final
{
/* The connection to the database */
MySQLService *service;
@@ -47,7 +50,7 @@ struct QueryRequest
};
/** A query result */
-struct QueryResult
+struct QueryResult final
{
/* The interface to send the data back on */
Interface *sqlinterface;
@@ -59,11 +62,12 @@ struct QueryResult
/** A MySQL result
*/
-class MySQLResult : public Result
+class MySQLResult final
+ : public Result
{
- MYSQL_RES *res;
+ MYSQL_RES *res = nullptr;
- public:
+public:
MySQLResult(unsigned int i, const Query &q, const Anope::string &fq, MYSQL_RES *r) : Result(i, q, fq), res(r)
{
unsigned num_fields = res ? mysql_num_fields(res) : 0;
@@ -94,7 +98,7 @@ class MySQLResult : public Result
}
}
- MySQLResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err), res(NULL)
+ MySQLResult(const Query &q, const Anope::string &fq, const Anope::string &err) : Result(0, q, fq, err)
{
}
@@ -107,7 +111,8 @@ class MySQLResult : public Result
/** A MySQL connection, there can be multiple
*/
-class MySQLService : public Provider
+class MySQLService final
+ : public Provider
{
std::map<Anope::string, std::set<Anope::string> > active_schema;
@@ -115,35 +120,36 @@ class MySQLService : public Provider
Anope::string server;
Anope::string user;
Anope::string password;
- int port;
+ unsigned int port;
+ Anope::string socket;
- MYSQL *sql;
+ MYSQL *sql = nullptr;
/** Escape a query.
* Note the mutex must be held!
*/
Anope::string Escape(const Anope::string &query);
- public:
+public:
/* Locked by the SQL thread when a query is pending on this database,
* prevents us from deleting a connection while a query is executing
* in the thread
*/
- Mutex Lock;
+ std::mutex Lock;
- MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, int po);
+ MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, unsigned int po, const Anope::string &so);
~MySQLService();
- void Run(Interface *i, const Query &query) anope_override;
+ void Run(Interface *i, const Query &query) override;
- Result RunQuery(const Query &query) anope_override;
+ Result RunQuery(const Query &query) override;
- std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
+ std::vector<Query> CreateTable(const Anope::string &table, const Data &data) override;
- Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) anope_override;
+ Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) override;
- Query GetTables(const Anope::string &prefix) anope_override;
+ Query GetTables(const Anope::string &prefix) override;
void Connect();
@@ -151,26 +157,80 @@ class MySQLService : public Provider
Anope::string BuildQuery(const Query &q);
- Anope::string FromUnixtime(time_t);
+ Anope::string FromUnixtime(time_t) override;
+
+ const char* GetColumnDefault(Serialize::DataType dt)
+ {
+ switch (dt)
+ {
+ case Serialize::DataType::BOOL:
+ case Serialize::DataType::INT:
+ case Serialize::DataType::UINT:
+ return "0";
+ case Serialize::DataType::FLOAT:
+ return "0.0";
+ case Serialize::DataType::TEXT:
+ return "NULL";
+ }
+ return "NULL"; // Should never be reached
+ }
+
+ bool GetColumnNull(Serialize::DataType dt)
+ {
+ return dt == Serialize::DataType::TEXT;
+ }
+
+ const char* GetColumnType(Serialize::DataType dt)
+ {
+ switch (dt)
+ {
+ case Serialize::DataType::BOOL:
+ return "TINYINT";
+ case Serialize::DataType::FLOAT:
+ return "DOUBLE";
+ case Serialize::DataType::INT:
+ return "BIGINT";
+ case Serialize::DataType::TEXT:
+ return "TEXT";
+ case Serialize::DataType::UINT:
+ return "BIGINT UNSIGNED";
+ }
+ return "TEXT"; // Should never be reached
+ }
+
+ Anope::string GetColumn(Serialize::DataType dt)
+ {
+ return Anope::printf("%s %s DEFAULT %s",
+ GetColumnType(dt),
+ GetColumnNull(dt) ? "NULL" : "NOT NULL",
+ GetColumnDefault(dt));
+ }
};
/** The SQL thread used to execute queries
*/
-class DispatcherThread : public Thread, public Condition
+class DispatcherThread final
+ : public Thread
{
- public:
+public:
+ std::condition_variable_any condvar;
+ std::mutex mutex;
+
DispatcherThread() : Thread() { }
- void Run() anope_override;
+ void Run() override;
};
class ModuleSQL;
static ModuleSQL *me;
-class ModuleSQL : public Module, public Pipe
+
+class ModuleSQL final
+ : public Module
+ , public Pipe
{
/* SQL connections */
std::map<Anope::string, MySQLService *> MySQLServices;
- public:
+public:
/* Pending query requests */
std::deque<QueryRequest> QueryRequests;
/* Pending finished requests with results */
@@ -194,12 +254,12 @@ class ModuleSQL : public Module, public Pipe
MySQLServices.clear();
DThread->SetExitState();
- DThread->Wakeup();
+ DThread->condvar.notify_all();
DThread->Join();
delete DThread;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
@@ -235,14 +295,15 @@ class ModuleSQL : public Module, public Pipe
const Anope::string &server = block->Get<const Anope::string>("server", "127.0.0.1");
const Anope::string &user = block->Get<const Anope::string>("username", "anope");
const Anope::string &password = block->Get<const Anope::string>("password");
- int port = block->Get<int>("port", "3306");
+ unsigned int port = block->Get<unsigned int>("port", "3306");
+ const Anope::string &socket = block->Get<const Anope::string>("socket");
try
{
- MySQLService *ss = new MySQLService(this, connname, database, server, user, password, port);
- this->MySQLServices.insert(std::make_pair(connname, ss));
+ auto *ss = new MySQLService(this, connname, database, server, user, password, port, socket);
+ this->MySQLServices.emplace(connname, ss);
- Log(LOG_NORMAL, "mysql") << "MySQL: Successfully connected to server " << connname << " (" << server << ")";
+ Log(LOG_NORMAL, "mysql") << "MySQL: Successfully connected to server " << connname << " (" << (socket.empty() ? server + ":" + port : socket) << ")";
}
catch (const SQL::Exception &ex)
{
@@ -252,9 +313,9 @@ class ModuleSQL : public Module, public Pipe
}
}
- void OnModuleUnload(User *, Module *m) anope_override
+ void OnModuleUnload(User *, Module *m) override
{
- this->DThread->Lock();
+ this->DThread->mutex.lock();
for (unsigned i = this->QueryRequests.size(); i > 0; --i)
{
@@ -264,30 +325,28 @@ class ModuleSQL : public Module, public Pipe
{
if (i == 1)
{
- r.service->Lock.Lock();
- r.service->Lock.Unlock();
+ r.service->Lock.lock();
+ r.service->Lock.unlock();
}
this->QueryRequests.erase(this->QueryRequests.begin() + i - 1);
}
}
- this->DThread->Unlock();
+ this->DThread->mutex.unlock();
this->OnNotify();
}
- void OnNotify() anope_override
+ void OnNotify() override
{
- this->DThread->Lock();
+ this->DThread->mutex.lock();
std::deque<QueryResult> finishedRequests = this->FinishedRequests;
this->FinishedRequests.clear();
- this->DThread->Unlock();
+ this->DThread->mutex.unlock();
- for (std::deque<QueryResult>::const_iterator it = finishedRequests.begin(), it_end = finishedRequests.end(); it != it_end; ++it)
+ for (const auto &qr : finishedRequests)
{
- const QueryResult &qr = *it;
-
if (!qr.sqlinterface)
throw SQL::Exception("NULL qr.sqlinterface in MySQLPipe::OnNotify() ?");
@@ -299,16 +358,22 @@ class ModuleSQL : public Module, public Pipe
}
};
-MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, int po)
-: Provider(o, n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
+MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, unsigned int po, const Anope::string &so)
+ : Provider(o, n)
+ , database(d)
+ , server(s)
+ , user(u)
+ , password(p)
+ , port(po)
+ , socket(so)
{
Connect();
}
MySQLService::~MySQLService()
{
- me->DThread->Lock();
- this->Lock.Lock();
+ me->DThread->mutex.lock();
+ this->Lock.lock();
mysql_close(this->sql);
this->sql = NULL;
@@ -323,25 +388,25 @@ MySQLService::~MySQLService()
me->QueryRequests.erase(me->QueryRequests.begin() + i - 1);
}
}
- this->Lock.Unlock();
- me->DThread->Unlock();
+ this->Lock.unlock();
+ me->DThread->mutex.unlock();
}
void MySQLService::Run(Interface *i, const Query &query)
{
- me->DThread->Lock();
+ me->DThread->mutex.lock();
me->QueryRequests.push_back(QueryRequest(this, i, query));
- me->DThread->Unlock();
- me->DThread->Wakeup();
+ me->DThread->mutex.unlock();
+ me->DThread->condvar.notify_all();
}
Result MySQLService::RunQuery(const Query &query)
{
- this->Lock.Lock();
+ this->Lock.lock();
if (!this->CheckConnection())
{
- this->Lock.Unlock();
+ this->Lock.unlock();
return MySQLResult(query, query.query, mysql_error(this->sql));
}
@@ -360,13 +425,13 @@ Result MySQLService::RunQuery(const Query &query)
while (!mysql_next_result(this->sql))
mysql_free_result(mysql_store_result(this->sql));
- this->Lock.Unlock();
+ this->Lock.unlock();
return MySQLResult(id, query, real_query, res);
}
else
{
Anope::string error = mysql_error(this->sql);
- this->Lock.Unlock();
+ this->Lock.unlock();
return MySQLResult(query, real_query, error);
}
}
@@ -378,51 +443,114 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
if (known_cols.empty())
{
- Log(LOG_DEBUG) << "m_mysql: Fetching columns for " << table;
+ Log(LOG_DEBUG) << "mysql: Fetching columns for " << table;
Result columns = this->RunQuery("SHOW COLUMNS FROM `" + table + "`");
for (int i = 0; i < columns.Rows(); ++i)
{
- const Anope::string &column = columns.Get(i, "Field");
- Log(LOG_DEBUG) << "m_mysql: Column #" << i << " for " << table << ": " << column;
+ const auto column = columns.Get(i, "Field");
+ Log(LOG_DEBUG) << "mysql: Column #" << i << " for " << table << ": " << column;
+
+ if (column == "id" || column == "timestamp")
+ continue; // These columns are special and aren't part of the data.
+
known_cols.insert(column);
+ if (data.data.count(column) == 0)
+ {
+ Log(LOG_DEBUG) << "mysql: Column has been removed from the data set: " << column;
+ continue;
+ }
+
+ // We know the column exists but is the type correct?
+ auto update = false;
+ const auto stype = data.GetType(column);
+
+ auto coldef = columns.Get(i, "Default");
+ if (coldef.empty())
+ coldef = "NULL";
+
+ const auto *newcoldef = GetColumnDefault(stype);
+ if (!coldef.equals_ci(newcoldef))
+ {
+ Log(LOG_DEBUG) << "mysql: Updating the default of " << column << " from " << coldef << " to " << newcoldef;
+ update = true;
+ }
+
+ const auto colnull = columns.Get(i, "Null");
+ const auto newcolnull = GetColumnNull(stype) ? "YES" : "NO";
+ if (!colnull.equals_ci(newcolnull))
+ {
+ Log(LOG_DEBUG) << "mysql: Updating the nullability of " << column << " from " << colnull << " to " << newcolnull;
+ update = true;
+ }
+
+ const auto coltype = columns.Get(i, "Type");
+ const auto *newcoltype = GetColumnType(stype);
+ if (!coltype.equals_ci(newcoltype))
+ {
+ Log(LOG_DEBUG) << "mysql: Updating the type of " << column << " from " << coltype << " to " << newcoltype;
+ update = true;
+ }
+
+ if (update)
+ {
+ // We can't just use MODIFY COLUMN here because the value may not
+ // be valid and we may need to replace with the default.
+ auto res = this->RunQuery(Anope::printf("ALTER TABLE `%s` ADD COLUMN `%s_new` %s; ",
+ table.c_str(), column.c_str(), GetColumn(stype).c_str()));
+
+ if (res)
+ {
+ res = this->RunQuery(Anope::printf("UPDATE IGNORE `%s` SET `%s_new` = %s; ",
+ table.c_str(), column.c_str(), column.c_str()));
+ }
+
+ if (res)
+ {
+ res = this->RunQuery(Anope::printf("ALTER TABLE `%s` DROP COLUMN `%s`; ",
+ table.c_str(), column.c_str()));
+ }
+
+ if (res)
+ {
+ res = this->RunQuery(Anope::printf("ALTER TABLE `%s` RENAME COLUMN `%s_new` TO `%s`; ",
+ table.c_str(), column.c_str(), column.c_str()));
+ }
+
+ if (!res)
+ Log(LOG_DEBUG) << "Failed to migrate the " << column << " column: " << res.GetError();
+ }
}
}
if (known_cols.empty())
{
- Anope::string query_text = "CREATE TABLE `" + table + "` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
+ Anope::string query_text = "CREATE TABLE `" + table + "` (`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,"
" `timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (const auto &[column, _] : data.data)
{
- known_cols.insert(it->first);
+ known_cols.insert(column);
- query_text += ", `" + it->first + "` ";
- if (data.GetType(it->first) == Serialize::Data::DT_INT)
- query_text += "int";
- else
- query_text += "text";
+ query_text += ", `" + column + "` " + GetColumn(data.GetType(column));
}
query_text += ", PRIMARY KEY (`id`), KEY `timestamp_idx` (`timestamp`)) ROW_FORMAT=DYNAMIC";
queries.push_back(query_text);
}
else
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ {
+ for (const auto &[column, _] : data.data)
{
- if (known_cols.count(it->first) > 0)
+ if (known_cols.count(column) > 0)
continue;
- known_cols.insert(it->first);
+ known_cols.insert(column);
- Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
- if (data.GetType(it->first) == Serialize::Data::DT_INT)
- query_text += "int";
- else
- query_text += "text";
+ Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumn(data.GetType(column));
queries.push_back(query_text);
}
+ }
return queries;
}
@@ -430,36 +558,56 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Data &data)
{
/* Empty columns not present in the data set */
- const std::set<Anope::string> &known_cols = this->active_schema[table];
- for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
- if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
- data[*it] << "";
+ for (const auto &known_col : this->active_schema[table])
+ {
+ if (data.data.count(known_col) == 0)
+ data[known_col] << "";
+ }
Anope::string query_text = "INSERT INTO `" + table + "` (`id`";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += ",`" + it->first + "`";
- query_text += ") VALUES (" + stringify(id);
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += ",@" + it->first + "@";
+
+ for (const auto &[field, _] : data.data)
+ query_text += ",`" + field + "`";
+ query_text += ") VALUES (" + Anope::ToString(id);
+ for (const auto &[field, _] : data.data)
+ query_text += ",@" + field + "@";
query_text += ") ON DUPLICATE KEY UPDATE ";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += "`" + it->first + "`=VALUES(`" + it->first + "`),";
+ for (const auto &[field, _] : data.data)
+ query_text += "`" + field + "`=VALUES(`" + field + "`),";
query_text.erase(query_text.end() - 1);
Query query(query_text);
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (auto &[field, value] : data.data)
{
Anope::string buf;
- *it->second >> buf;
+ *value >> buf;
- bool escape = true;
- if (buf.empty())
+ auto escape = true;
+ switch (data.GetType(field))
{
- buf = "NULL";
- escape = false;
+ case Serialize::DataType::BOOL:
+ case Serialize::DataType::FLOAT:
+ case Serialize::DataType::INT:
+ case Serialize::DataType::UINT:
+ {
+ if (buf.empty())
+ buf = "DEFAULT";
+ escape = false;
+ break;
+ }
+
+ case Serialize::DataType::TEXT:
+ {
+ if (buf.empty())
+ {
+ buf = "DEFAULT";
+ escape = false;
+ }
+ break;
+ }
}
- query.SetValue(it->first, buf, escape);
+ query.SetValue(field, buf, escape);
}
return query;
@@ -477,12 +625,15 @@ void MySQLService::Connect()
const unsigned int timeout = 1;
mysql_options(this->sql, MYSQL_OPT_CONNECT_TIMEOUT, reinterpret_cast<const char *>(&timeout));
- bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, CLIENT_MULTI_RESULTS);
+ bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, this->socket.empty() ? nullptr : this->socket.c_str(), CLIENT_MULTI_RESULTS);
if (!connect)
throw SQL::Exception("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
- Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
+ if (this->socket.empty())
+ Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
+ else
+ Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->socket;
}
@@ -514,31 +665,31 @@ Anope::string MySQLService::BuildQuery(const Query &q)
{
Anope::string real_query = q.query;
- for (std::map<Anope::string, QueryData>::const_iterator it = q.parameters.begin(), it_end = q.parameters.end(); it != it_end; ++it)
- real_query = real_query.replace_all_cs("@" + it->first + "@", (it->second.escape ? ("'" + this->Escape(it->second.data) + "'") : it->second.data));
+ for (const auto &[name, value] : q.parameters)
+ real_query = real_query.replace_all_cs("@" + name + "@", (value.escape ? ("'" + this->Escape(value.data) + "'") : value.data));
return real_query;
}
Anope::string MySQLService::FromUnixtime(time_t t)
{
- return "FROM_UNIXTIME(" + stringify(t) + ")";
+ return "FROM_UNIXTIME(" + Anope::ToString(t) + ")";
}
void DispatcherThread::Run()
{
- this->Lock();
+ this->mutex.lock();
while (!this->GetExitState())
{
if (!me->QueryRequests.empty())
{
QueryRequest &r = me->QueryRequests.front();
- this->Unlock();
+ this->mutex.unlock();
Result sresult = r.service->RunQuery(r.query);
- this->Lock();
+ this->mutex.lock();
if (!me->QueryRequests.empty() && me->QueryRequests.front().query == r.query)
{
if (r.sqlinterface)
@@ -550,11 +701,11 @@ void DispatcherThread::Run()
{
if (!me->FinishedRequests.empty())
me->Notify();
- this->Wait();
+ this->condvar.wait(this->mutex);
}
}
- this->Unlock();
+ this->mutex.unlock();
}
MODULE_INIT(ModuleSQL)
diff --git a/modules/extra/m_regex_pcre2.cpp b/modules/extra/regex_pcre2.cpp
index 23c45a5b8..a99eb9afb 100644
--- a/modules/extra/m_regex_pcre2.cpp
+++ b/modules/extra/regex_pcre2.cpp
@@ -14,11 +14,12 @@
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
-class PCRERegex : public Regex
+class PCRERegex final
+ : public Regex
{
pcre2_code *regex;
- public:
+public:
PCRERegex(const Anope::string &expr) : Regex(expr)
{
int errcode;
@@ -29,7 +30,7 @@ class PCRERegex : public Regex
{
PCRE2_UCHAR error[128];
pcre2_get_error_message(errcode, error, sizeof error);
- throw RegexException("Error in regex " + expr + " at offset " + stringify(erroffset) + ": " + reinterpret_cast<const char*>(error));
+ throw RegexException("Error in regex " + expr + " at offset " + Anope::ToString(erroffset) + ": " + reinterpret_cast<const char*>(error));
}
}
@@ -47,22 +48,24 @@ class PCRERegex : public Regex
}
};
-class PCRERegexProvider : public RegexProvider
+class PCRERegexProvider final
+ : public RegexProvider
{
- public:
+public:
PCRERegexProvider(Module *creator) : RegexProvider(creator, "regex/pcre") { }
- Regex *Compile(const Anope::string &expression) anope_override
+ Regex *Compile(const Anope::string &expression) override
{
return new PCRERegex(expression);
}
};
-class ModuleRegexPCRE : public Module
+class ModuleRegexPCRE final
+ : public Module
{
PCRERegexProvider pcre_regex_provider;
- public:
+public:
ModuleRegexPCRE(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
pcre_regex_provider(this)
{
@@ -71,15 +74,10 @@ class ModuleRegexPCRE : public Module
~ModuleRegexPCRE()
{
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(); it != XLineManager::XLineManagers.end(); ++it)
+ for (auto *xlm : XLineManager::XLineManagers)
{
- XLineManager *xlm = *it;
- const std::vector<XLine *> &xlines = xlm->GetList();
-
- for (unsigned int i = 0; i < xlines.size(); ++i)
+ for (auto *x : xlm->GetList())
{
- XLine *x = xlines[i];
-
if (x->regex && dynamic_cast<PCRERegex *>(x->regex))
{
delete x->regex;
diff --git a/modules/extra/m_regex_posix.cpp b/modules/extra/regex_posix.cpp
index ad0adca18..e183b6c82 100644
--- a/modules/extra/m_regex_posix.cpp
+++ b/modules/extra/regex_posix.cpp
@@ -10,11 +10,12 @@
#include <sys/types.h>
#include <regex.h>
-class POSIXRegex : public Regex
+class POSIXRegex final
+ : public Regex
{
regex_t regbuf;
- public:
+public:
POSIXRegex(const Anope::string &expr) : Regex(expr)
{
int err = regcomp(&this->regbuf, expr.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE);
@@ -38,22 +39,24 @@ class POSIXRegex : public Regex
}
};
-class POSIXRegexProvider : public RegexProvider
+class POSIXRegexProvider final
+ : public RegexProvider
{
- public:
+public:
POSIXRegexProvider(Module *creator) : RegexProvider(creator, "regex/posix") { }
- Regex *Compile(const Anope::string &expression) anope_override
+ Regex *Compile(const Anope::string &expression) override
{
return new POSIXRegex(expression);
}
};
-class ModuleRegexPOSIX : public Module
+class ModuleRegexPOSIX final
+ : public Module
{
POSIXRegexProvider posix_regex_provider;
- public:
+public:
ModuleRegexPOSIX(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
posix_regex_provider(this)
{
@@ -62,15 +65,10 @@ class ModuleRegexPOSIX : public Module
~ModuleRegexPOSIX()
{
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(); it != XLineManager::XLineManagers.end(); ++it)
+ for (auto *xlm : XLineManager::XLineManagers)
{
- XLineManager *xlm = *it;
- const std::vector<XLine *> &xlines = xlm->GetList();
-
- for (unsigned int i = 0; i < xlines.size(); ++i)
+ for (auto *x : xlm->GetList())
{
- XLine *x = xlines[i];
-
if (x->regex && dynamic_cast<POSIXRegex *>(x->regex))
{
delete x->regex;
diff --git a/modules/extra/m_regex_tre.cpp b/modules/extra/regex_tre.cpp
index a47348189..022dd0d9d 100644
--- a/modules/extra/m_regex_tre.cpp
+++ b/modules/extra/regex_tre.cpp
@@ -11,11 +11,12 @@
#include "module.h"
#include <tre/regex.h>
-class TRERegex : public Regex
+class TRERegex final
+ : public Regex
{
regex_t regbuf;
- public:
+public:
TRERegex(const Anope::string &expr) : Regex(expr)
{
int err = regcomp(&this->regbuf, expr.c_str(), REG_EXTENDED | REG_NOSUB);
@@ -39,22 +40,24 @@ class TRERegex : public Regex
}
};
-class TRERegexProvider : public RegexProvider
+class TRERegexProvider final
+ : public RegexProvider
{
- public:
+public:
TRERegexProvider(Module *creator) : RegexProvider(creator, "regex/tre") { }
- Regex *Compile(const Anope::string &expression) anope_override
+ Regex *Compile(const Anope::string &expression) override
{
return new TRERegex(expression);
}
};
-class ModuleRegexTRE : public Module
+class ModuleRegexTRE final
+ : public Module
{
TRERegexProvider tre_regex_provider;
- public:
+public:
ModuleRegexTRE(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
tre_regex_provider(this)
{
@@ -63,15 +66,10 @@ class ModuleRegexTRE : public Module
~ModuleRegexTRE()
{
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(); it != XLineManager::XLineManagers.end(); ++it)
+ for (auto *xlm : XLineManager::XLineManagers)
{
- XLineManager *xlm = *it;
- const std::vector<XLine *> &xlines = xlm->GetList();
-
- for (unsigned int i = 0; i < xlines.size(); ++i)
+ for (auto *x : xlm->GetList())
{
- XLine *x = xlines[i];
-
if (x->regex && dynamic_cast<TRERegex *>(x->regex))
{
delete x->regex;
diff --git a/modules/extra/m_sqlite.cpp b/modules/extra/sqlite.cpp
index da09d45e2..565c1ee30 100644
--- a/modules/extra/m_sqlite.cpp
+++ b/modules/extra/sqlite.cpp
@@ -19,9 +19,10 @@ using namespace SQL;
/** A SQLite result
*/
-class SQLiteResult : public Result
+class SQLiteResult final
+ : public Result
{
- public:
+public:
SQLiteResult(unsigned int i, const Query &q, const Anope::string &fq) : Result(i, q, fq)
{
}
@@ -38,41 +39,68 @@ class SQLiteResult : public Result
/** A SQLite database, there can be multiple
*/
-class SQLiteService : public Provider
+class SQLiteService final
+ : public Provider
{
std::map<Anope::string, std::set<Anope::string> > active_schema;
Anope::string database;
- sqlite3 *sql;
+ sqlite3 *sql = nullptr;
Anope::string Escape(const Anope::string &query);
- public:
+public:
SQLiteService(Module *o, const Anope::string &n, const Anope::string &d);
~SQLiteService();
- void Run(Interface *i, const Query &query) anope_override;
+ void Run(Interface *i, const Query &query) override;
- Result RunQuery(const Query &query);
+ Result RunQuery(const Query &query) override;
- std::vector<Query> CreateTable(const Anope::string &table, const Data &data) anope_override;
+ std::vector<Query> CreateTable(const Anope::string &table, const Data &data) override;
- Query BuildInsert(const Anope::string &table, unsigned int id, Data &data);
+ Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) override;
- Query GetTables(const Anope::string &prefix);
+ Query GetTables(const Anope::string &prefix) override;
Anope::string BuildQuery(const Query &q);
- Anope::string FromUnixtime(time_t);
+ Anope::string FromUnixtime(time_t) override;
+
+ Anope::string GetColumnType(Serialize::DataType dt)
+ {
+ switch (dt)
+ {
+ case Serialize::DataType::BOOL:
+ return "INTEGER";
+
+ case Serialize::DataType::FLOAT:
+ return "REAL";
+
+ case Serialize::DataType::INT:
+ return "INTEGER";
+
+ case Serialize::DataType::TEXT:
+ return "TEXT";
+
+ // SQLite lacks support for 64-bit unsigned integers so we have to
+ // store them as text columns instead.
+ case Serialize::DataType::UINT:
+ return "TEXT";
+ }
+
+ return "TEXT"; // Should never be reached
+ }
};
-class ModuleSQLite : public Module
+class ModuleSQLite final
+ : public Module
{
/* SQL connections */
std::map<Anope::string, SQLiteService *> SQLiteServices;
- public:
+public:
ModuleSQLite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
}
@@ -84,7 +112,7 @@ class ModuleSQLite : public Module
SQLiteServices.clear();
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
@@ -115,11 +143,10 @@ class ModuleSQLite : public Module
if (this->SQLiteServices.find(connname) == this->SQLiteServices.end())
{
- Anope::string database = Anope::DataDir + "/" + block->Get<const Anope::string>("database", "anope");
-
+ auto database = Anope::ExpandData(block->Get<const Anope::string>("database", "anope"));
try
{
- SQLiteService *ss = new SQLiteService(this, connname, database);
+ auto *ss = new SQLiteService(this, connname, database);
this->SQLiteServices[connname] = ss;
Log(LOG_NORMAL, "sqlite") << "SQLite: Successfully added database " << database;
@@ -134,7 +161,7 @@ class ModuleSQLite : public Module
};
SQLiteService::SQLiteService(Module *o, const Anope::string &n, const Anope::string &d)
-: Provider(o, n), database(d), sql(NULL)
+: Provider(o, n), database(d)
{
int db = sqlite3_open_v2(database.c_str(), &this->sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
if (db != SQLITE_OK)
@@ -200,7 +227,12 @@ Result SQLiteService::RunQuery(const Query &query)
if (err != SQLITE_DONE)
return SQLiteResult(query, real_query, sqlite3_errmsg(this->sql));
+ // GCC and clang disagree about whether this should be a move >:(
+#ifdef __clang__
+ return std::move(result);
+#else
return result;
+#endif
}
std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const Data &data)
@@ -210,14 +242,14 @@ std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const
if (known_cols.empty())
{
- Log(LOG_DEBUG) << "m_sqlite: Fetching columns for " << table;
+ Log(LOG_DEBUG) << "sqlite: Fetching columns for " << table;
Result columns = this->RunQuery("PRAGMA table_info(" + table + ")");
for (int i = 0; i < columns.Rows(); ++i)
{
const Anope::string &column = columns.Get(i, "name");
- Log(LOG_DEBUG) << "m_sqlite: Column #" << i << " for " << table << ": " << column;
+ Log(LOG_DEBUG) << "sqlite: Column #" << i << " for " << table << ": " << column;
known_cols.insert(column);
}
}
@@ -226,15 +258,11 @@ std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const
{
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` INTEGER PRIMARY KEY, `timestamp` timestamp DEFAULT CURRENT_TIMESTAMP";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (const auto &[column, _] : data.data)
{
- known_cols.insert(it->first);
+ known_cols.insert(column);
- query_text += ", `" + it->first + "` ";
- if (data.GetType(it->first) == Serialize::Data::DT_INT)
- query_text += "int(11)";
- else
- query_text += "text";
+ query_text += ", `" + column + "` " + GetColumnType(data.GetType(column));
}
query_text += ")";
@@ -251,21 +279,19 @@ std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const
queries.push_back(query_text);
}
else
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ {
+ for (const auto &[column, _] : data.data)
{
- if (known_cols.count(it->first) > 0)
+ if (known_cols.count(column) > 0)
continue;
- known_cols.insert(it->first);
+ known_cols.insert(column);
- Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
- if (data.GetType(it->first) == Serialize::Data::DT_INT)
- query_text += "int(11)";
- else
- query_text += "text";
+ Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumnType(data.GetType(column));;
queries.push_back(query_text);
}
+ }
return queries;
}
@@ -273,31 +299,58 @@ std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const
Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Data &data)
{
/* Empty columns not present in the data set */
- const std::set<Anope::string> &known_cols = this->active_schema[table];
- for (std::set<Anope::string>::iterator it = known_cols.begin(), it_end = known_cols.end(); it != it_end; ++it)
- if (*it != "id" && *it != "timestamp" && data.data.count(*it) == 0)
- data[*it] << "";
+ for (const auto &known_col : this->active_schema[table])
+ {
+ if (known_col != "id" && known_col != "timestamp" && data.data.count(known_col) == 0)
+ data[known_col] << "";
+ }
Anope::string query_text = "REPLACE INTO `" + table + "` (";
if (id > 0)
query_text += "`id`,";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += "`" + it->first + "`,";
+ for (const auto &[field, _] : data.data)
+ query_text += "`" + field + "`,";
query_text.erase(query_text.length() - 1);
query_text += ") VALUES (";
if (id > 0)
- query_text += stringify(id) + ",";
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- query_text += "@" + it->first + "@,";
+ query_text += Anope::ToString(id) + ",";
+ for (const auto &[field, _] : data.data)
+ query_text += "@" + field + "@,";
query_text.erase(query_text.length() - 1);
query_text += ")";
Query query(query_text);
- for (Data::Map::const_iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
+ for (auto &[field, value] : data.data)
{
Anope::string buf;
- *it->second >> buf;
- query.SetValue(it->first, buf);
+ *value >> buf;
+
+ auto escape = true;
+ switch (data.GetType(field))
+ {
+ case Serialize::DataType::BOOL:
+ case Serialize::DataType::FLOAT:
+ case Serialize::DataType::INT:
+ {
+ if (buf.empty())
+ buf = "0";
+ escape = false;
+ break;
+ }
+
+ case Serialize::DataType::TEXT:
+ case Serialize::DataType::UINT:
+ {
+ if (buf.empty())
+ {
+ buf = "NULL";
+ escape = false;
+ }
+ break;
+ }
+ }
+
+ query.SetValue(field, buf, escape);
}
return query;
@@ -320,15 +373,15 @@ Anope::string SQLiteService::BuildQuery(const Query &q)
{
Anope::string real_query = q.query;
- for (std::map<Anope::string, QueryData>::const_iterator it = q.parameters.begin(), it_end = q.parameters.end(); it != it_end; ++it)
- real_query = real_query.replace_all_cs("@" + it->first + "@", (it->second.escape ? ("'" + this->Escape(it->second.data) + "'") : it->second.data));
+ for (const auto &[name, value] : q.parameters)
+ real_query = real_query.replace_all_cs("@" + name + "@", (value.escape ? ("'" + this->Escape(value.data) + "'") : value.data));
return real_query;
}
Anope::string SQLiteService::FromUnixtime(time_t t)
{
- return "datetime('" + stringify(t) + "', 'unixepoch')";
+ return "datetime('" + Anope::ToString(t) + "', 'unixepoch')";
}
MODULE_INIT(ModuleSQLite)
diff --git a/modules/extra/m_ssl_gnutls.cpp b/modules/extra/ssl_gnutls.cpp
index 45f4276d1..338cc91c1 100644
--- a/modules/extra/m_ssl_gnutls.cpp
+++ b/modules/extra/ssl_gnutls.cpp
@@ -22,22 +22,24 @@ static GnuTLSModule *me;
namespace GnuTLS { class X509CertCredentials; }
-class MySSLService : public SSLService
+class MySSLService final
+ : public SSLService
{
- public:
+public:
MySSLService(Module *o, const Anope::string &n);
/** Initialize a socket to use SSL
* @param s The socket
*/
- void Init(Socket *s) anope_override;
+ void Init(Socket *s) override;
};
-class SSLSocketIO : public SocketIO
+class SSLSocketIO final
+ : public SocketIO
{
- public:
- gnutls_session_t sess;
- GnuTLS::X509CertCredentials* mycreds;
+public:
+ gnutls_session_t sess = nullptr;
+ GnuTLS::X509CertCredentials *mycreds;
/** Constructor
*/
@@ -49,61 +51,61 @@ class SSLSocketIO : public SocketIO
* @param sz How much to read
* @return Number of bytes received
*/
- int Recv(Socket *s, char *buf, size_t sz) anope_override;
+ ssize_t Recv(Socket *s, char *buf, size_t sz) override;
/** Write something to the socket
* @param s The socket
* @param buf The data to write
* @param size The length of the data
*/
- int Send(Socket *s, const char *buf, size_t sz) anope_override;
+ ssize_t Send(Socket *s, const char *buf, size_t sz) override;
/** Accept a connection from a socket
* @param s The socket
* @return The new socket
*/
- ClientSocket *Accept(ListenSocket *s) anope_override;
+ ClientSocket *Accept(ListenSocket *s) override;
/** Finished accepting a connection from a socket
* @param s The socket
* @return SF_ACCEPTED if accepted, SF_ACCEPTING if still in process, SF_DEAD on error
*/
- SocketFlag FinishAccept(ClientSocket *cs) anope_override;
+ SocketFlag FinishAccept(ClientSocket *cs) override;
/** Connect the socket
* @param s THe socket
* @param target IP to connect to
* @param port to connect to
*/
- void Connect(ConnectionSocket *s, const Anope::string &target, int port) anope_override;
+ void Connect(ConnectionSocket *s, const Anope::string &target, int port) override;
/** Called to potentially finish a pending connection
* @param s The socket
* @return SF_CONNECTED on success, SF_CONNECTING if still pending, and SF_DEAD on error.
*/
- SocketFlag FinishConnect(ConnectionSocket *s) anope_override;
+ SocketFlag FinishConnect(ConnectionSocket *s) override;
/** Called when the socket is destructing
*/
- void Destroy() anope_override;
+ void Destroy() override;
};
namespace GnuTLS
{
- class Init
+ class Init final
{
- public:
+ public:
Init() { gnutls_global_init(); }
~Init() { gnutls_global_deinit(); }
};
/** Used to create a gnutls_datum_t* from an Anope::string
*/
- class Datum
+ class Datum final
{
gnutls_datum_t datum;
- public:
+ public:
Datum(const Anope::string &dat)
{
datum.data = reinterpret_cast<unsigned char *>(const_cast<char *>(dat.data()));
@@ -113,13 +115,11 @@ namespace GnuTLS
const gnutls_datum_t *get() const { return &datum; }
};
- class DHParams
+ class DHParams final
{
- gnutls_dh_params_t dh_params;
-
- public:
- DHParams() : dh_params(NULL) { }
+ gnutls_dh_params_t dh_params = nullptr;
+ public:
void Import(const Anope::string &dhstr)
{
if (dh_params != NULL)
@@ -150,13 +150,13 @@ namespace GnuTLS
gnutls_dh_params_t get() const { return dh_params; }
};
- class X509Key
+ class X509Key final
{
/** Ensure that the key is deinited in case the constructor of X509Key throws
*/
- class RAIIKey
+ class RAIIKey final
{
- public:
+ public:
gnutls_x509_privkey_t key;
RAIIKey()
@@ -172,7 +172,7 @@ namespace GnuTLS
}
} key;
- public:
+ public:
/** Import */
X509Key(const Anope::string &keystr)
{
@@ -181,14 +181,14 @@ namespace GnuTLS
throw ConfigException("Error loading private key: " + Anope::string(gnutls_strerror(ret)));
}
- gnutls_x509_privkey_t& get() { return key.key; }
+ gnutls_x509_privkey_t &get() { return key.key; }
};
- class X509CertList
+ class X509CertList final
{
std::vector<gnutls_x509_crt_t> certs;
- public:
+ public:
/** Import */
X509CertList(const Anope::string &certstr)
{
@@ -219,13 +219,13 @@ namespace GnuTLS
gnutls_x509_crt_deinit(*i);
}
- gnutls_x509_crt_t* raw() { return &certs[0]; }
+ gnutls_x509_crt_t *raw() { return &certs[0]; }
unsigned int size() const { return certs.size(); }
};
- class X509CertCredentials
+ class X509CertCredentials final
{
- unsigned int refcount;
+ unsigned int refcount = 0;
gnutls_certificate_credentials_t cred;
DHParams dh;
@@ -236,18 +236,14 @@ namespace GnuTLS
return ret;
}
- #if (GNUTLS_VERSION_MAJOR < 2 || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 12))
- static int cert_callback(gnutls_session_t sess, const gnutls_datum_t* req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t* sign_algos, int sign_algos_length, gnutls_retr_st* st);
- #else
- static int cert_callback(gnutls_session_t sess, const gnutls_datum_t* req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t* sign_algos, int sign_algos_length, gnutls_retr2_st* st);
- #endif
+ static int cert_callback(gnutls_session_t sess, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *sign_algos, int sign_algos_length, gnutls_retr2_st *st);
- public:
+ public:
X509CertList certs;
X509Key key;
X509CertCredentials(const Anope::string &certfile, const Anope::string &keyfile)
- : refcount(0), certs(LoadFile(certfile)), key(LoadFile(keyfile))
+ : certs(LoadFile(certfile)), key(LoadFile(keyfile))
{
if (gnutls_certificate_allocate_credentials(&cred) < 0)
throw ConfigException("Cannot allocate certificate credentials");
@@ -259,11 +255,7 @@ namespace GnuTLS
throw ConfigException("Unable to set cert/key pair");
}
- #if (GNUTLS_VERSION_MAJOR < 2 || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 12))
- gnutls_certificate_client_set_retrieve_function(cred, cert_callback);
- #else
gnutls_certificate_set_retrieve_function(cred, cert_callback);
- #endif
}
~X509CertCredentials()
@@ -294,15 +286,16 @@ namespace GnuTLS
};
}
-class GnuTLSModule : public Module
+class GnuTLSModule final
+ : public Module
{
GnuTLS::Init libinit;
- public:
- GnuTLS::X509CertCredentials *cred;
+public:
+ GnuTLS::X509CertCredentials *cred = nullptr;
MySSLService service;
- GnuTLSModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), cred(NULL), service(this, "ssl")
+ GnuTLSModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), service(this, "ssl")
{
me = this;
this->SetPermanent(true);
@@ -325,20 +318,20 @@ class GnuTLSModule : public Module
static void CheckFile(const Anope::string &filename)
{
- if (!Anope::IsFile(filename.c_str()))
+ if (!Anope::IsFile(filename))
{
Log() << "File does not exist: " << filename;
throw ConfigException("Error loading certificate/private key");
}
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
- const Anope::string certfile = config->Get<const Anope::string>("cert", "data/anope.crt");
- const Anope::string keyfile = config->Get<const Anope::string>("key", "data/anope.key");
- const Anope::string dhfile = config->Get<const Anope::string>("dh", "data/dhparams.pem");
+ const Anope::string certfile = Anope::ExpandConfig(config->Get<const Anope::string>("cert", "fullchain.pem"));
+ const Anope::string keyfile = Anope::ExpandConfig(config->Get<const Anope::string>("key", "privkey.pem"));
+ const Anope::string dhfile = Anope::ExpandConfig(config->Get<const Anope::string>("dh", "dhparams.pem"));
CheckFile(certfile);
CheckFile(keyfile);
@@ -346,7 +339,7 @@ class GnuTLSModule : public Module
GnuTLS::X509CertCredentials *newcred = new GnuTLS::X509CertCredentials(certfile, keyfile);
// DH params is not mandatory
- if (Anope::IsFile(dhfile.c_str()))
+ if (Anope::IsFile(dhfile))
{
try
{
@@ -357,7 +350,7 @@ class GnuTLSModule : public Module
delete newcred;
throw;
}
- Log(LOG_DEBUG) << "m_ssl_gnutls: Successfully loaded DH parameters from " << dhfile;
+ Log(LOG_DEBUG) << "ssl_gnutls: Successfully loaded DH parameters from " << dhfile;
}
if (cred)
@@ -365,10 +358,10 @@ class GnuTLSModule : public Module
cred = newcred;
cred->incrref();
- Log(LOG_DEBUG) << "m_ssl_gnutls: Successfully loaded certificate " << certfile << " and private key " << keyfile;
+ Log(LOG_DEBUG) << "ssl_gnutls: Successfully loaded certificate " << certfile << " and private key " << keyfile;
}
- void OnPreServerConnect() anope_override
+ void OnPreServerConnect() override
{
Configuration::Block *config = Config->GetBlock("uplink", Anope::CurrentUplink);
@@ -391,9 +384,9 @@ void MySSLService::Init(Socket *s)
s->io = new SSLSocketIO();
}
-int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
+ssize_t SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
{
- int ret = gnutls_record_recv(this->sess, buf, sz);
+ ssize_t ret = gnutls_record_recv(this->sess, buf, sz);
if (ret > 0)
TotalRead += ret;
@@ -418,9 +411,9 @@ int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
return ret;
}
-int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
+ssize_t SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
{
- int ret = gnutls_record_send(this->sess, buf, sz);
+ ssize_t ret = gnutls_record_send(this->sess, buf, sz);
if (ret > 0)
TotalWritten += ret;
@@ -535,7 +528,7 @@ void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int
s->flags[SF_CONNECTING] = s->flags[SF_CONNECTED] = false;
- s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port);
+ s->conaddr.pton(s->GetFamily(), target, port);
int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size());
if (c == -1)
{
@@ -630,21 +623,15 @@ void SSLSocketIO::Destroy()
delete this;
}
-SSLSocketIO::SSLSocketIO() : sess(NULL), mycreds(me->cred)
+SSLSocketIO::SSLSocketIO() : mycreds(me->cred)
{
mycreds->incrref();
}
-#if (GNUTLS_VERSION_MAJOR < 2 || (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 12))
-int GnuTLS::X509CertCredentials::cert_callback(gnutls_session_t sess, const gnutls_datum_t* req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t* sign_algos, int sign_algos_length, gnutls_retr_st* st)
-{
- st->type = GNUTLS_CRT_X509;
-#else
-int GnuTLS::X509CertCredentials::cert_callback(gnutls_session_t sess, const gnutls_datum_t* req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t* sign_algos, int sign_algos_length, gnutls_retr2_st* st)
+int GnuTLS::X509CertCredentials::cert_callback(gnutls_session_t sess, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *sign_algos, int sign_algos_length, gnutls_retr2_st *st)
{
st->cert_type = GNUTLS_CRT_X509;
st->key_type = GNUTLS_PRIVKEY_X509;
-#endif
st->ncerts = me->cred->certs.size();
st->cert.x509 = me->cred->certs.raw();
st->key.x509 = me->cred->key.get();
diff --git a/modules/extra/m_ssl_openssl.cpp b/modules/extra/ssl_openssl.cpp
index c436c2bb0..45ea0714d 100644
--- a/modules/extra/m_ssl_openssl.cpp
+++ b/modules/extra/ssl_openssl.cpp
@@ -12,7 +12,9 @@
#include "module.h"
#include "modules/ssl.h"
-#define OPENSSL_NO_SHA512
+#define OPENSSL_API_COMPAT 0x10100000L
+#define OPENSSL_NO_DEPRECATED
+
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
@@ -21,20 +23,22 @@
static SSL_CTX *server_ctx, *client_ctx;
-class MySSLService : public SSLService
+class MySSLService final
+ : public SSLService
{
- public:
+public:
MySSLService(Module *o, const Anope::string &n);
/** Initialize a socket to use SSL
* @param s The socket
*/
- void Init(Socket *s) anope_override;
+ void Init(Socket *s) override;
};
-class SSLSocketIO : public SocketIO
+class SSLSocketIO final
+ : public SocketIO
{
- public:
+public:
/* The SSL socket for this socket */
SSL *sslsock;
@@ -48,52 +52,53 @@ class SSLSocketIO : public SocketIO
* @param sz How much to read
* @return Number of bytes received
*/
- int Recv(Socket *s, char *buf, size_t sz) anope_override;
+ ssize_t Recv(Socket *s, char *buf, size_t sz) override;
/** Write something to the socket
* @param s The socket
* @param buf The data to write
* @param size The length of the data
*/
- int Send(Socket *s, const char *buf, size_t sz) anope_override;
+ ssize_t Send(Socket *s, const char *buf, size_t sz) override;
/** Accept a connection from a socket
* @param s The socket
* @return The new socket
*/
- ClientSocket *Accept(ListenSocket *s) anope_override;
+ ClientSocket *Accept(ListenSocket *s) override;
/** Finished accepting a connection from a socket
* @param s The socket
* @return SF_ACCEPTED if accepted, SF_ACCEPTING if still in process, SF_DEAD on error
*/
- SocketFlag FinishAccept(ClientSocket *cs) anope_override;
+ SocketFlag FinishAccept(ClientSocket *cs) override;
/** Connect the socket
* @param s THe socket
* @param target IP to connect to
* @param port to connect to
*/
- void Connect(ConnectionSocket *s, const Anope::string &target, int port) anope_override;
+ void Connect(ConnectionSocket *s, const Anope::string &target, int port) override;
/** Called to potentially finish a pending connection
* @param s The socket
* @return SF_CONNECTED on success, SF_CONNECTING if still pending, and SF_DEAD on error.
*/
- SocketFlag FinishConnect(ConnectionSocket *s) anope_override;
+ SocketFlag FinishConnect(ConnectionSocket *s) override;
/** Called when the socket is destructing
*/
- void Destroy() anope_override;
+ void Destroy() override;
};
class SSLModule;
static SSLModule *me;
-class SSLModule : public Module
+class SSLModule final
+ : public Module
{
Anope::string certfile, keyfile;
- public:
+public:
MySSLService service;
SSLModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), service(this, "ssl")
@@ -102,16 +107,15 @@ class SSLModule : public Module
this->SetPermanent(true);
- SSL_library_init();
- SSL_load_error_strings();
+ OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, nullptr);
- client_ctx = SSL_CTX_new(SSLv23_client_method());
- server_ctx = SSL_CTX_new(SSLv23_server_method());
+ client_ctx = SSL_CTX_new(TLS_client_method());
+ server_ctx = SSL_CTX_new(TLS_server_method());
if (!client_ctx || !server_ctx)
throw ModuleException("Error initializing SSL CTX");
- long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE;
+ long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE;
SSL_CTX_set_options(client_ctx, opts);
SSL_CTX_set_options(server_ctx, opts);
@@ -138,55 +142,74 @@ class SSLModule : public Module
SSL_CTX_free(server_ctx);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
- this->certfile = config->Get<const Anope::string>("cert", "data/anope.crt");
- this->keyfile = config->Get<const Anope::string>("key", "data/anope.key");
+ this->certfile = Anope::ExpandConfig(config->Get<const Anope::string>("cert", "fullchain.pem"));
+ this->keyfile = Anope::ExpandConfig(config->Get<const Anope::string>("key", "privkey.pem"));
- if (Anope::IsFile(this->certfile.c_str()))
+ if (Anope::IsFile(this->certfile))
{
if (!SSL_CTX_use_certificate_chain_file(client_ctx, this->certfile.c_str()) || !SSL_CTX_use_certificate_chain_file(server_ctx, this->certfile.c_str()))
throw ConfigException("Error loading certificate");
else
- Log(LOG_DEBUG) << "m_ssl_openssl: Successfully loaded certificate " << this->certfile;
+ Log(LOG_DEBUG) << "ssl_openssl: Successfully loaded certificate " << this->certfile;
}
else
Log() << "Unable to open certificate " << this->certfile;
- if (Anope::IsFile(this->keyfile.c_str()))
+ if (Anope::IsFile(this->keyfile))
{
if (!SSL_CTX_use_PrivateKey_file(client_ctx, this->keyfile.c_str(), SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(server_ctx, this->keyfile.c_str(), SSL_FILETYPE_PEM))
throw ConfigException("Error loading private key");
else
- Log(LOG_DEBUG) << "m_ssl_openssl: Successfully loaded private key " << this->keyfile;
+ Log(LOG_DEBUG) << "ssl_openssl: Successfully loaded private key " << this->keyfile;
}
else
{
- if (Anope::IsFile(this->certfile.c_str()))
+ if (Anope::IsFile(this->certfile))
throw ConfigException("Error loading private key " + this->keyfile + " - file not found");
else
Log() << "Unable to open private key " << this->keyfile;
}
- // Allow disabling SSLv3
- if (!config->Get<Anope::string>("sslv3").empty())
+ // Allow disabling old versions of TLS
+ if (config->Get<bool>("tlsv10", "false"))
{
- if (config->Get<bool>("sslv3"))
- {
- SSL_CTX_clear_options(client_ctx, SSL_OP_NO_SSLv3);
- SSL_CTX_clear_options(server_ctx, SSL_OP_NO_SSLv3);
- }
- else
- {
- SSL_CTX_set_options(client_ctx, SSL_OP_NO_SSLv3);
- SSL_CTX_set_options(server_ctx, SSL_OP_NO_SSLv3);
- }
+ SSL_CTX_clear_options(client_ctx, SSL_OP_NO_TLSv1);
+ SSL_CTX_clear_options(server_ctx, SSL_OP_NO_TLSv1);
+ }
+ else
+ {
+ SSL_CTX_set_options(client_ctx, SSL_OP_NO_TLSv1);
+ SSL_CTX_set_options(server_ctx, SSL_OP_NO_TLSv1);
+ }
+
+ if (config->Get<bool>("tlsv11", "true"))
+ {
+ SSL_CTX_clear_options(client_ctx, SSL_OP_NO_TLSv1_1);
+ SSL_CTX_clear_options(server_ctx, SSL_OP_NO_TLSv1_1);
+ }
+ else
+ {
+ SSL_CTX_set_options(client_ctx, SSL_OP_NO_TLSv1_1);
+ SSL_CTX_set_options(server_ctx, SSL_OP_NO_TLSv1_1);
+ }
+
+ if (config->Get<bool>("tlsv12", "true"))
+ {
+ SSL_CTX_clear_options(client_ctx, SSL_OP_NO_TLSv1_2);
+ SSL_CTX_clear_options(server_ctx, SSL_OP_NO_TLSv1_2);
+ }
+ else
+ {
+ SSL_CTX_set_options(client_ctx, SSL_OP_NO_TLSv1_2);
+ SSL_CTX_set_options(server_ctx, SSL_OP_NO_TLSv1_2);
}
}
- void OnPreServerConnect() anope_override
+ void OnPreServerConnect() override
{
Configuration::Block *config = Config->GetBlock("uplink", Anope::CurrentUplink);
@@ -214,7 +237,7 @@ SSLSocketIO::SSLSocketIO()
this->sslsock = NULL;
}
-int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
+ssize_t SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
{
int i = SSL_read(this->sslsock, buf, sz);
if (i > 0)
@@ -233,7 +256,7 @@ int SSLSocketIO::Recv(Socket *s, char *buf, size_t sz)
return i;
}
-int SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
+ssize_t SSLSocketIO::Send(Socket *s, const char *buf, size_t sz)
{
int i = SSL_write(this->sslsock, buf, sz);
if (i > 0)
@@ -334,7 +357,7 @@ void SSLSocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int
s->flags[SF_CONNECTING] = s->flags[SF_CONNECTED] = false;
- s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port);
+ s->conaddr.pton(s->GetFamily(), target, port);
int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size());
if (c == -1)
{
diff --git a/modules/extra/stats/irc2sql/irc2sql.h b/modules/extra/stats/irc2sql/irc2sql.h
deleted file mode 100644
index 2cabb058f..000000000
--- a/modules/extra/stats/irc2sql/irc2sql.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *
- * (C) 2013-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "module.h"
-#include "modules/sql.h"
-
-class MySQLInterface : public SQL::Interface
-{
- public:
- MySQLInterface(Module *o) : SQL::Interface(o) { }
-
- void OnResult(const SQL::Result &r) anope_override
- {
- }
-
- void OnError(const SQL::Result &r) anope_override
- {
- if (!r.GetQuery().query.empty())
- Log(LOG_DEBUG) << "m_irc2sql: Error executing query " << r.finished_query << ": " << r.GetError();
- else
- Log(LOG_DEBUG) << "m_irc2sql: Error executing query: " << r.GetError();
- }
-};
-
-class IRC2SQL : public Module
-{
- ServiceReference<SQL::Provider> sql;
- MySQLInterface sqlinterface;
- SQL::Query query;
- std::vector<Anope::string> TableList, ProcedureList, EventList;
- Anope::string prefix, GeoIPDB;
- bool quitting, introduced_myself, ctcpuser, ctcpeob, firstrun;
- BotInfo *StatServ;
- PrimitiveExtensibleItem<bool> versionreply;
-
- void RunQuery(const SQL::Query &q);
- void GetTables();
-
- bool HasTable(const Anope::string &table);
- bool HasProcedure(const Anope::string &table);
- bool HasEvent(const Anope::string &table);
-
- void CheckTables();
-
- public:
- IRC2SQL(const Anope::string &modname, const Anope::string &creator) :
- Module(modname, creator, EXTRA | VENDOR), sql("", ""), sqlinterface(this), versionreply(this, "CTCPVERSION")
- {
- firstrun = true;
- quitting = false;
- introduced_myself = false;
- }
-
- void OnShutdown() anope_override;
- void OnReload(Configuration::Conf *config) anope_override;
- void OnNewServer(Server *server) anope_override;
- void OnServerQuit(Server *server) anope_override;
- void OnUserConnect(User *u, bool &exempt) anope_override;
- void OnUserQuit(User *u, const Anope::string &msg) anope_override;
- void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override;
- void OnUserAway(User *u, const Anope::string &message) anope_override;
- void OnFingerprint(User *u) anope_override;
- void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override;
- void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) anope_override;
- void OnUserLogin(User *u) anope_override;
- void OnNickLogout(User *u) anope_override;
- void OnSetDisplayedHost(User *u) anope_override;
-
- void OnChannelCreate(Channel *c) anope_override;
- void OnChannelDelete(Channel *c) anope_override;
- void OnLeaveChannel(User *u, Channel *c) anope_override;
- void OnJoinChannel(User *u, Channel *c) anope_override;
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override;
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override;
-
- void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override;
-
- void OnBotNotice(User *u, BotInfo *bi, Anope::string &message) anope_override;
-};
diff --git a/modules/fantasy.cpp b/modules/fantasy.cpp
index 66322ec5f..82584c41e 100644
--- a/modules/fantasy.cpp
+++ b/modules/fantasy.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandBSSetFantasy : public Command
+class CommandBSSetFantasy final
+ : public Command
{
- public:
+public:
CommandBSSetFantasy(Module *creator, const Anope::string &sname = "botserv/set/fantasy") : Command(creator, sname, 2, 2)
{
- this->SetDesc(_("Enable fantaisist commands"));
+ this->SetDesc(_("Enable fantasy commands"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
const Anope::string &value = params[1];
@@ -39,7 +40,7 @@ class CommandBSSetFantasy : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -63,7 +64,7 @@ class CommandBSSetFantasy : public Command
this->OnSyntaxError(source, source.command);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -72,27 +73,28 @@ class CommandBSSetFantasy : public Command
"fantasy commands on a channel when prefixed\n"
"with one of the following fantasy characters: \002%s\002\n"
" \n"
- "Note that users wanting to use fantaisist\n"
- "commands MUST have enough access for both\n"
- "the FANTASIA and the command they are executing."),
+ "Note that users wanting to use fantasy commands\n"
+ "MUST have enough access for both the FANTASY\n"
+ "privilege and the command they are executing."),
Config->GetModule(this->owner)->Get<const Anope::string>("fantasycharacter", "!").c_str());
return true;
}
};
-class Fantasy : public Module
+class Fantasy final
+ : public Module
{
SerializableExtensibleItem<bool> fantasy;
CommandBSSetFantasy commandbssetfantasy;
- public:
+public:
Fantasy(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
fantasy(this, "BS_FANTASY"), commandbssetfantasy(this)
{
}
- void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
+ void OnPrivmsg(User *u, Channel *c, Anope::string &msg, const Anope::map<Anope::string> &tags) override
{
if (!u || !c || !c->ci || !c->ci->bi || msg.empty() || msg[0] == '\1')
return;
@@ -173,16 +175,21 @@ class Fantasy : public Module
if (params.size() < cmd->min_params)
return;
- CommandSource source(u->nick, u, u->Account(), u, c->ci->bi);
+ Anope::string msgid;
+ auto iter = tags.find("msgid");
+ if (iter != tags.end())
+ msgid = iter->second;
+
+ CommandSource source(u->nick, u, u->Account(), u, c->ci->bi, msgid);
source.c = c;
source.command = it->first;
source.permission = info.permission;
AccessGroup ag = c->ci->AccessFor(u);
- bool has_fantasia = ag.HasPriv("FANTASIA") || source.HasPriv("botserv/fantasy");
+ bool has_fantasy = ag.HasPriv("FANTASY") || source.HasPriv("botserv/fantasy");
EventReturn MOD_RESULT;
- if (has_fantasia)
+ if (has_fantasy)
{
FOREACH_RESULT(OnBotFantasy, MOD_RESULT, (source, cmd, c->ci, params));
}
@@ -191,7 +198,7 @@ class Fantasy : public Module
FOREACH_RESULT(OnBotNoFantasyAccess, MOD_RESULT, (source, cmd, c->ci, params));
}
- if (MOD_RESULT == EVENT_STOP || !has_fantasia)
+ if (MOD_RESULT == EVENT_STOP || !has_fantasy)
return;
if (MOD_RESULT != EVENT_ALLOW && !info.permission.empty() && !source.HasCommand(info.permission))
@@ -208,7 +215,7 @@ class Fantasy : public Module
FOREACH_MOD(OnPostCommand, (source, cmd, params));
}
- void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) override
{
if (fantasy.HasExt(ci))
info.AddOption(_("Fantasy"));
diff --git a/modules/global/gl_global.cpp b/modules/global/gl_global.cpp
new file mode 100644
index 000000000..a88c8080d
--- /dev/null
+++ b/modules/global/gl_global.cpp
@@ -0,0 +1,105 @@
+/* Global core functions
+ *
+ * (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"
+
+class CommandGLGlobal final
+ : public Command
+{
+private:
+ ServiceReference<GlobalService> global;
+
+ BotInfo *GetSender(CommandSource &source)
+ {
+ Reference<BotInfo> sender;
+ if (global)
+ sender = global->GetDefaultSender();
+ if (!sender)
+ sender = source.service;
+ return sender;
+ }
+
+public:
+ CommandGLGlobal(Module *creator)
+ : Command(creator, "global/global", 0, 1)
+ , global("GlobalService", "Global")
+ {
+ this->SetDesc(_("Send a message to all users"));
+ this->SetSyntax(_("[\037message\037]"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (!global)
+ {
+ source.Reply(SERVICE_UNAVAILABLE, source.service->nick.c_str());
+ return;
+ }
+
+ auto queuesize = global->CountQueue(source.nc);
+ if (!queuesize && params.empty())
+ {
+ source.Reply(GLOBAL_NO_MESSAGE);
+ return;
+ }
+
+ if (queuesize && !params.empty())
+ {
+ source.Reply(GLOBAL_QUEUE_CONFLICT);
+ return;
+ }
+
+ if (params.empty())
+ {
+ // We are sending the message queue.
+ global->SendQueue(source, GetSender(source));
+ }
+ else
+ {
+ // We are sending a single message.
+ global->SendSingle(params[0], &source, GetSender(source));
+ queuesize = 1;
+ }
+
+ Log(LOG_ADMIN, source, this) << "to send " << queuesize << " messages to all users";
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_(
+ "Allows sending messages to all users on the network. The message will be sent\n"
+ "from \002%s\002.\n"
+ "\n"
+ "You can either send a message by specifying it as a parameter or provide no\n"
+ "parameters to send a previously queued message.\n"
+ ), GetSender(source)->nick.c_str());
+ return true;
+ }
+};
+
+class GLGlobal final
+ : public Module
+{
+private:
+ CommandGLGlobal commandglglobal;
+
+public:
+ GLGlobal(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandglglobal(this)
+ {
+
+ }
+};
+
+MODULE_INIT(GLGlobal)
diff --git a/modules/global/gl_queue.cpp b/modules/global/gl_queue.cpp
new file mode 100644
index 000000000..583a46f6a
--- /dev/null
+++ b/modules/global/gl_queue.cpp
@@ -0,0 +1,208 @@
+/* Global core functions
+ *
+ * (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"
+
+#define QUEUE_EMPTY _("You have no messages queued.")
+
+class QueueDelCallback final
+ : public NumberList
+{
+private:
+ unsigned deleted = 0;
+ ServiceReference<GlobalService> &global;
+ CommandSource &source;
+
+public:
+ QueueDelCallback(CommandSource &src, ServiceReference<GlobalService>& gl, const Anope::string &list)
+ : NumberList(list, true)
+ , global(gl)
+ , source(src)
+ {
+ }
+
+ ~QueueDelCallback() override
+ {
+ switch (deleted)
+ {
+ case 0:
+ source.Reply(_("No matching entries in your message queue."));
+ break;
+ case 1:
+ source.Reply(_("Deleted one entry from your message queue."));
+ break;
+ default:
+ source.Reply(_("Deleted %u entries from your message queue."), deleted);
+ break;
+ }
+ }
+
+ void HandleNumber(unsigned number) override
+ {
+ if (!number || number > global->CountQueue(source.nc))
+ return;
+
+ if (global->Unqueue(source.nc, number - 1))
+ deleted++;
+ }
+};
+
+class CommandGLQueue final
+ : public Command
+{
+private:
+ ServiceReference<GlobalService> global;
+
+ void DoAdd(CommandSource &source, const Anope::string &message)
+ {
+ if (message.empty())
+ {
+ this->OnSyntaxError(source, "ADD");
+ return;
+ }
+
+ auto maxqueue = Config->GetModule(this->module)->Get<size_t>("maxqueue", "10");
+ if (global->CountQueue(source.nc) >= maxqueue)
+ {
+ source.Reply(_("You can not queue any more messages."));
+ return;
+ }
+
+ global->Queue(source.nc, message);
+ source.Reply(_("Your message has been queued."));
+ Log(LOG_ADMIN, source, this) << "to queue: " << message;
+ }
+
+ void DoClear(CommandSource &source)
+ {
+ if (!global->CountQueue(source.nc))
+ {
+ source.Reply(_("You do not have any queued messages."));
+ return;
+ }
+
+ global->ClearQueue(source.nc);
+ source.Reply(_("Your message queue has been cleared."));
+ Log(LOG_ADMIN, source, this);
+ }
+
+ void DoDel(CommandSource &source, const Anope::string &what)
+ {
+ if (what.empty())
+ {
+ this->OnSyntaxError(source, "DEL");
+ return;
+ }
+
+ if (!global->CountQueue(source.nc))
+ {
+ source.Reply(QUEUE_EMPTY);
+ return;
+ }
+
+ QueueDelCallback(source, global, what).Process();
+ }
+
+ void DoList(CommandSource &source)
+ {
+ const auto *q = global->GetQueue(source.nc);
+ if (!q || q->empty())
+ {
+ source.Reply(QUEUE_EMPTY);
+ return;
+ }
+
+ ListFormatter list(source.nc);
+ list.AddColumn(_("Number")).AddColumn(_("Message"));
+ for (size_t i = 0; i < q->size(); ++i)
+ {
+ ListFormatter::ListEntry entry;
+ entry["Number"] = Anope::ToString(i + 1);
+ entry["Message"] = (*q)[i];
+ list.AddEntry(entry);
+ }
+
+ std::vector<Anope::string> replies;
+ list.Process(replies);
+ for (const auto &reply : replies)
+ source.Reply(reply);
+ }
+
+public:
+ CommandGLQueue(Module *creator)
+ : Command(creator, "global/queue", 1, 2)
+ , global("GlobalService", "Global")
+ {
+ this->SetDesc(_("Manages your pending message queue."));
+ this->SetSyntax(_("ADD \037message\037"));
+ this->SetSyntax(_("DEL \037entry-num\037"));
+ this->SetSyntax("LIST");
+ this->SetSyntax("CLEAR");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (!global)
+ {
+ source.Reply(SERVICE_UNAVAILABLE, source.service->nick.c_str());
+ return;
+ }
+
+ const auto &cmd = params[0];
+ const auto &what = params.size() > 1 ? params[1] : "";
+ if (cmd.equals_ci("ADD"))
+ this->DoAdd(source, what);
+ else if (cmd.equals_ci("CLEAR"))
+ this->DoClear(source);
+ else if (cmd.equals_ci("DEL"))
+ this->DoDel(source, what);
+ else if (cmd.equals_ci("LIST"))
+ this->DoList(source);
+ else
+ this->OnSyntaxError(source, "");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply("");
+ source.Reply(_(
+ "Allows queueing messages to send to users on the network.\n"
+ "\n"
+ "The \002QUEUE ADD\002 command adds the given message to the message queue."
+ "\n"
+ "The \002QUEUE CLEAR\002 command clears the message queue."
+ "\n"
+ "The \002QUEUE DEL\002 command removes the specified message from the message queue. The\n"
+ "message number can be obtained from the output of the \002QUEUE LIST\002 command."
+ "\n"
+ "The \002QUEUE LIST\002 command lists all messages that are currently in the message queue."
+ ));
+ return true;
+ }
+};
+
+class GLQueue final
+ : public Module
+{
+private:
+ CommandGLQueue commandglqueue;
+
+public:
+ GLQueue(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandglqueue(this)
+ {
+
+ }
+};
+
+MODULE_INIT(GLQueue)
diff --git a/modules/global/gl_server.cpp b/modules/global/gl_server.cpp
new file mode 100644
index 000000000..4b9effdaa
--- /dev/null
+++ b/modules/global/gl_server.cpp
@@ -0,0 +1,112 @@
+/* Global core functions
+ *
+ * (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"
+
+class CommandGLServer final
+ : public Command
+{
+private:
+ ServiceReference<GlobalService> global;
+
+ BotInfo *GetSender(CommandSource &source)
+ {
+ Reference<BotInfo> sender;
+ if (global)
+ sender = global->GetDefaultSender();
+ if (!sender)
+ sender = source.service;
+ return sender;
+ }
+
+public:
+ CommandGLServer(Module *creator)
+ : Command(creator, "global/server", 1, 2)
+ , global("GlobalService", "Global")
+ {
+ this->SetDesc(_("Send a message to all users on a server"));
+ this->SetSyntax(_("\037server\037 [\037message\037]"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (!global)
+ {
+ source.Reply(SERVICE_UNAVAILABLE, source.service->nick.c_str());
+ return;
+ }
+
+ auto *server = Server::Find(params[0]);
+ if (!server || server == Me || server->IsJuped())
+ {
+ source.Reply(_("Server \002%s\002 is not linked to the network."), params[0].c_str());
+ return;
+ }
+
+ auto queuesize = global->CountQueue(source.nc);
+ if (!queuesize && params.size() < 2)
+ {
+ source.Reply(GLOBAL_NO_MESSAGE);
+ return;
+ }
+
+ if (queuesize && params.size() > 1)
+ {
+ source.Reply(GLOBAL_QUEUE_CONFLICT);
+ return;
+ }
+
+ if (params.empty())
+ {
+ // We are sending the message queue.
+ global->SendQueue(source, GetSender(source), server);
+ }
+ else
+ {
+ // We are sending a single message.
+ global->SendSingle(params[1], &source, GetSender(source), server);
+ queuesize = 1;
+ }
+
+ Log(LOG_ADMIN, source, this) << "to send " << queuesize << " messages to users on " << server->GetName();
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_(
+ "Allows sending messages to all users on a server. The message will be sent\n"
+ "from \002%s\002.\n"
+ "\n"
+ "You can either send a message by specifying it as a parameter or provide no\n"
+ "parameters to send a previously queued message.\n"
+ ), GetSender(source)->nick.c_str());
+ return true;
+ }
+};
+
+class GLServer final
+ : public Module
+{
+private:
+ CommandGLServer commandglserver;
+
+public:
+ GLServer(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandglserver(this)
+ {
+
+ }
+};
+
+MODULE_INIT(GLServer)
diff --git a/modules/global/global.cpp b/modules/global/global.cpp
new file mode 100644
index 000000000..44b17326a
--- /dev/null
+++ b/modules/global/global.cpp
@@ -0,0 +1,173 @@
+/* Global core functions
+ *
+ * (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"
+
+class GlobalCore final
+ : public Module
+ , public GlobalService
+{
+private:
+ Reference<BotInfo> global;
+ PrimitiveExtensibleItem<std::vector<Anope::string>> queue;
+
+ void ServerGlobal(BotInfo *sender, Server *server, bool children, const Anope::string &message)
+ {
+ if (server != Me && !server->IsJuped())
+ server->Notice(sender, message);
+
+ if (children)
+ {
+ for (auto *link : server->GetLinks())
+ this->ServerGlobal(sender, link, true, message);
+ }
+ }
+
+public:
+ GlobalCore(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, PSEUDOCLIENT | VENDOR)
+ , GlobalService(this)
+ , queue(this, "global-queue")
+ {
+ }
+
+ void ClearQueue(NickCore *nc) override
+ {
+ queue.Unset(nc);
+ }
+
+ Reference<BotInfo> GetDefaultSender() const override
+ {
+ return global;
+ }
+
+ const std::vector<Anope::string> *GetQueue(NickCore* nc) const override
+ {
+ return queue.Get(nc);
+ }
+
+ size_t Queue(NickCore *nc, const Anope::string &message) override
+ {
+ auto *q = queue.Require(nc);
+ q->push_back(message);
+ return q->size();
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ const auto glnick = conf->GetModule(this)->Get<const Anope::string>("client");
+ if (glnick.empty())
+ throw ConfigException(Module::name + ": <client> must be defined");
+
+ auto *bi = BotInfo::Find(glnick, true);
+ if (!bi)
+ throw ConfigException(Module::name + ": no bot named " + glnick);
+
+ global = bi;
+ }
+
+ void OnRestart() override
+ {
+ const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
+ if (!msg.empty())
+ this->SendSingle(msg, nullptr, nullptr, nullptr);
+ }
+
+ void OnShutdown() override
+ {
+ const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
+ if (!msg.empty())
+ this->SendSingle(msg, nullptr, nullptr, nullptr);
+ }
+
+ void OnNewServer(Server *s) override
+ {
+ const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycleup");
+ if (!msg.empty() && !Me->IsSynced())
+ s->Notice(global, msg);
+ }
+
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (!params.empty() || source.c || source.service != *global)
+ return EVENT_CONTINUE;
+
+ source.Reply(_("%s commands:"), global->nick.c_str());
+ return EVENT_CONTINUE;
+ }
+
+ bool SendQueue(CommandSource &source, BotInfo *sender, Server *server) override
+ {
+ // We MUST have an account.
+ if (!source.nc)
+ return false;
+
+ // We MUST have a message queue.
+ auto *q = queue.Get(source.nc);
+ if (!q || q->empty())
+ return false;
+
+ auto success = true;
+ for (const auto &message : *q)
+ {
+ if (!SendSingle(message, &source, sender, server))
+ {
+ success = false;
+ break;
+ }
+ }
+
+ queue.Unset(source.nc);
+ return success;
+ }
+
+ bool SendSingle(const Anope::string &message, CommandSource *source, BotInfo* sender, Server* server) override
+ {
+ // We MUST have a sender.
+ if (sender)
+ sender = global;
+ if (!sender)
+ return false;
+
+ Anope::string line;
+ if (source && !Config->GetModule(this)->Get<bool>("anonymousglobal"))
+ {
+ // A source is available and they're not anonymous.
+ line = Anope::printf("[%s] %s", source->GetNick().c_str(), message.c_str());
+ }
+ else
+ {
+ // A source isn't available or they're anonymous.
+ line = message.empty() ? " " : message;
+ }
+
+ if (server)
+ this->ServerGlobal(sender, server, false, line);
+ else
+ this->ServerGlobal(sender, Servers::GetUplink(), true, line);
+ return true;
+ }
+
+ bool Unqueue(NickCore *nc, size_t idx) override
+ {
+ auto *q = queue.Get(nc);
+ if (!q || idx > q->size())
+ return false;
+
+ q->erase(q->begin() + idx);
+ if (q->empty())
+ queue.Unset(nc);
+
+ return true;
+ }
+};
+
+MODULE_INIT(GlobalCore)
diff --git a/modules/commands/greet.cpp b/modules/greet.cpp
index 5cb48e834..9f620d9cb 100644
--- a/modules/commands/greet.cpp
+++ b/modules/greet.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandBSSetGreet : public Command
+class CommandBSSetGreet final
+ : public Command
{
- public:
+public:
CommandBSSetGreet(Module *creator, const Anope::string &sname = "botserv/set/greet") : Command(creator, sname, 2, 2)
{
this->SetDesc(_("Enable greet messages"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
ChannelInfo *ci = ChannelInfo::Find(params[0]);
const Anope::string &value = params[1];
@@ -63,7 +64,7 @@ class CommandBSSetGreet : public Command
this->OnSyntaxError(source, source.command);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(_(" \n"
@@ -75,9 +76,10 @@ class CommandBSSetGreet : public Command
}
};
-class CommandNSSetGreet : public Command
+class CommandNSSetGreet
+ : public Command
{
- public:
+public:
CommandNSSetGreet(Module *creator, const Anope::string &sname = "nickserv/set/greet", size_t min = 0) : Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Associate a greet message with your nickname"));
@@ -119,12 +121,12 @@ class CommandNSSetGreet : public Command
}
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, params.size() > 0 ? params[0] : "");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -136,21 +138,22 @@ class CommandNSSetGreet : public Command
}
};
-class CommandNSSASetGreet : public CommandNSSetGreet
+class CommandNSSASetGreet final
+ : public CommandNSSetGreet
{
- public:
+public:
CommandNSSASetGreet(Module *creator) : CommandNSSetGreet(creator, "nickserv/saset/greet", 1)
{
this->ClearSyntax();
this->SetSyntax(_("\037nickname\037 \037message\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, params[0], params.size() > 1 ? params[1] : "");
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -162,7 +165,8 @@ class CommandNSSASetGreet : public CommandNSSetGreet
}
};
-class Greet : public Module
+class Greet final
+ : public Module
{
/* channel setting for whether or not greet should be shown */
SerializableExtensibleItem<bool> bs_greet;
@@ -173,7 +177,7 @@ class Greet : public Module
CommandNSSetGreet commandnssetgreet;
CommandNSSASetGreet commandnssasetgreet;
- public:
+public:
Greet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
bs_greet(this, "BS_GREET"),
ns_greet(this, "greet"),
@@ -182,7 +186,7 @@ class Greet : public Module
{
}
- void OnJoinChannel(User *user, Channel *c) anope_override
+ void OnJoinChannel(User *user, Channel *c) override
{
/* Only display the greet if the main uplink we're connected
* to has synced, or we'll get greet-floods when the net
@@ -194,19 +198,20 @@ class Greet : public Module
Anope::string *greet = ns_greet.Get(user->Account());
if (bs_greet.HasExt(c->ci) && greet != NULL && !greet->empty() && c->FindUser(c->ci->bi) && c->ci->AccessFor(user).HasPriv("GREET"))
{
- IRCD->SendPrivmsg(*c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), greet->c_str());
+ const auto message = Anope::printf("[%s] %s", user->Account()->display.c_str(), greet->c_str());
+ IRCD->SendPrivmsg(*c->ci->bi, c->name, message);
c->ci->bi->lastmsg = Anope::CurTime;
}
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
{
Anope::string *greet = ns_greet.Get(na->nc);
if (greet != NULL)
info[_("Greet")] = *greet;
}
- void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) override
{
if (bs_greet.HasExt(ci))
info.AddOption(_("Greet"));
diff --git a/modules/commands/help.cpp b/modules/help.cpp
index 4dfaafe8c..117293373 100644
--- a/modules/commands/help.cpp
+++ b/modules/help.cpp
@@ -11,15 +11,15 @@
#include "module.h"
-class CommandHelp : public Command
+class CommandHelp final
+ : public Command
{
static const unsigned help_wrap_len = 40;
static CommandGroup *FindGroup(const Anope::string &name)
{
- for (unsigned i = 0; i < Config->CommandGroups.size(); ++i)
+ for (auto &gr : Config->CommandGroups)
{
- CommandGroup &gr = Config->CommandGroups[i];
if (gr.name == name)
return &gr;
}
@@ -27,14 +27,14 @@ class CommandHelp : public Command
return NULL;
}
- public:
+public:
CommandHelp(Module *creator) : Command(creator, "generic/help", 0)
{
this->SetDesc(_("Displays this list and give information about commands"));
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
EventReturn MOD_RESULT;
FOREACH_RESULT(OnPreHelp, MOD_RESULT, (source, params));
@@ -56,18 +56,15 @@ class CommandHelp : public Command
if (all)
source.Reply(_("All available commands for \002%s\002:"), source.service->nick.c_str());
- for (CommandInfo::map::const_iterator it = map.begin(), it_end = map.end(); it != it_end; ++it)
+ for (const auto &[c_name, info] : map)
{
- const Anope::string &c_name = it->first;
- const CommandInfo &info = it->second;
-
if (info.hide)
continue;
// Smaller command exists
Anope::string cmd;
spacesepstream(c_name).GetToken(cmd, 0);
- if (cmd != it->first && map.count(cmd))
+ if (cmd != c_name && map.count(cmd))
continue;
ServiceReference<Command> c("Command", info.name);
@@ -95,18 +92,14 @@ class CommandHelp : public Command
}
- for (GroupInfo::iterator it = groups.begin(), it_end = groups.end(); it != it_end; ++it)
+ for (auto &[gr, cmds] : groups)
{
- CommandGroup *gr = it->first;
-
source.Reply(" ");
source.Reply("%s", gr->description.c_str());
Anope::string buf;
- for (std::list<Anope::string>::iterator it2 = it->second.begin(), it2_end = it->second.end(); it2 != it2_end; ++it2)
+ for (const auto &c_name : cmds)
{
- const Anope::string &c_name = *it2;
-
buf += ", " + c_name;
if (buf.length() > help_wrap_len)
@@ -180,7 +173,7 @@ class CommandHelp : public Command
break;
}
- if (helped == false)
+ if (!helped)
source.Reply(_("No help available for \002%s\002."), params[0].c_str());
}
@@ -190,11 +183,12 @@ class CommandHelp : public Command
}
};
-class Help : public Module
+class Help final
+ : public Module
{
CommandHelp commandhelp;
- public:
+public:
Help(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhelp(this)
{
diff --git a/modules/m_helpchan.cpp b/modules/helpchan.cpp
index ee41b14a9..0ea427ec2 100644
--- a/modules/m_helpchan.cpp
+++ b/modules/helpchan.cpp
@@ -8,14 +8,15 @@
#include "module.h"
-class HelpChannel : public Module
+class HelpChannel final
+ : public Module
{
- public:
+public:
HelpChannel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
{
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string &param) override
{
if (mode->name == "OP" && c && c->ci && c->name.equals_ci(Config->GetModule(this)->Get<const Anope::string>("helpchannel")))
{
diff --git a/modules/hostserv/hostserv.cpp b/modules/hostserv/hostserv.cpp
new file mode 100644
index 000000000..9c8266d02
--- /dev/null
+++ b/modules/hostserv/hostserv.cpp
@@ -0,0 +1,133 @@
+/* HostServ core functions
+ *
+ * (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"
+
+class HostServCore final
+ : public Module
+{
+ Reference<BotInfo> HostServ;
+public:
+ HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
+ {
+ if (!IRCD || !IRCD->CanSetVHost)
+ throw ModuleException("Your IRCd does not support vhosts");
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ const Anope::string &hsnick = conf->GetModule(this)->Get<const Anope::string>("client");
+
+ if (hsnick.empty())
+ throw ConfigException(Module::name + ": <client> must be defined");
+
+ BotInfo *bi = BotInfo::Find(hsnick, true);
+ if (!bi)
+ throw ConfigException(Module::name + ": no bot named " + hsnick);
+
+ HostServ = bi;
+ }
+
+ void OnUserLogin(User *u) override
+ {
+ if (!IRCD->CanSetVHost)
+ return;
+
+ const NickAlias *na = NickAlias::Find(u->nick);
+ if (!na || na->nc != u->Account() || !na->HasVHost())
+ na = u->AccountNick();
+ if (!na || !na->HasVHost())
+ return;
+
+ if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVHostHost()) || (!na->GetVHostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVHostIdent())))
+ {
+ IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
+
+ u->vhost = na->GetVHostHost();
+ u->UpdateHost();
+
+ if (IRCD->CanSetVIdent && !na->GetVHostIdent().empty())
+ u->SetVIdent(na->GetVHostIdent());
+
+ if (HostServ)
+ {
+ u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."),
+ na->GetVHostMask().c_str());
+ }
+ }
+ }
+
+ void OnNickDrop(CommandSource &source, NickAlias *na) override
+ {
+ if (na->HasVHost())
+ {
+ FOREACH_MOD(OnDeleteVHost, (na));
+ na->RemoveVHost();
+ }
+ }
+
+ void OnNickUpdate(User *u) override
+ {
+ this->OnUserLogin(u);
+ }
+
+ void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override
+ {
+ if (mname == "OPER" && Config->GetModule(this)->Get<bool>("activate_on_deoper", "yes"))
+ this->OnUserLogin(u);
+ }
+
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (!params.empty() || source.c || source.service != *HostServ)
+ return EVENT_CONTINUE;
+ source.Reply(_("%s commands:"), HostServ->nick.c_str());
+ return EVENT_CONTINUE;
+ }
+
+ void OnSetVHost(NickAlias *na) override
+ {
+ if (Config->GetModule(this)->Get<bool>("activate_on_set", "yes"))
+ {
+ User *u = User::Find(na->nick);
+
+ if (u && u->Account() == na->nc)
+ {
+ IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
+
+ u->vhost = na->GetVHostHost();
+ u->UpdateHost();
+
+ if (IRCD->CanSetVIdent && !na->GetVHostIdent().empty())
+ u->SetVIdent(na->GetVHostIdent());
+
+ if (HostServ)
+ {
+ u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."),
+ na->GetVHostMask().c_str());
+ }
+ }
+ }
+ }
+
+ void OnDeleteVHost(NickAlias *na) override
+ {
+ if (Config->GetModule(this)->Get<bool>("activate_on_set", "yes"))
+ {
+ User *u = User::Find(na->nick);
+
+ if (u && u->Account() == na->nc)
+ IRCD->SendVHostDel(u);
+ }
+ }
+};
+
+MODULE_INIT(HostServCore)
diff --git a/modules/commands/hs_del.cpp b/modules/hostserv/hs_del.cpp
index 61979c170..357f4f8e3 100644
--- a/modules/commands/hs_del.cpp
+++ b/modules/hostserv/hs_del.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandHSDel : public Command
+class CommandHSDel final
+ : public Command
{
- public:
+public:
CommandHSDel(Module *creator) : Command(creator, "hostserv/del", 1, 1)
{
this->SetDesc(_("Delete the vhost of another user"));
this->SetSyntax(_("\037nick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -33,15 +34,15 @@ class CommandHSDel : public Command
if (na)
{
Log(LOG_ADMIN, source, this) << "for user " << na->nick;
- FOREACH_MOD(OnDeleteVhost, (na));
- na->RemoveVhost();
- source.Reply(_("Vhost for \002%s\002 removed."), nick.c_str());
+ FOREACH_MOD(OnDeleteVHost, (na));
+ na->RemoveVHost();
+ source.Reply(_("VHost for \002%s\002 removed."), nick.c_str());
}
else
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -51,16 +52,17 @@ class CommandHSDel : public Command
}
};
-class CommandHSDelAll : public Command
+class CommandHSDelAll final
+ : public Command
{
- public:
+public:
CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1)
{
this->SetDesc(_("Deletes the vhost for all nicks in a group"));
this->SetSyntax(_("\037nick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -72,21 +74,21 @@ class CommandHSDelAll : public Command
NickAlias *na = NickAlias::Find(nick);
if (na)
{
- FOREACH_MOD(OnDeleteVhost, (na));
+ FOREACH_MOD(OnDeleteVHost, (na));
const NickCore *nc = na->nc;
- for (unsigned i = 0; i < nc->aliases->size(); ++i)
+ for (auto *alias : *nc->aliases)
{
- na = nc->aliases->at(i);
- na->RemoveVhost();
+ na = alias;
+ na->RemoveVHost();
}
Log(LOG_ADMIN, source, this) << "for all nicks in group " << nc->display;
- source.Reply(_("vhosts for group \002%s\002 have been removed."), nc->display.c_str());
+ source.Reply(_("VHosts for group \002%s\002 have been removed."), nc->display.c_str());
}
else
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -96,12 +98,13 @@ class CommandHSDelAll : public Command
}
};
-class HSDel : public Module
+class HSDel final
+ : public Module
{
CommandHSDel commandhsdel;
CommandHSDelAll commandhsdelall;
- public:
+public:
HSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhsdel(this), commandhsdelall(this)
{
diff --git a/modules/commands/hs_group.cpp b/modules/hostserv/hs_group.cpp
index a83c09b1f..06c29290e 100644
--- a/modules/commands/hs_group.cpp
+++ b/modules/hostserv/hs_group.cpp
@@ -11,38 +11,38 @@
#include "module.h"
-class CommandHSGroup : public Command
+class CommandHSGroup final
+ : public Command
{
- bool setting;
+ bool setting = false;
- public:
+public:
void Sync(const NickAlias *na)
{
if (setting)
return;
- if (!na || !na->HasVhost())
+ if (!na || !na->HasVHost())
return;
setting = true;
- for (unsigned i = 0; i < na->nc->aliases->size(); ++i)
+ for (auto *nick : *na->nc->aliases)
{
- NickAlias *nick = na->nc->aliases->at(i);
if (nick && nick != na)
{
- nick->SetVhost(na->GetVhostIdent(), na->GetVhostHost(), na->GetVhostCreator());
- FOREACH_MOD(OnSetVhost, (nick));
+ nick->SetVHost(na->GetVHostIdent(), na->GetVHostHost(), na->GetVHostCreator());
+ FOREACH_MOD(OnSetVHost, (nick));
}
}
setting = false;
}
- CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0), setting(false)
+ CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0)
{
this->SetDesc(_("Syncs the vhost for all nicks in a group"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -51,13 +51,11 @@ class CommandHSGroup : public Command
}
NickAlias *na = NickAlias::Find(source.GetNick());
- if (na && source.GetAccount() == na->nc && na->HasVhost())
+ if (na && source.GetAccount() == na->nc && na->HasVHost())
{
this->Sync(na);
- if (!na->GetVhostIdent().empty())
- source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002@\002%s\002."), source.nc->display.c_str(), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
- else
- source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002."), source.nc->display.c_str(), na->GetVhostHost().c_str());
+ source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002."),
+ source.nc->display.c_str(), na->GetVHostMask().c_str());
}
else
source.Reply(HOST_NOT_ASSIGNED);
@@ -65,7 +63,7 @@ class CommandHSGroup : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -76,13 +74,14 @@ class CommandHSGroup : public Command
}
};
-class HSGroup : public Module
+class HSGroup final
+ : public Module
{
CommandHSGroup commandhsgroup;
bool syncongroup;
bool synconset;
- public:
+public:
HSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhsgroup(this)
{
@@ -90,7 +89,7 @@ class HSGroup : public Module
throw ModuleException("Your IRCd does not support vhosts");
}
- void OnSetVhost(NickAlias *na) anope_override
+ void OnSetVHost(NickAlias *na) override
{
if (!synconset)
return;
@@ -98,7 +97,7 @@ class HSGroup : public Module
commandhsgroup.Sync(na);
}
- void OnNickGroup(User *u, NickAlias *na) anope_override
+ void OnNickGroup(User *u, NickAlias *na) override
{
if (!syncongroup)
return;
@@ -106,7 +105,7 @@ class HSGroup : public Module
commandhsgroup.Sync(na);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
syncongroup = block->Get<bool>("syncongroup");
diff --git a/modules/commands/hs_list.cpp b/modules/hostserv/hs_list.cpp
index 4a9619f7e..345d62852 100644
--- a/modules/commands/hs_list.cpp
+++ b/modules/hostserv/hs_list.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandHSList : public Command
+class CommandHSList final
+ : public Command
{
- public:
+public:
CommandHSList(Module *creator) : Command(creator, "hostserv/list", 0, 1)
{
this->SetDesc(_("Displays one or more vhost entries"));
this->SetSyntax(_("[\037key\037|\037#X-Y\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &key = !params.empty() ? params[0] : "";
int from = 0, to = 0, counter = 1;
@@ -44,41 +45,33 @@ class CommandHSList : public Command
source.Reply(LIST_INCORRECT_RANGE);
return;
}
- try
- {
- from = convertTo<int>(key.substr(1, tmp - 1));
- to = convertTo<int>(key.substr(tmp + 1));
- }
- catch (const ConvertException &) { }
+
+ from = Anope::Convert<int>(key.substr(1, tmp - 1), 0);
+ to = Anope::Convert<int>(key.substr(tmp + 1), 0);
}
}
unsigned display_counter = 0, listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50");
ListFormatter list(source.GetAccount());
- list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Creator")).AddColumn(_("Created"));
+ list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("VHost")).AddColumn(_("Creator")).AddColumn(_("Created"));
- for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
+ for (const auto &[_, na] : *NickAliasList)
{
- const NickAlias *na = it->second;
-
- if (!na->HasVhost())
+ if (!na->HasVHost())
continue;
if (!key.empty() && key[0] != '#')
{
- if ((Anope::Match(na->nick, key) || Anope::Match(na->GetVhostHost(), key)) && display_counter < listmax)
+ if ((Anope::Match(na->nick, key) || Anope::Match(na->GetVHostHost(), key)) && display_counter < listmax)
{
++display_counter;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(display_counter);
+ entry["Number"] = Anope::ToString(display_counter);
entry["Nick"] = na->nick;
- if (!na->GetVhostIdent().empty())
- entry["Vhost"] = na->GetVhostIdent() + "@" + na->GetVhostHost();
- else
- entry["Vhost"] = na->GetVhostHost();
- entry["Creator"] = na->GetVhostCreator();
- entry["Created"] = Anope::strftime(na->GetVhostCreated(), NULL, true);
+ entry["VHost"] = na->GetVHostMask();
+ entry["Creator"] = na->GetVHostCreator();
+ entry["Created"] = Anope::strftime(na->GetVHostCreated(), NULL, true);
list.AddEntry(entry);
}
}
@@ -92,14 +85,11 @@ class CommandHSList : public Command
{
++display_counter;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(display_counter);
+ entry["Number"] = Anope::ToString(display_counter);
entry["Nick"] = na->nick;
- if (!na->GetVhostIdent().empty())
- entry["Vhost"] = na->GetVhostIdent() + "@" + na->GetVhostHost();
- else
- entry["Vhost"] = na->GetVhostHost();
- entry["Creator"] = na->GetVhostCreator();
- entry["Created"] = Anope::strftime(na->GetVhostCreated(), NULL, true);
+ entry["VHost"] = na->GetVHostMask();
+ entry["Creator"] = na->GetVHostCreator();
+ entry["Created"] = Anope::strftime(na->GetVHostCreated(), NULL, true);
list.AddEntry(entry);
}
}
@@ -125,11 +115,11 @@ class CommandHSList : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -144,11 +134,12 @@ class CommandHSList : public Command
}
};
-class HSList : public Module
+class HSList final
+ : public Module
{
CommandHSList commandhslist;
- public:
+public:
HSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhslist(this)
{
diff --git a/modules/commands/hs_off.cpp b/modules/hostserv/hs_off.cpp
index 62c852ccd..534640ca3 100644
--- a/modules/commands/hs_off.cpp
+++ b/modules/hostserv/hs_off.cpp
@@ -11,29 +11,30 @@
#include "module.h"
-class CommandHSOff : public Command
+class CommandHSOff final
+ : public Command
{
- public:
+public:
CommandHSOff(Module *creator) : Command(creator, "hostserv/off", 0, 0)
{
this->SetDesc(_("Deactivates your assigned vhost"));
this->RequireUser(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
User *u = source.GetUser();
const NickAlias *na = NickAlias::Find(u->nick);
- if (!na || na->nc != u->Account() || !na->HasVhost())
- na = NickAlias::Find(u->Account()->display);
+ if (!na || na->nc != u->Account() || !na->HasVHost())
+ na = u->AccountNick();
- if (!na || !na->HasVhost())
+ if (!na || !na->HasVHost())
source.Reply(HOST_NOT_ASSIGNED);
else
{
u->vhost.clear();
- IRCD->SendVhostDel(u);
+ IRCD->SendVHostDel(u);
u->UpdateHost();
Log(LOG_COMMAND, source, this) << "to disable their vhost";
source.Reply(_("Your vhost was removed and the normal cloaking restored."));
@@ -42,7 +43,7 @@ class CommandHSOff : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -53,11 +54,12 @@ class CommandHSOff : public Command
}
};
-class HSOff : public Module
+class HSOff final
+ : public Module
{
CommandHSOff commandhsoff;
- public:
+public:
HSOff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhsoff(this)
{
diff --git a/modules/commands/hs_on.cpp b/modules/hostserv/hs_on.cpp
index 0c7863171..dbd675333 100644
--- a/modules/commands/hs_on.cpp
+++ b/modules/hostserv/hs_on.cpp
@@ -11,35 +11,33 @@
#include "module.h"
-class CommandHSOn : public Command
+class CommandHSOn final
+ : public Command
{
- public:
+public:
CommandHSOn(Module *creator) : Command(creator, "hostserv/on", 0, 0)
{
this->SetDesc(_("Activates your assigned vhost"));
this->RequireUser(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!IRCD->CanSetVHost)
return; // HostServ wouldn't even be loaded at this point
User *u = source.GetUser();
const NickAlias *na = NickAlias::Find(u->nick);
- if (!na || na->nc != u->Account() || !na->HasVhost())
- na = NickAlias::Find(u->Account()->display);
- if (na && u->Account() == na->nc && na->HasVhost())
+ if (!na || na->nc != u->Account() || !na->HasVHost())
+ na = u->AccountNick();
+ if (na && u->Account() == na->nc && na->HasVHost())
{
- if (!na->GetVhostIdent().empty())
- source.Reply(_("Your vhost of \002%s\002@\002%s\002 is now activated."), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
- else
- source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str());
- Log(LOG_COMMAND, source, this) << "to enable their vhost of " << (!na->GetVhostIdent().empty() ? na->GetVhostIdent() + "@" : "") << na->GetVhostHost();
- IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
- u->vhost = na->GetVhostHost();
- if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
- u->SetVIdent(na->GetVhostIdent());
+ source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVHostMask().c_str());
+ Log(LOG_COMMAND, source, this) << "to enable their vhost of " << na->GetVHostMask();
+ IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
+ u->vhost = na->GetVHostHost();
+ if (IRCD->CanSetVIdent && !na->GetVHostIdent().empty())
+ u->SetVIdent(na->GetVHostIdent());
u->UpdateHost();
}
else
@@ -48,7 +46,7 @@ class CommandHSOn : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -59,11 +57,12 @@ class CommandHSOn : public Command
}
};
-class HSOn : public Module
+class HSOn final
+ : public Module
{
CommandHSOn commandhson;
- public:
+public:
HSOn(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhson(this)
{
diff --git a/modules/commands/hs_request.cpp b/modules/hostserv/hs_request.cpp
index 26ab2dfb4..649462aac 100644
--- a/modules/commands/hs_request.cpp
+++ b/modules/hostserv/hs_request.cpp
@@ -15,29 +15,30 @@
*/
#include "module.h"
+#include "modules/hs_request.h"
static ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
-static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost);
+static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vident, const Anope::string &vhost);
-struct HostRequest : Serializable
+struct HostRequestImpl final
+ : HostRequest
+ , Serializable
{
- Anope::string nick;
- Anope::string ident;
- Anope::string host;
- time_t time;
-
- HostRequest(Extensible *) : Serializable("HostRequest") { }
+ HostRequestImpl(Extensible *)
+ : Serializable("HostRequest")
+ {
+ }
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["nick"] << this->nick;
- data["ident"] << this->ident;
- data["host"] << this->host;
- data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
+ data.Store("nick", this->nick);
+ data.Store("ident", this->ident);
+ data.Store("host", this->host);
+ data.Store("time", this->time);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string snick;
data["nick"] >> snick;
@@ -46,11 +47,11 @@ struct HostRequest : Serializable
if (na == NULL)
return NULL;
- HostRequest *req;
+ HostRequestImpl *req;
if (obj)
- req = anope_dynamic_static_cast<HostRequest *>(obj);
+ req = anope_dynamic_static_cast<HostRequestImpl *>(obj);
else
- req = na->Extend<HostRequest>("hostrequest");
+ req = na->Extend<HostRequestImpl>("hostrequest");
if (req)
{
req->nick = na->nick;
@@ -63,23 +64,22 @@ struct HostRequest : Serializable
}
};
-class CommandHSRequest : public Command
+class CommandHSRequest final
+ : public Command
{
- bool isvalidchar(char c)
+ static bool isvalidchar(char c)
{
- if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
- return true;
- return false;
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-';
}
- public:
+public:
CommandHSRequest(Module *creator) : Command(creator, "hostserv/request", 1, 1)
{
- this->SetDesc(_("Request a vHost for your nick"));
+ this->SetDesc(_("Request a vhost for your nick"));
this->SetSyntax(_("vhost"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -122,9 +122,9 @@ class CommandHSRequest : public Command
if (!user.empty())
{
- if (user.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
+ if (user.length() > IRCD->MaxUser)
{
- source.Reply(HOST_SET_IDENTTOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("userlen"));
+ source.Reply(HOST_SET_IDENTTOOLONG, IRCD->MaxUser);
return;
}
else if (!IRCD->CanSetVIdent)
@@ -132,17 +132,19 @@ class CommandHSRequest : public Command
source.Reply(HOST_NO_VIDENT);
return;
}
- for (Anope::string::iterator s = user.begin(), s_end = user.end(); s != s_end; ++s)
- if (!isvalidchar(*s))
+ for (const auto &chr : user)
+ {
+ if (!isvalidchar(chr))
{
source.Reply(HOST_SET_IDENT_ERROR);
return;
}
+ }
}
- if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
+ if (host.length() > IRCD->MaxHost)
{
- source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"));
+ source.Reply(HOST_SET_TOOLONG, IRCD->MaxHost);
return;
}
@@ -155,44 +157,46 @@ class CommandHSRequest : public Command
time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay");
if (Config->GetModule(this->owner)->Get<bool>("memooper") && send_delay > 0 && u && u->lastmemosend + send_delay > Anope::CurTime)
{
- source.Reply(_("Please wait %d seconds before requesting a new vHost."), send_delay);
+ auto waitperiod = (u->lastmemosend + send_delay) - Anope::CurTime;
+ source.Reply(_("Please wait %s before requesting a new vhost."), Anope::Duration(waitperiod, source.GetAccount()).c_str());
u->lastmemosend = Anope::CurTime;
return;
}
- HostRequest req(na);
+ HostRequestImpl req(na);
req.nick = source.GetNick();
req.ident = user;
req.host = host;
req.time = Anope::CurTime;
- na->Extend<HostRequest>("hostrequest", req);
+ na->Extend<HostRequestImpl>("hostrequest", req);
- source.Reply(_("Your vHost has been requested."));
+ source.Reply(_("Your vhost has been requested."));
req_send_memos(owner, source, user, host);
Log(LOG_COMMAND, source, this) << "to request new vhost " << (!user.empty() ? user + "@" : "") << host;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Request the given vHost to be activated for your nick by the\n"
+ source.Reply(_("Request the given vhost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."));
return true;
}
};
-class CommandHSActivate : public Command
+class CommandHSActivate final
+ : public Command
{
- public:
+public:
CommandHSActivate(Module *creator) : Command(creator, "hostserv/activate", 1, 1)
{
- this->SetDesc(_("Approve the requested vHost of a user"));
+ this->SetDesc(_("Approve the requested vhost of a user"));
this->SetSyntax(_("\037nick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -203,28 +207,28 @@ class CommandHSActivate : public Command
const Anope::string &nick = params[0];
NickAlias *na = NickAlias::Find(nick);
- HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL;
+ HostRequestImpl *req = na ? na->GetExt<HostRequestImpl>("hostrequest") : NULL;
if (req)
{
- na->SetVhost(req->ident, req->host, source.GetNick(), req->time);
- FOREACH_MOD(OnSetVhost, (na));
+ na->SetVHost(req->ident, req->host, source.GetNick(), req->time);
+ FOREACH_MOD(OnSetVHost, (na));
if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv)
- memoserv->Send(source.service->nick, na->nick, _("[auto memo] Your requested vHost has been approved."), true);
+ memoserv->Send(source.service->nick, na->nick, _("[auto memo] Your requested vhost has been approved."), true);
- source.Reply(_("vHost for %s has been activated."), na->nick.c_str());
+ source.Reply(_("VHost for %s has been activated."), na->nick.c_str());
Log(LOG_COMMAND, source, this) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host;
- na->Shrink<HostRequest>("hostrequest");
+ na->Shrink<HostRequestImpl>("hostrequest");
}
else
source.Reply(_("No request for nick %s found."), nick.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Activate the requested vHost for the given nick."));
+ source.Reply(_("Activate the requested vhost for the given nick."));
if (Config->GetModule(this->owner)->Get<bool>("memouser"))
source.Reply(_("A memo informing the user will also be sent."));
@@ -232,16 +236,17 @@ class CommandHSActivate : public Command
}
};
-class CommandHSReject : public Command
+class CommandHSReject final
+ : public Command
{
- public:
+public:
CommandHSReject(Module *creator) : Command(creator, "hostserv/reject", 1, 2)
{
- this->SetDesc(_("Reject the requested vHost of a user"));
+ this->SetDesc(_("Reject the requested vhost of a user"));
this->SetSyntax(_("\037nick\037 [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -253,34 +258,34 @@ class CommandHSReject : public Command
const Anope::string &reason = params.size() > 1 ? params[1] : "";
NickAlias *na = NickAlias::Find(nick);
- HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL;
+ HostRequestImpl *req = na ? na->GetExt<HostRequestImpl>("hostrequest") : NULL;
if (req)
{
- na->Shrink<HostRequest>("hostrequest");
+ na->Shrink<HostRequestImpl>("hostrequest");
if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv)
{
Anope::string message;
if (!reason.empty())
- message = Anope::printf(_("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str());
+ message = Anope::printf(_("[auto memo] Your requested vhost has been rejected. Reason: %s"), reason.c_str());
else
- message = _("[auto memo] Your requested vHost has been rejected.");
+ message = _("[auto memo] Your requested vhost has been rejected.");
memoserv->Send(source.service->nick, nick, Language::Translate(source.GetAccount(), message.c_str()), true);
}
- source.Reply(_("vHost for %s has been rejected."), nick.c_str());
+ source.Reply(_("VHost for %s has been rejected."), nick.c_str());
Log(LOG_COMMAND, source, this) << "to reject vhost for " << nick << " (" << (!reason.empty() ? reason : "no reason") << ")";
}
else
source.Reply(_("No request for nick %s found."), nick.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Reject the requested vHost for the given nick."));
+ source.Reply(_("Reject the requested vhost for the given nick."));
if (Config->GetModule(this->owner)->Get<bool>("memouser"))
source.Reply(_("A memo informing the user will also be sent, which includes the reason for the rejection if supplied."));
@@ -288,26 +293,26 @@ class CommandHSReject : public Command
}
};
-class CommandHSWaiting : public Command
+class CommandHSWaiting final
+ : public Command
{
- public:
+public:
CommandHSWaiting(Module *creator) : Command(creator, "hostserv/waiting", 0, 0)
{
this->SetDesc(_("Retrieves the vhost requests"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
unsigned counter = 0;
unsigned display_counter = 0, listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax");
ListFormatter list(source.GetAccount());
- list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Created"));
+ list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("VHost")).AddColumn(_("Created"));
- for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
+ for (const auto &[nick, na] : *NickAliasList)
{
- const NickAlias *na = it->second;
- HostRequest *hr = na->GetExt<HostRequest>("hostrequest");
+ HostRequestImpl *hr = na->GetExt<HostRequestImpl>("hostrequest");
if (!hr)
continue;
@@ -316,12 +321,12 @@ class CommandHSWaiting : public Command
++display_counter;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(display_counter);
- entry["Nick"] = it->first;
+ entry["Number"] = Anope::ToString(display_counter);
+ entry["Nick"] = nick;
if (!hr->ident.empty())
- entry["Vhost"] = hr->ident + "@" + hr->host;
+ entry["VHost"] = hr->ident + "@" + hr->host;
else
- entry["Vhost"] = hr->host;
+ entry["VHost"] = hr->host;
entry["Created"] = Anope::strftime(hr->time, NULL, true);
list.AddEntry(entry);
}
@@ -331,13 +336,13 @@ class CommandHSWaiting : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("Displayed \002%d\002 records (\002%d\002 total)."), display_counter, counter);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -347,48 +352,47 @@ class CommandHSWaiting : public Command
}
};
-class HSRequest : public Module
+class HSRequest final
+ : public Module
{
CommandHSRequest commandhsrequest;
CommandHSActivate commandhsactive;
CommandHSReject commandhsreject;
CommandHSWaiting commandhswaiting;
- ExtensibleItem<HostRequest> hostrequest;
+ ExtensibleItem<HostRequestImpl> hostrequest;
Serialize::Type request_type;
- public:
+public:
HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandhsrequest(this), commandhsactive(this),
- commandhsreject(this), commandhswaiting(this), hostrequest(this, "hostrequest"), request_type("HostRequest", HostRequest::Unserialize)
+ commandhsreject(this), commandhswaiting(this), hostrequest(this, "hostrequest"), request_type("HostRequest", HostRequestImpl::Unserialize)
{
if (!IRCD || !IRCD->CanSetVHost)
throw ModuleException("Your IRCd does not support vhosts");
}
};
-static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost)
+static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vident, const Anope::string &vhost)
{
Anope::string host;
- std::list<std::pair<Anope::string, Anope::string> >::iterator it, it_end;
-
- if (!vIdent.empty())
- host = vIdent + "@" + vHost;
+ if (!vident.empty())
+ host = vident + "@" + vhost;
else
- host = vHost;
+ host = vhost;
if (Config->GetModule(me)->Get<bool>("memooper") && memoserv)
- for (unsigned i = 0; i < Oper::opers.size(); ++i)
+ {
+ for (auto *o : Oper::opers)
{
- Oper *o = Oper::opers[i];
-
const NickAlias *na = NickAlias::Find(o->name);
if (!na)
continue;
- Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str());
+ Anope::string message = Anope::printf(_("[auto memo] VHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str());
memoserv->Send(source.service->nick, na->nick, message, true);
}
+ }
}
MODULE_INIT(HSRequest)
diff --git a/modules/commands/hs_set.cpp b/modules/hostserv/hs_set.cpp
index f2c413a6a..740646a9c 100644
--- a/modules/commands/hs_set.cpp
+++ b/modules/hostserv/hs_set.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandHSSet : public Command
+class CommandHSSet final
+ : public Command
{
- public:
+public:
CommandHSSet(Module *creator) : Command(creator, "hostserv/set", 2, 2)
{
this->SetDesc(_("Set the vhost of another user"));
this->SetSyntax(_("\037nick\037 \037hostmask\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -70,9 +71,9 @@ class CommandHSSet : public Command
}
}
- if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
+ if (host.length() > IRCD->MaxHost)
{
- source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"));
+ source.Reply(HOST_SET_TOOLONG, IRCD->MaxHost);
return;
}
@@ -84,49 +85,46 @@ class CommandHSSet : public Command
Log(LOG_ADMIN, source, this) << "to set the vhost of " << na->nick << " to " << (!user.empty() ? user + "@" : "") << host;
- na->SetVhost(user, host, source.GetNick());
- FOREACH_MOD(OnSetVhost, (na));
- if (!user.empty())
- source.Reply(_("VHost for \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str());
- else
- source.Reply(_("VHost for \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str());
+ na->SetVHost(user, host, source.GetNick());
+ FOREACH_MOD(OnSetVHost, (na));
+ source.Reply(_("VHost for \002%s\002 set to \002%s\002."), nick.c_str(), na->GetVHostMask().c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Sets the vhost for the given nick to that of the given\n"
- "hostmask. If your IRCD supports vIdents, then using\n"
+ "hostmask. If your IRCD supports vidents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."));
return true;
}
};
-class CommandHSSetAll : public Command
+class CommandHSSetAll final
+ : public Command
{
- void Sync(const NickAlias *na)
+ static void Sync(const NickAlias *na)
{
- if (!na || !na->HasVhost())
+ if (!na || !na->HasVHost())
return;
- for (unsigned i = 0; i < na->nc->aliases->size(); ++i)
+ for (auto *nick : *na->nc->aliases)
{
- NickAlias *nick = na->nc->aliases->at(i);
if (nick && nick != na)
- nick->SetVhost(na->GetVhostIdent(), na->GetVhostHost(), na->GetVhostCreator());
+ nick->SetVHost(na->GetVHostIdent(), na->GetVHostHost(), na->GetVHostCreator());
}
}
- public:
+public:
CommandHSSetAll(Module *creator) : Command(creator, "hostserv/setall", 2, 2)
{
this->SetDesc(_("Set the vhost for all nicks in a group"));
this->SetSyntax(_("\037nick\037 \037hostmask\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -176,9 +174,9 @@ class CommandHSSetAll : public Command
}
}
- if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
+ if (host.length() > IRCD->MaxHost)
{
- source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"));
+ source.Reply(HOST_SET_TOOLONG, IRCD->MaxHost);
return;
}
@@ -190,21 +188,18 @@ class CommandHSSetAll : public Command
Log(LOG_ADMIN, source, this) << "to set the vhost of " << na->nick << " to " << (!user.empty() ? user + "@" : "") << host;
- na->SetVhost(user, host, source.GetNick());
+ na->SetVHost(user, host, source.GetNick());
this->Sync(na);
- FOREACH_MOD(OnSetVhost, (na));
- if (!user.empty())
- source.Reply(_("VHost for group \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str());
- else
- source.Reply(_("VHost for group \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str());
+ FOREACH_MOD(OnSetVHost, (na));
+ source.Reply(_("VHost for group \002%s\002 set to \002%s\002."), nick.c_str(), na->GetVHostMask().c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Sets the vhost for all nicks in the same group as that\n"
- "of the given nick. If your IRCD supports vIdents, then\n"
+ "of the given nick. If your IRCD supports vidents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
@@ -213,12 +208,13 @@ class CommandHSSetAll : public Command
}
};
-class HSSet : public Module
+class HSSet final
+ : public Module
{
CommandHSSet commandhsset;
CommandHSSetAll commandhssetall;
- public:
+public:
HSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandhsset(this), commandhssetall(this)
{
if (!IRCD || !IRCD->CanSetVHost)
diff --git a/modules/m_httpd.cpp b/modules/httpd.cpp
index fbce68891..d25742aa2 100644
--- a/modules/m_httpd.cpp
+++ b/modules/httpd.cpp
@@ -37,23 +37,24 @@ static Anope::string GetStatusFromCode(HTTPError err)
return "501 Not Implemented";
}
-class MyHTTPClient : public HTTPClient
+class MyHTTPClient final
+ : public HTTPClient
{
HTTPProvider *provider;
HTTPMessage message;
- bool header_done, served;
+ bool header_done = false, served = false;
Anope::string page_name;
Reference<HTTPPage> page;
Anope::string ip;
- unsigned content_length;
+ unsigned content_length = 0;
enum
{
ACTION_NONE,
ACTION_GET,
ACTION_POST
- } action;
+ } action = ACTION_NONE;
void Serve()
{
@@ -69,20 +70,18 @@ class MyHTTPClient : public HTTPClient
if (std::find(this->provider->ext_ips.begin(), this->provider->ext_ips.end(), this->ip) != this->provider->ext_ips.end())
{
- for (unsigned i = 0; i < this->provider->ext_headers.size(); ++i)
+ for (auto &token : this->provider->ext_headers)
{
- const Anope::string &token = this->provider->ext_headers[i];
-
if (this->message.headers.count(token))
{
this->ip = this->message.headers[token];
- Log(LOG_DEBUG, "httpd") << "m_httpd: IP for connection " << this->GetFD() << " changed to " << this->ip;
+ Log(LOG_DEBUG, "httpd") << "httpd: IP for connection " << this->GetFD() << " changed to " << this->ip;
break;
}
}
}
- Log(LOG_DEBUG, "httpd") << "m_httpd: Serving page " << this->page_name << " to " << this->ip;
+ Log(LOG_DEBUG, "httpd") << "httpd: Serving page " << this->page_name << " to " << this->ip;
HTTPReply reply;
reply.content_type = this->page->GetContentType();
@@ -91,31 +90,31 @@ class MyHTTPClient : public HTTPClient
this->SendReply(&reply);
}
- public:
+public:
time_t created;
- MyHTTPClient(HTTPProvider *l, int f, const sockaddrs &a) : Socket(f, l->IsIPv6()), HTTPClient(l, f, a), provider(l), header_done(false), served(false), ip(a.addr()), content_length(0), action(ACTION_NONE), created(Anope::CurTime)
+ MyHTTPClient(HTTPProvider *l, int f, const sockaddrs &a) : Socket(f, l->GetFamily()), HTTPClient(l, f, a), provider(l), ip(a.addr()), created(Anope::CurTime)
{
Log(LOG_DEBUG, "httpd") << "Accepted connection " << f << " from " << a.addr();
}
- ~MyHTTPClient()
+ ~MyHTTPClient() override
{
Log(LOG_DEBUG, "httpd") << "Closing connection " << this->GetFD() << " from " << this->ip;
}
/* Close connection once all data is written */
- bool ProcessWrite() anope_override
+ bool ProcessWrite() override
{
- return !BinarySocket::ProcessWrite() || this->write_buffer.empty() ? false : true;
+ return !(!BinarySocket::ProcessWrite() || this->write_buffer.empty());
}
- const Anope::string GetIP() anope_override
+ const Anope::string GetIP() override
{
return this->ip;
}
- bool Read(const char *buffer, size_t l) anope_override
+ bool Read(const char *buffer, size_t l) override
{
message.content.append(buffer, l);
@@ -217,11 +216,8 @@ class MyHTTPClient : public HTTPClient
}
else if (buf.find_ci("Content-Length: ") == 0)
{
- try
- {
- this->content_length = convertTo<unsigned>(buf.substr(16));
- }
- catch (const ConvertException &ex) { }
+ if (auto len = Anope::TryConvert<unsigned>(buf.substr(16)))
+ this->content_length = len.value();
}
else if (buf.find(':') != Anope::string::npos)
{
@@ -233,7 +229,7 @@ class MyHTTPClient : public HTTPClient
return true;
}
- void SendError(HTTPError err, const Anope::string &msg) anope_override
+ void SendError(HTTPError err, const Anope::string &msg) override
{
HTTPReply h;
@@ -244,7 +240,7 @@ class MyHTTPClient : public HTTPClient
this->SendReply(&h);
}
- void SendReply(HTTPReply *msg) anope_override
+ void SendReply(HTTPReply *msg) override
{
this->WriteClient("HTTP/1.1 " + GetStatusFromCode(msg->error));
this->WriteClient("Date: " + BuildDate());
@@ -253,32 +249,29 @@ class MyHTTPClient : public HTTPClient
this->WriteClient("Content-Type: text/html");
else
this->WriteClient("Content-Type: " + msg->content_type);
- this->WriteClient("Content-Length: " + stringify(msg->length));
+ this->WriteClient("Content-Length: " + Anope::ToString(msg->length));
- for (unsigned i = 0; i < msg->cookies.size(); ++i)
+ for (const auto &cookie : msg->cookies)
{
Anope::string buf = "Set-Cookie:";
- for (HTTPReply::cookie::iterator it = msg->cookies[i].begin(), it_end = msg->cookies[i].end(); it != it_end; ++it)
- buf += " " + it->first + "=" + it->second + ";";
+ for (const auto &[name, value] : cookie)
+ buf += " " + name + "=" + value + ";";
buf.erase(buf.length() - 1);
this->WriteClient(buf);
}
- typedef std::map<Anope::string, Anope::string> map;
- for (map::iterator it = msg->headers.begin(), it_end = msg->headers.end(); it != it_end; ++it)
- this->WriteClient(it->first + ": " + it->second);
+ for (auto &[name, value] : msg->headers)
+ this->WriteClient(name + ": " + value);
this->WriteClient("Connection: Close");
this->WriteClient("");
- for (unsigned i = 0; i < msg->out.size(); ++i)
+ for (auto *d : msg->out)
{
- HTTPReply::Data* d = msg->out[i];
-
- this->Write(d->buf, d->len);
+ this->Write(d->buf, d->len);
delete d;
}
@@ -287,16 +280,24 @@ class MyHTTPClient : public HTTPClient
}
};
-class MyHTTPProvider : public HTTPProvider, public Timer
+class MyHTTPProvider final
+ : public HTTPProvider
+ , public Timer
{
int timeout;
std::map<Anope::string, HTTPPage *> pages;
std::list<Reference<MyHTTPClient> > clients;
- public:
- MyHTTPProvider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, const int t, bool s) : Socket(-1, i.find(':') != Anope::string::npos), HTTPProvider(c, n, i, p, s), Timer(c, 10, Anope::CurTime, true), timeout(t) { }
+public:
+ MyHTTPProvider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, const int t, bool s)
+ : Socket(-1, i.find(':') == Anope::string::npos ? AF_INET : AF_INET6)
+ , HTTPProvider(c, n, i, p, s)
+ , Timer(c, 10, true)
+ , timeout(t)
+ {
+ }
- void Tick(time_t) anope_override
+ void Tick() override
{
while (!this->clients.empty())
{
@@ -309,24 +310,24 @@ class MyHTTPProvider : public HTTPProvider, public Timer
}
}
- ClientSocket* OnAccept(int fd, const sockaddrs &addr) anope_override
+ ClientSocket *OnAccept(int fd, const sockaddrs &addr) override
{
- MyHTTPClient *c = new MyHTTPClient(this, fd, addr);
- this->clients.push_back(c);
+ auto *c = new MyHTTPClient(this, fd, addr);
+ this->clients.emplace_back(c);
return c;
}
- bool RegisterPage(HTTPPage *page) anope_override
+ bool RegisterPage(HTTPPage *page) override
{
- return this->pages.insert(std::make_pair(page->GetURL(), page)).second;
+ return this->pages.emplace(page->GetURL(), page).second;
}
- void UnregisterPage(HTTPPage *page) anope_override
+ void UnregisterPage(HTTPPage *page) override
{
this->pages.erase(page->GetURL());
}
- HTTPPage* FindPage(const Anope::string &pname) anope_override
+ HTTPPage *FindPage(const Anope::string &pname) override
{
if (this->pages.count(pname) == 0)
return NULL;
@@ -334,17 +335,18 @@ class MyHTTPProvider : public HTTPProvider, public Timer
}
};
-class HTTPD : public Module
+class HTTPD final
+ : public Module
{
ServiceReference<SSLService> sslref;
std::map<Anope::string, MyHTTPProvider *> providers;
- public:
+public:
HTTPD(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), sslref("SSLService", "ssl")
{
}
- ~HTTPD()
+ ~HTTPD() override
{
for (std::map<int, Socket *>::const_iterator it = SocketEngine::Sockets.begin(), it_end = SocketEngine::Sockets.end(); it != it_end;)
{
@@ -358,7 +360,7 @@ class HTTPD : public Module
this->providers.clear();
}
- void OnReload(Configuration::Conf *config) anope_override
+ void OnReload(Configuration::Conf *config) override
{
Configuration::Block *conf = config->GetModule(this);
std::set<Anope::string> existing;
@@ -453,12 +455,10 @@ class HTTPD : public Module
}
}
- void OnModuleLoad(User *u, Module *m) anope_override
+ void OnModuleLoad(User *u, Module *m) override
{
- for (std::map<Anope::string, MyHTTPProvider *>::iterator it = this->providers.begin(), it_end = this->providers.end(); it != it_end; ++it)
+ for (auto &[_, p] : this->providers)
{
- MyHTTPProvider *p = it->second;
-
if (p->IsSSL() && sslref)
try
{
diff --git a/modules/extra/stats/irc2sql/CMakeLists.txt b/modules/irc2sql/CMakeLists.txt
index 781f0ef1f..781f0ef1f 100644
--- a/modules/extra/stats/irc2sql/CMakeLists.txt
+++ b/modules/irc2sql/CMakeLists.txt
diff --git a/modules/extra/stats/irc2sql/irc2sql.cpp b/modules/irc2sql/irc2sql.cpp
index e1af50ae5..c288a2366 100644
--- a/modules/extra/stats/irc2sql/irc2sql.cpp
+++ b/modules/irc2sql/irc2sql.cpp
@@ -11,7 +11,7 @@
void IRC2SQL::OnShutdown()
{
// TODO: test if we really have to use blocking query here
- // (sometimes m_mysql get unloaded before the other thread executed all queries)
+ // (sometimes mysql get unloaded before the other thread executed all queries)
if (this->sql)
SQL::Result r = this->sql->RunQuery(SQL::Query("CALL " + prefix + "OnShutdown()"));
quitting = true;
@@ -47,19 +47,18 @@ void IRC2SQL::OnReload(Configuration::Conf *conf)
this->OnNewServer(it->second);
}
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
+ for (const auto &[_, c] : ChannelList)
{
- this->OnChannelCreate(it->second);
+ this->OnChannelCreate(c);
}
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u] : UserListByNick)
{
- User *u = it->second;
bool exempt = false;
this->OnUserConnect(u, exempt);
- for (User::ChanUserList::const_iterator cit = u->chans.begin(), cit_end = u->chans.end(); cit != cit_end; ++cit)
+ for (const auto &[_, uc] : u->chans)
{
- this->OnJoinChannel(u, cit->second->chan);
+ this->OnJoinChannel(u, uc->chan);
}
}
}
@@ -107,7 +106,7 @@ void IRC2SQL::OnUserConnect(User *u, bool &exempt)
query.SetValue("ip", u->ip.addr());
query.SetValue("ident", u->GetIdent());
query.SetValue("vident", u->GetVIdent());
- query.SetValue("secure", u->HasMode("SSL") || u->HasExt("ssl") ? "Y" : "N");
+ query.SetValue("secure", u->IsSecurelyConnected() ? "Y" : "N");
query.SetValue("account", u->IsIdentified() ? u->Account()->display : "");
query.SetValue("fingerprint", u->fingerprint);
query.SetValue("signon", u->signon);
@@ -118,7 +117,7 @@ void IRC2SQL::OnUserConnect(User *u, bool &exempt)
this->RunQuery(query);
if (ctcpuser && (Me->IsSynced() || ctcpeob) && u->server != Me)
- IRCD->SendPrivmsg(StatServ, u->GetUID(), "\1VERSION\1");
+ IRCD->SendPrivmsg(StatServ, u->GetUID(), Anope::FormatCTCP("VERSION"));
}
@@ -152,7 +151,7 @@ void IRC2SQL::OnUserAway(User *u, const Anope::string &message)
void IRC2SQL::OnFingerprint(User *u)
{
query = "UPDATE `" + prefix + "user` SET secure=@secure@, fingerprint=@fingerprint@ WHERE nick=@nick@";
- query.SetValue("secure", u->HasMode("SSL") || u->HasExt("ssl") ? "Y" : "N");
+ query.SetValue("secure", u->IsSecurelyConnected() ? "Y" : "N");
query.SetValue("fingerprint", u->fingerprint);
query.SetValue("nick", u->nick);
this->RunQuery(query);
@@ -298,30 +297,29 @@ void IRC2SQL::OnTopicUpdated(User *source, Channel *c, const Anope::string &user
this->RunQuery(query);
}
-void IRC2SQL::OnBotNotice(User *u, BotInfo *bi, Anope::string &message)
+void IRC2SQL::OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags)
{
- Anope::string versionstr;
if (bi != StatServ)
return;
- if (message[0] == '\1' && message[message.length() - 1] == '\1')
- {
- if (message.substr(0, 9).equals_ci("\1VERSION "))
- {
- if (u->HasExt("CTCPVERSION"))
- return;
- u->Extend<bool>("CTCPVERSION");
-
- versionstr = Anope::NormalizeBuffer(message.substr(9, message.length() - 10));
- if (versionstr.empty())
- return;
- query = "UPDATE `" + prefix + "user` "
- "SET version=@version@ "
- "WHERE nick=@nick@";
- query.SetValue("version", versionstr);
- query.SetValue("nick", u->nick);
- this->RunQuery(query);
- }
- }
+
+ Anope::string ctcpname, ctcpbody;
+ if (!Anope::ParseCTCP(message, ctcpname, ctcpbody) || ctcpname != "VERSION")
+ return;
+
+ if (u->HasExt("CTCPVERSION"))
+ return;
+
+ u->Extend<bool>("CTCPVERSION");
+ auto versionstr = Anope::NormalizeBuffer(message.substr(9, message.length() - 10));
+ if (versionstr.empty())
+ return;
+
+ query = "UPDATE `" + prefix + "user` "
+ "SET version=@version@ "
+ "WHERE nick=@nick@";
+ query.SetValue("version", versionstr);
+ query.SetValue("nick", u->nick);
+ this->RunQuery(query);
}
MODULE_INIT(IRC2SQL)
diff --git a/modules/irc2sql/irc2sql.h b/modules/irc2sql/irc2sql.h
new file mode 100644
index 000000000..27e1dee13
--- /dev/null
+++ b/modules/irc2sql/irc2sql.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * (C) 2013-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+#include "module.h"
+#include "modules/sql.h"
+
+class MySQLInterface final
+ : public SQL::Interface
+{
+public:
+ MySQLInterface(Module *o) : SQL::Interface(o) { }
+
+ void OnResult(const SQL::Result &r) override
+ {
+ }
+
+ void OnError(const SQL::Result &r) override
+ {
+ if (!r.GetQuery().query.empty())
+ Log(LOG_DEBUG) << "irc2sql: Error executing query " << r.finished_query << ": " << r.GetError();
+ else
+ Log(LOG_DEBUG) << "irc2sql: Error executing query: " << r.GetError();
+ }
+};
+
+class IRC2SQL final
+ : public Module
+{
+ ServiceReference<SQL::Provider> sql;
+ MySQLInterface sqlinterface;
+ SQL::Query query;
+ std::vector<Anope::string> TableList, ProcedureList, EventList;
+ Anope::string prefix, GeoIPDB;
+ bool quitting, introduced_myself, ctcpuser, ctcpeob, firstrun;
+ BotInfo *StatServ;
+ PrimitiveExtensibleItem<bool> versionreply;
+
+ void RunQuery(const SQL::Query &q);
+ void GetTables();
+
+ bool HasTable(const Anope::string &table);
+ bool HasProcedure(const Anope::string &table);
+ bool HasEvent(const Anope::string &table);
+
+ void CheckTables();
+
+public:
+ IRC2SQL(const Anope::string &modname, const Anope::string &creator) :
+ Module(modname, creator, EXTRA | VENDOR), sql("", ""), sqlinterface(this), versionreply(this, "CTCPVERSION")
+ {
+ firstrun = true;
+ quitting = false;
+ introduced_myself = false;
+ }
+
+ void OnShutdown() override;
+ void OnReload(Configuration::Conf *config) override;
+ void OnNewServer(Server *server) override;
+ void OnServerQuit(Server *server) override;
+ void OnUserConnect(User *u, bool &exempt) override;
+ void OnUserQuit(User *u, const Anope::string &msg) override;
+ void OnUserNickChange(User *u, const Anope::string &oldnick) override;
+ void OnUserAway(User *u, const Anope::string &message) override;
+ void OnFingerprint(User *u) override;
+ void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override;
+ void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override;
+ void OnUserLogin(User *u) override;
+ void OnNickLogout(User *u) override;
+ void OnSetDisplayedHost(User *u) override;
+
+ void OnChannelCreate(Channel *c) override;
+ void OnChannelDelete(Channel *c) override;
+ void OnLeaveChannel(User *u, Channel *c) override;
+ void OnJoinChannel(User *u, Channel *c) override;
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override;
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override;
+
+ void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override;
+
+ void OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override;
+};
diff --git a/modules/extra/stats/irc2sql/tables.cpp b/modules/irc2sql/tables.cpp
index 712274f14..b00c0e9a5 100644
--- a/modules/extra/stats/irc2sql/tables.cpp
+++ b/modules/irc2sql/tables.cpp
@@ -80,14 +80,14 @@ void IRC2SQL::CheckTables()
if (!this->HasTable(prefix + "server"))
{
query = "CREATE TABLE `" + prefix + "server` ("
- "`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
+ "`id` int UNSIGNED NOT NULL AUTO_INCREMENT,"
"`name` varchar(64) NOT NULL,"
- "`hops` tinyint(3) NOT NULL,"
+ "`hops` tinyint NOT NULL,"
"`comment` varchar(255) NOT NULL,"
"`link_time` datetime DEFAULT NULL,"
"`split_time` datetime DEFAULT NULL,"
"`version` varchar(127) DEFAULT NULL,"
- "`currentusers` int(15) DEFAULT 0,"
+ "`currentusers` int DEFAULT 0,"
"`online` enum('Y','N') NOT NULL DEFAULT 'Y',"
"`ulined` enum('Y','N') NOT NULL DEFAULT 'N',"
"PRIMARY KEY (`id`),"
@@ -98,7 +98,7 @@ void IRC2SQL::CheckTables()
if (!this->HasTable(prefix + "chan"))
{
query = "CREATE TABLE `" + prefix + "chan` ("
- "`chanid` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
+ "`chanid` int UNSIGNED NOT NULL AUTO_INCREMENT,"
"`channel` varchar(255) NOT NULL,"
"`topic` varchar(512) DEFAULT NULL,"
"`topicauthor` varchar(255) DEFAULT NULL,"
@@ -112,7 +112,7 @@ void IRC2SQL::CheckTables()
if (!this->HasTable(prefix + "user"))
{
query = "CREATE TABLE `" + prefix + "user` ("
- "`nickid` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,"
+ "`nickid` int UNSIGNED NOT NULL AUTO_INCREMENT,"
"`nick` varchar(255) NOT NULL DEFAULT '',"
"`host` varchar(255) NOT NULL DEFAULT '',"
"`vhost` varchar(255) NOT NULL DEFAULT '',"
@@ -127,7 +127,7 @@ void IRC2SQL::CheckTables()
"`fingerprint` varchar(128) NOT NULL DEFAULT '',"
"`signon` datetime DEFAULT NULL,"
"`server` varchar(255) NOT NULL DEFAULT '',"
- "`servid` int(11) UNSIGNED NOT NULL DEFAULT '0',"
+ "`servid` int UNSIGNED NOT NULL DEFAULT '0',"
"`uuid` varchar(32) NOT NULL DEFAULT '',"
"`oper` enum('Y','N') NOT NULL DEFAULT 'N',"
"`away` enum('Y','N') NOT NULL DEFAULT 'N',"
@@ -147,8 +147,8 @@ void IRC2SQL::CheckTables()
if (!this->HasTable(prefix + "ison"))
{
query = "CREATE TABLE `" + prefix + "ison` ("
- "`nickid` int(11) unsigned NOT NULL default '0',"
- "`chanid` int(11) unsigned NOT NULL default '0',"
+ "`nickid` int unsigned NOT NULL default '0',"
+ "`chanid` int unsigned NOT NULL default '0',"
"`modes` varchar(255) NOT NULL default '',"
"PRIMARY KEY (`nickid`,`chanid`),"
"KEY `modes` (`modes`)"
@@ -159,7 +159,7 @@ void IRC2SQL::CheckTables()
{
query = "CREATE TABLE `" + prefix + "maxusers` ("
"`name` VARCHAR(255) NOT NULL,"
- "`maxusers` INT(15) NOT NULL,"
+ "`maxusers` int NOT NULL,"
"`maxtime` DATETIME NOT NULL,"
"`lastused` DATETIME NOT NULL,"
"UNIQUE KEY `name` (`name`)"
@@ -200,12 +200,12 @@ void IRC2SQL::CheckTables()
"(nick_ varchar(255), host_ varchar(255), vhost_ varchar(255), "
"chost_ varchar(255), realname_ varchar(255), ip_ varchar(255), "
"ident_ varchar(255), vident_ varchar(255), account_ varchar(255), "
- "secure_ enum('Y','N'), fingerprint_ varchar(255), signon_ int(15), "
+ "secure_ enum('Y','N'), fingerprint_ varchar(255), signon_ int, "
"server_ varchar(255), uuid_ varchar(32), modes_ varchar(255), "
"oper_ enum('Y','N')) "
"BEGIN "
- "DECLARE cur int(15);"
- "DECLARE max int(15);"
+ "DECLARE cur int;"
+ "DECLARE max int;"
"INSERT INTO `" + prefix + "user` "
"(nick, host, vhost, chost, realname, ip, ident, vident, account, "
"secure, fingerprint, signon, server, uuid, modes, oper) "
@@ -304,8 +304,8 @@ void IRC2SQL::CheckTables()
query = "CREATE PROCEDURE `"+ prefix + "JoinUser`"
"(nick_ varchar(255), channel_ varchar(255), modes_ varchar(255)) "
"BEGIN "
- "DECLARE cur int(15);"
- "DECLARE max int(15);"
+ "DECLARE cur int;"
+ "DECLARE max int;"
"INSERT INTO `" + prefix + "ison` (nickid, chanid, modes) "
"SELECT u.nickid, c.chanid, modes_ "
"FROM " + prefix + "user AS u, " + prefix + "chan AS c "
diff --git a/modules/extra/stats/irc2sql/utils.cpp b/modules/irc2sql/utils.cpp
index 7debdda9d..7debdda9d 100644
--- a/modules/extra/stats/irc2sql/utils.cpp
+++ b/modules/irc2sql/utils.cpp
diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/ldap_authentication.cpp
index 8d81056b8..5860055e5 100644
--- a/modules/extra/m_ldap_authentication.cpp
+++ b/modules/ldap_authentication.cpp
@@ -17,15 +17,15 @@ static Anope::string object_class;
static Anope::string email_attribute;
static Anope::string username_attribute;
-struct IdentifyInfo
+struct IdentifyInfo final
{
Reference<User> user;
IdentifyRequest *req;
ServiceReference<LDAPProvider> lprov;
- bool admin_bind;
+ bool admin_bind = true;
Anope::string dn;
- IdentifyInfo(User *u, IdentifyRequest *r, ServiceReference<LDAPProvider> &lp) : user(u), req(r), lprov(lp), admin_bind(true)
+ IdentifyInfo(User *u, IdentifyRequest *r, ServiceReference<LDAPProvider> &lp) : user(u), req(r), lprov(lp)
{
req->Hold(me);
}
@@ -36,11 +36,12 @@ struct IdentifyInfo
}
};
-class IdentifyInterface : public LDAPInterface
+class IdentifyInterface final
+ : public LDAPInterface
{
IdentifyInfo *ii;
- public:
+public:
IdentifyInterface(Module *m, IdentifyInfo *i) : LDAPInterface(m), ii(i) { }
~IdentifyInterface()
@@ -48,12 +49,12 @@ class IdentifyInterface : public LDAPInterface
delete ii;
}
- void OnDelete() anope_override
+ void OnDelete() override
{
delete this;
}
- void OnResult(const LDAPResult &r) anope_override
+ void OnResult(const LDAPResult &r) override
{
if (!ii->lprov)
return;
@@ -68,7 +69,7 @@ class IdentifyInterface : public LDAPInterface
{
const LDAPAttributes &attr = r.get(0);
ii->dn = attr.get("dn");
- Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn;
+ Log(LOG_DEBUG) << "ldap_authenticationn: binding as " << ii->dn;
ii->lprov->Bind(new IdentifyInterface(this->owner, ii), ii->dn, ii->req->GetPassword());
ii = NULL;
@@ -87,7 +88,7 @@ class IdentifyInterface : public LDAPInterface
Anope::string sf = search_filter.replace_all_cs("%account", ii->req->GetAccount()).replace_all_cs("%object_class", object_class);
try
{
- Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
+ Log(LOG_DEBUG) << "ldap_authentication: searching for " << sf;
ii->lprov->Search(new IdentifyInterface(this->owner, ii), basedn, sf);
ii->admin_bind = false;
ii = NULL;
@@ -112,7 +113,7 @@ class IdentifyInterface : public LDAPInterface
// encrypt and store the password in the nickcore
Anope::Encrypt(ii->req->GetPassword(), na->nc->pass);
- na->nc->Extend<Anope::string>("m_ldap_authentication_dn", ii->dn);
+ na->nc->Extend<Anope::string>("ldap_authentication_dn", ii->dn);
ii->req->Success(me);
}
break;
@@ -122,24 +123,25 @@ class IdentifyInterface : public LDAPInterface
}
}
- void OnError(const LDAPResult &r) anope_override
+ void OnError(const LDAPResult &r) override
{
}
};
-class OnIdentifyInterface : public LDAPInterface
+class OnIdentifyInterface final
+ : public LDAPInterface
{
Anope::string uid;
- public:
+public:
OnIdentifyInterface(Module *m, const Anope::string &i) : LDAPInterface(m), uid(i) { }
- void OnDelete() anope_override
+ void OnDelete() override
{
delete this;
}
- void OnResult(const LDAPResult &r) anope_override
+ void OnResult(const LDAPResult &r) override
{
User *u = User::Find(uid);
@@ -166,29 +168,31 @@ class OnIdentifyInterface : public LDAPInterface
}
}
- void OnError(const LDAPResult &r) anope_override
+ void OnError(const LDAPResult &r) override
{
Log(this->owner) << r.error;
}
};
-class OnRegisterInterface : public LDAPInterface
+class OnRegisterInterface final
+ : public LDAPInterface
{
- public:
+public:
OnRegisterInterface(Module *m) : LDAPInterface(m) { }
- void OnResult(const LDAPResult &r) anope_override
+ void OnResult(const LDAPResult &r) override
{
Log(this->owner) << "Successfully added newly created account to LDAP";
}
- void OnError(const LDAPResult &r) anope_override
+ void OnError(const LDAPResult &r) override
{
Log(this->owner) << "Error adding newly created account to LDAP: " << r.getError();
}
};
-class ModuleLDAPAuthentication : public Module
+class ModuleLDAPAuthentication final
+ : public Module
{
ServiceReference<LDAPProvider> ldap;
OnRegisterInterface orinterface;
@@ -198,20 +202,20 @@ class ModuleLDAPAuthentication : public Module
Anope::string password_attribute;
Anope::string disable_register_reason;
Anope::string disable_email_reason;
- public:
+public:
ModuleLDAPAuthentication(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), orinterface(this),
- dn(this, "m_ldap_authentication_dn")
+ dn(this, "ldap_authentication_dn")
{
me = this;
}
- void Prioritize() anope_override
+ void Prioritize() override
{
ModuleManager::SetPriority(this, PRIORITY_FIRST);
}
- void OnReload(Configuration::Conf *config) anope_override
+ void OnReload(Configuration::Conf *config) override
{
Configuration::Block *conf = Config->GetModule(this);
@@ -225,11 +229,13 @@ class ModuleLDAPAuthentication : public Module
this->disable_email_reason = conf->Get<const Anope::string>("disable_email_reason");
if (!email_attribute.empty())
+ {
/* Don't complain to users about how they need to update their email, we will do it for them */
- config->GetModule("nickserv")->Set("forceemail", "false");
+ config->GetModule("nickserv")->Set("forceemail", "no");
+ }
}
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
{
if (!this->disable_register_reason.empty())
{
@@ -249,16 +255,16 @@ class ModuleLDAPAuthentication : public Module
return EVENT_CONTINUE;
}
- void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *u, IdentifyRequest *req) override
{
if (!this->ldap)
return;
- IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap);
+ auto *ii = new IdentifyInfo(u, req, this->ldap);
this->ldap->BindAsAdmin(new IdentifyInterface(this, ii));
}
- void OnNickIdentify(User *u) anope_override
+ void OnNickIdentify(User *u) override
{
if (email_attribute.empty() || !this->ldap)
return;
@@ -270,7 +276,7 @@ class ModuleLDAPAuthentication : public Module
this->ldap->Search(new OnIdentifyInterface(this, u->GetUID()), *d, "(" + email_attribute + "=*)");
}
- void OnNickRegister(User *, NickAlias *na, const Anope::string &pass) anope_override
+ void OnNickRegister(User *, NickAlias *na, const Anope::string &pass) override
{
if (!this->disable_register_reason.empty() || !this->ldap)
return;
@@ -300,7 +306,7 @@ class ModuleLDAPAuthentication : public Module
this->ldap->Add(&this->orinterface, new_dn, attributes);
}
- void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+ void OnPreNickExpire(NickAlias *na, bool &expire) override
{
// We can't let nicks expire if they still have a group or
// there will be a zombie account left over that can't be
diff --git a/modules/extra/m_ldap_oper.cpp b/modules/ldap_oper.cpp
index fa64f2853..3f34eb7ca 100644
--- a/modules/extra/m_ldap_oper.cpp
+++ b/modules/ldap_oper.cpp
@@ -12,16 +12,17 @@
static std::set<Oper *> my_opers;
static Anope::string opertype_attribute;
-class IdentifyInterface : public LDAPInterface
+class IdentifyInterface final
+ : public LDAPInterface
{
Reference<User> u;
- public:
+public:
IdentifyInterface(Module *m, User *user) : LDAPInterface(m), u(user)
{
}
- void OnResult(const LDAPResult &r) anope_override
+ void OnResult(const LDAPResult &r) override
{
if (!u || !u->IsIdentified())
return;
@@ -65,17 +66,18 @@ class IdentifyInterface : public LDAPInterface
}
}
- void OnError(const LDAPResult &r) anope_override
+ void OnError(const LDAPResult &r) override
{
}
- void OnDelete() anope_override
+ void OnDelete() override
{
delete this;
}
};
-class LDAPOper : public Module
+class LDAPOper final
+ : public Module
{
ServiceReference<LDAPProvider> ldap;
@@ -83,14 +85,14 @@ class LDAPOper : public Module
Anope::string password;
Anope::string basedn;
Anope::string filter;
- public:
+public:
LDAPOper(const Anope::string &modname, const Anope::string &creator) :
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main")
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = Config->GetModule(this);
@@ -100,17 +102,17 @@ class LDAPOper : public Module
this->filter = config->Get<const Anope::string>("filter");
opertype_attribute = config->Get<const Anope::string>("opertype_attribute");
- for (std::set<Oper *>::iterator it = my_opers.begin(), it_end = my_opers.end(); it != it_end; ++it)
- delete *it;
+ for (const auto *oper : my_opers)
+ delete oper;
my_opers.clear();
}
- void OnNickIdentify(User *u) anope_override
+ void OnNickIdentify(User *u) override
{
try
{
if (!this->ldap)
- throw LDAPException("No LDAP interface. Is m_ldap loaded and configured correctly?");
+ throw LDAPException("No LDAP interface. Is ldap loaded and configured correctly?");
else if (this->basedn.empty() || this->filter.empty() || opertype_attribute.empty())
throw LDAPException("Could not search LDAP for opertype settings, invalid configuration.");
@@ -124,7 +126,7 @@ class LDAPOper : public Module
}
}
- void OnDelCore(NickCore *nc) anope_override
+ void OnDelCore(NickCore *nc) override
{
if (nc->o != NULL && my_opers.count(nc->o) > 0)
{
diff --git a/modules/m_xmlrpc_main.cpp b/modules/m_xmlrpc_main.cpp
deleted file mode 100644
index f72ee1b63..000000000
--- a/modules/m_xmlrpc_main.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- *
- * (C) 2010-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "module.h"
-#include "modules/xmlrpc.h"
-
-static Module *me;
-
-class XMLRPCIdentifyRequest : public IdentifyRequest
-{
- XMLRPCRequest request;
- HTTPReply repl; /* Request holds a reference to the HTTPReply, because we might exist long enough to invalidate it
- we'll copy it here then reset the reference before we use it */
- Reference<HTTPClient> client;
- Reference<XMLRPCServiceInterface> xinterface;
-
- public:
- XMLRPCIdentifyRequest(Module *m, XMLRPCRequest& req, HTTPClient *c, XMLRPCServiceInterface* iface, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), request(req), repl(request.r), client(c), xinterface(iface) { }
-
- void OnSuccess() anope_override
- {
- if (!xinterface || !client)
- return;
-
- request.r = this->repl;
-
- request.reply("result", "Success");
- request.reply("account", GetAccount());
-
- xinterface->Reply(request);
- client->SendReply(&request.r);
- }
-
- void OnFail() anope_override
- {
- if (!xinterface || !client)
- return;
-
- request.r = this->repl;
-
- request.reply("error", "Invalid password");
-
- xinterface->Reply(request);
- client->SendReply(&request.r);
- }
-};
-
-class MyXMLRPCEvent : public XMLRPCEvent
-{
- public:
- bool Run(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) anope_override
- {
- if (request.name == "command")
- this->DoCommand(iface, client, request);
- else if (request.name == "checkAuthentication")
- return this->DoCheckAuthentication(iface, client, request);
- else if (request.name == "stats")
- this->DoStats(iface, client, request);
- else if (request.name == "channel")
- this->DoChannel(iface, client, request);
- else if (request.name == "user")
- this->DoUser(iface, client, request);
- else if (request.name == "opers")
- this->DoOperType(iface, client, request);
- else if (request.name == "notice")
- this->DoNotice(iface, client, request);
-
- return true;
- }
-
- private:
- void DoCommand(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- Anope::string service = request.data.size() > 0 ? request.data[0] : "";
- Anope::string user = request.data.size() > 1 ? request.data[1] : "";
- Anope::string command = request.data.size() > 2 ? request.data[2] : "";
-
- if (service.empty() || user.empty() || command.empty())
- request.reply("error", "Invalid parameters");
- else
- {
- BotInfo *bi = BotInfo::Find(service, true);
- if (!bi)
- request.reply("error", "Invalid service");
- else
- {
- request.reply("result", "Success");
-
- NickAlias *na = NickAlias::Find(user);
-
- Anope::string out;
-
- struct XMLRPCommandReply : CommandReply
- {
- Anope::string &str;
-
- XMLRPCommandReply(Anope::string &s) : str(s) { }
-
- void SendMessage(BotInfo *, const Anope::string &msg) anope_override
- {
- str += msg + "\n";
- };
- }
- reply(out);
-
- User *u = User::Find(user, true);
- CommandSource source(user, u, na ? *na->nc : NULL, &reply, bi);
- Command::Run(source, command);
-
- if (!out.empty())
- request.reply("return", iface->Sanitize(out));
- }
- }
- }
-
- bool DoCheckAuthentication(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- Anope::string username = request.data.size() > 0 ? request.data[0] : "";
- Anope::string password = request.data.size() > 1 ? request.data[1] : "";
-
- if (username.empty() || password.empty())
- request.reply("error", "Invalid parameters");
- else
- {
- XMLRPCIdentifyRequest *req = new XMLRPCIdentifyRequest(me, request, client, iface, username, password);
- FOREACH_MOD(OnCheckAuthentication, (NULL, req));
- req->Dispatch();
- return false;
- }
-
- return true;
- }
-
- void DoStats(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- request.reply("uptime", stringify(Anope::CurTime - Anope::StartTime));
- request.reply("uplinkname", Me->GetLinks().front()->GetName());
- {
- Anope::string buf;
- for (std::set<Anope::string>::iterator it = Servers::Capab.begin(); it != Servers::Capab.end(); ++it)
- buf += " " + *it;
- if (!buf.empty())
- buf.erase(buf.begin());
- request.reply("uplinkcapab", buf);
- }
- request.reply("usercount", stringify(UserListByNick.size()));
- request.reply("maxusercount", stringify(MaxUserCount));
- request.reply("channelcount", stringify(ChannelList.size()));
- }
-
- void DoChannel(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- if (request.data.empty())
- return;
-
- Channel *c = Channel::Find(request.data[0]);
-
- request.reply("name", iface->Sanitize(c ? c->name : request.data[0]));
-
- if (c)
- {
- request.reply("bancount", stringify(c->HasMode("BAN")));
- int count = 0;
- std::vector<Anope::string> v = c->GetModeList("BAN");
- for (unsigned int i = 0; i < v.size(); ++i)
- request.reply("ban" + stringify(++count), iface->Sanitize(v[i]));
-
- request.reply("exceptcount", stringify(c->HasMode("EXCEPT")));
- count = 0;
- v = c->GetModeList("EXCEPT");
- for (unsigned int i = 0; i < v.size(); ++i)
- request.reply("except" + stringify(++count), iface->Sanitize(v[i]));
-
- request.reply("invitecount", stringify(c->HasMode("INVITEOVERRIDE")));
- count = 0;
- v = c->GetModeList("INVITEOVERRIDE");
- for (unsigned int i = 0; i < v.size(); ++i)
- request.reply("invite" + stringify(++count), iface->Sanitize(v[i]));
-
- Anope::string users;
- for (Channel::ChanUserList::const_iterator it = c->users.begin(); it != c->users.end(); ++it)
- {
- ChanUserContainer *uc = it->second;
- users += uc->status.BuildModePrefixList() + uc->user->nick + " ";
- }
- if (!users.empty())
- {
- users.erase(users.length() - 1);
- request.reply("users", iface->Sanitize(users));
- }
-
- if (!c->topic.empty())
- request.reply("topic", iface->Sanitize(c->topic));
-
- if (!c->topic_setter.empty())
- request.reply("topicsetter", iface->Sanitize(c->topic_setter));
-
- request.reply("topictime", stringify(c->topic_time));
- request.reply("topicts", stringify(c->topic_ts));
- }
- }
-
- void DoUser(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- if (request.data.empty())
- return;
-
- User *u = User::Find(request.data[0]);
-
- request.reply("nick", iface->Sanitize(u ? u->nick : request.data[0]));
-
- if (u)
- {
- request.reply("ident", iface->Sanitize(u->GetIdent()));
- request.reply("vident", iface->Sanitize(u->GetVIdent()));
- request.reply("host", iface->Sanitize(u->host));
- if (!u->vhost.empty())
- request.reply("vhost", iface->Sanitize(u->vhost));
- if (!u->chost.empty())
- request.reply("chost", iface->Sanitize(u->chost));
- request.reply("ip", u->ip.addr());
- request.reply("timestamp", stringify(u->timestamp));
- request.reply("signon", stringify(u->signon));
- if (u->IsIdentified())
- {
- request.reply("account", iface->Sanitize(u->Account()->display));
- if (u->Account()->o)
- request.reply("opertype", iface->Sanitize(u->Account()->o->ot->GetName()));
- }
-
- Anope::string channels;
- for (User::ChanUserList::const_iterator it = u->chans.begin(); it != u->chans.end(); ++it)
- {
- ChanUserContainer *cc = it->second;
- channels += cc->status.BuildModePrefixList() + cc->chan->name + " ";
- }
- if (!channels.empty())
- {
- channels.erase(channels.length() - 1);
- request.reply("channels", channels);
- }
- }
- }
-
- void DoOperType(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i)
- {
- OperType *ot = Config->MyOperTypes[i];
- Anope::string perms;
-
- std::list<Anope::string> privs = ot->GetPrivs();
- for (std::list<Anope::string>::const_iterator it2 = privs.begin(), it2_end = privs.end(); it2 != it2_end; ++it2)
- perms += " " + *it2;
-
- std::list<Anope::string> commands = ot->GetCommands();
- for (std::list<Anope::string>::const_iterator it2 = commands.begin(), it2_end = commands.end(); it2 != it2_end; ++it2)
- perms += " " + *it2;
- request.reply(ot->GetName(), perms);
- }
- }
-
- void DoNotice(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request)
- {
- Anope::string from = request.data.size() > 0 ? request.data[0] : "";
- Anope::string to = request.data.size() > 1 ? request.data[1] : "";
- Anope::string message = request.data.size() > 2 ? request.data[2] : "";
-
- BotInfo *bi = BotInfo::Find(from, true);
- User *u = User::Find(to, true);
-
- if (!bi || !u || message.empty())
- return;
-
- u->SendMessage(bi, message);
-
- request.reply("result", "Success");
- }
-};
-
-class ModuleXMLRPCMain : public Module
-{
- ServiceReference<XMLRPCServiceInterface> xmlrpc;
-
- MyXMLRPCEvent stats;
-
- public:
- ModuleXMLRPCMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), xmlrpc("XMLRPCServiceInterface", "xmlrpc")
- {
- me = this;
-
- if (!xmlrpc)
- throw ModuleException("Unable to find xmlrpc reference, is m_xmlrpc loaded?");
-
- xmlrpc->Register(&stats);
- }
-
- ~ModuleXMLRPCMain()
- {
- if (xmlrpc)
- xmlrpc->Unregister(&stats);
- }
-};
-
-MODULE_INIT(ModuleXMLRPCMain)
diff --git a/modules/pseudoclients/memoserv.cpp b/modules/memoserv/memoserv.cpp
index ee98e18e5..a1399e8f6 100644
--- a/modules/pseudoclients/memoserv.cpp
+++ b/modules/memoserv/memoserv.cpp
@@ -11,37 +11,39 @@
#include "module.h"
-class MemoServCore : public Module, public MemoServService
+class MemoServCore final
+ : public Module
+ , public MemoServService
{
Reference<BotInfo> MemoServ;
- bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m)
+ static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m)
{
Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<const Anope::string>("memo_subject").c_str()),
message = Language::Translate(nc, Config->GetBlock("mail")->Get<const Anope::string>("memo_message").c_str());
subject = subject.replace_all_cs("%n", nc->display);
subject = subject.replace_all_cs("%s", m->sender);
- subject = subject.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1));
+ subject = subject.replace_all_cs("%d", Anope::ToString(mi->GetIndex(m) + 1));
subject = subject.replace_all_cs("%t", m->text);
subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
message = message.replace_all_cs("%n", nc->display);
message = message.replace_all_cs("%s", m->sender);
- message = message.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1));
+ message = message.replace_all_cs("%d", Anope::ToString(mi->GetIndex(m) + 1));
message = message.replace_all_cs("%t", m->text);
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
return Mail::Send(nc, subject, message);
}
- public:
+public:
MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
MemoServService(this)
{
}
- MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) anope_override
+ MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) override
{
bool ischan;
MemoInfo *mi = MemoInfo::GetMemoInfo(target, ischan);
@@ -77,7 +79,7 @@ class MemoServCore : public Module, public MemoServService
if (sender != NULL)
sender->lastmemosend = Anope::CurTime;
- Memo *m = new Memo();
+ auto *m = new Memo();
m->mi = mi;
mi->memos->push_back(m);
m->owner = target;
@@ -94,14 +96,12 @@ class MemoServCore : public Module, public MemoServService
if (ci->c)
{
- for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
+ for (const auto &[_, cu] : ci->c->users)
{
- ChanUserContainer *cu = it->second;
-
if (ci->AccessFor(cu->user).HasPriv("MEMO"))
{
if (cu->user->IsIdentified() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
- cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), ci->name.c_str(), mi->memos->size());
+ cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), MemoServ->GetQueryCommand().c_str(), ci->name.c_str(), mi->memos->size());
}
}
}
@@ -112,12 +112,11 @@ class MemoServCore : public Module, public MemoServService
if (nc->HasExt("MEMO_RECEIVE"))
{
- for (unsigned i = 0; i < nc->aliases->size(); ++i)
+ for (auto *na : *nc->aliases)
{
- const NickAlias *na = nc->aliases->at(i);
User *user = User::Find(na->nick, true);
if (user && user->IsIdentified())
- user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), mi->memos->size());
+ user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), MemoServ->GetQueryCommand().c_str(), mi->memos->size());
}
}
@@ -129,7 +128,7 @@ class MemoServCore : public Module, public MemoServService
return MEMO_SUCCESS;
}
- void Check(User *u) anope_override
+ void Check(User *u) override
{
const NickCore *nc = u->Account();
if (!nc)
@@ -140,7 +139,7 @@ class MemoServCore : public Module, public MemoServService
if (nc->memos.GetMemo(i)->unread)
++newcnt;
if (newcnt > 0)
- u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt);
+ u->SendMessage(MemoServ, newcnt, N_("You have %d new memo.", "You have %d new memos."), newcnt);
if (nc->memos.memomax > 0 && nc->memos.memos->size() >= static_cast<unsigned>(nc->memos.memomax))
{
if (nc->memos.memos->size() > static_cast<unsigned>(nc->memos.memomax))
@@ -150,7 +149,7 @@ class MemoServCore : public Module, public MemoServService
}
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
const Anope::string &msnick = conf->GetModule(this)->Get<const Anope::string>("client");
@@ -164,55 +163,55 @@ class MemoServCore : public Module, public MemoServService
MemoServ = bi;
}
- void OnNickCoreCreate(NickCore *nc) anope_override
+ void OnNickCoreCreate(NickCore *nc) override
{
nc->memos.memomax = Config->GetModule(this)->Get<int>("maxmemos");
}
- void OnCreateChan(ChannelInfo *ci) anope_override
+ void OnCreateChan(ChannelInfo *ci) override
{
ci->memos.memomax = Config->GetModule(this)->Get<int>("maxmemos");
}
- void OnBotDelete(BotInfo *bi) anope_override
+ void OnBotDelete(BotInfo *bi) override
{
if (bi == MemoServ)
MemoServ = NULL;
}
- void OnNickIdentify(User *u) anope_override
+ void OnNickIdentify(User *u) override
{
this->Check(u);
}
- void OnJoinChannel(User *u, Channel *c) anope_override
+ void OnJoinChannel(User *u, Channel *c) override
{
if (c->ci && !c->ci->memos.memos->empty() && c->ci->AccessFor(u).HasPriv("MEMO"))
{
if (c->ci->memos.memos->size() == 1)
- u->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str());
+ u->SendMessage(MemoServ, _("There is \002%zu\002 memo on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str());
else
- u->SendMessage(MemoServ, _("There are \002%d\002 memos on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str());
+ u->SendMessage(MemoServ, _("There are \002%zu\002 memos on channel %s."), c->ci->memos.memos->size(), c->ci->name.c_str());
}
}
- void OnUserAway(User *u, const Anope::string &message) anope_override
+ void OnUserAway(User *u, const Anope::string &message) override
{
if (message.empty())
this->Check(u);
}
- void OnNickUpdate(User *u) anope_override
+ void OnNickUpdate(User *u) override
{
this->Check(u);
}
- void OnUserConnect(User *user, bool &exempt) anope_override
+ void OnUserConnect(User *user, bool &exempt) override
{
this->Check(user);
}
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *MemoServ)
return EVENT_CONTINUE;
@@ -225,13 +224,13 @@ class MemoServCore : public Module, public MemoServService
return EVENT_CONTINUE;
}
- void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *MemoServ)
return;
source.Reply(_(" \n"
- "Type \002%s%s HELP \037command\037\002 for help on any of the\n"
- "above commands."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str());
+ "Type \002%s HELP \037command\037\002 for help on any of the\n"
+ "above commands."), MemoServ->GetQueryCommand().c_str());
}
};
diff --git a/modules/commands/ms_cancel.cpp b/modules/memoserv/ms_cancel.cpp
index 936995862..b423899b0 100644
--- a/modules/commands/ms_cancel.cpp
+++ b/modules/memoserv/ms_cancel.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandMSCancel : public Command
+class CommandMSCancel final
+ : public Command
{
- public:
+public:
CommandMSCancel(Module *creator) : Command(creator, "memoserv/cancel", 1, 1)
{
this->SetDesc(_("Cancel the last memo you sent"));
this->SetSyntax(_("{\037nick\037 | \037channel\037}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -77,7 +78,7 @@ class CommandMSCancel : public Command
source.Reply(_("No memo was cancelable."));
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -87,11 +88,12 @@ class CommandMSCancel : public Command
}
};
-class MSCancel : public Module
+class MSCancel final
+ : public Module
{
CommandMSCancel commandmscancel;
- public:
+public:
MSCancel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmscancel(this)
{
diff --git a/modules/commands/ms_check.cpp b/modules/memoserv/ms_check.cpp
index 19efba3fe..7c478b02b 100644
--- a/modules/commands/ms_check.cpp
+++ b/modules/memoserv/ms_check.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandMSCheck : public Command
+class CommandMSCheck final
+ : public Command
{
- public:
+public:
CommandMSCheck(Module *creator) : Command(creator, "memoserv/check", 1, 1)
{
this->SetDesc(_("Checks if last memo to a nick was read"));
this->SetSyntax(_("\037nick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &recipient = params[0];
@@ -62,7 +63,7 @@ class CommandMSCheck : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -72,11 +73,12 @@ class CommandMSCheck : public Command
}
};
-class MSCheck : public Module
+class MSCheck final
+ : public Module
{
CommandMSCheck commandmscheck;
- public:
+public:
MSCheck(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmscheck(this)
{
diff --git a/modules/commands/ms_del.cpp b/modules/memoserv/ms_del.cpp
index 2d1c9cb98..56700b0bd 100644
--- a/modules/commands/ms_del.cpp
+++ b/modules/memoserv/ms_del.cpp
@@ -11,18 +11,19 @@
#include "module.h"
-class MemoDelCallback : public NumberList
+class MemoDelCallback final
+ : public NumberList
{
CommandSource &source;
Command *cmd;
ChannelInfo *ci;
MemoInfo *mi;
- public:
+public:
MemoDelCallback(CommandSource &_source, Command *c, ChannelInfo *_ci, MemoInfo *_mi, const Anope::string &list) : NumberList(list, true), source(_source), cmd(c), ci(_ci), mi(_mi)
{
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > mi->memos->size())
return;
@@ -36,16 +37,17 @@ class MemoDelCallback : public NumberList
}
};
-class CommandMSDel : public Command
+class CommandMSDel final
+ : public Command
{
- public:
+public:
CommandMSDel(Module *creator) : Command(creator, "memoserv/del", 0, 2)
{
this->SetDesc(_("Delete a memo or memos"));
this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | ALL}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -98,7 +100,7 @@ class CommandMSDel : public Command
/* Delete last memo. */
FOREACH_MOD(OnMemoDel, (ci ? ci->name : source.nc->display, mi, mi->GetMemo(mi->memos->size() - 1)));
mi->Del(mi->memos->size() - 1);
- source.Reply(_("Memo %d has been deleted."), mi->memos->size() + 1);
+ source.Reply(_("Memo %zu has been deleted."), mi->memos->size() + 1);
if (ci)
Log(LOG_COMMAND, source, this, ci) << "on LAST memo";
}
@@ -122,7 +124,7 @@ class CommandMSDel : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -144,11 +146,12 @@ class CommandMSDel : public Command
}
};
-class MSDel : public Module
+class MSDel final
+ : public Module
{
CommandMSDel commandmsdel;
- public:
+public:
MSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsdel(this)
{
diff --git a/modules/commands/ms_ignore.cpp b/modules/memoserv/ms_ignore.cpp
index 522aad03e..52ec79944 100644
--- a/modules/commands/ms_ignore.cpp
+++ b/modules/memoserv/ms_ignore.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandMSIgnore : public Command
+class CommandMSIgnore final
+ : public Command
{
- public:
+public:
CommandMSIgnore(Module *creator) : Command(creator, "memoserv/ignore", 1, 3)
{
this->SetDesc(_("Manage the memo ignore list"));
@@ -22,7 +23,7 @@ class CommandMSIgnore : public Command
this->SetSyntax(_("[\037channel\037] LIST"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (Anope::ReadOnly)
{
@@ -50,7 +51,7 @@ class CommandMSIgnore : public Command
source.Reply(ACCESS_DENIED);
else if (command.equals_ci("ADD") && !param.empty())
{
- if (mi->ignores.size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
+ if (mi->ignores.size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "50"))
{
source.Reply(_("Sorry, the memo ignore list for \002%s\002 is full."), channel.c_str());
return;
@@ -58,7 +59,7 @@ class CommandMSIgnore : public Command
if (std::find(mi->ignores.begin(), mi->ignores.end(), param.ci_str()) == mi->ignores.end())
{
- mi->ignores.push_back(param.ci_str());
+ mi->ignores.emplace_back(param.ci_str());
source.Reply(_("\002%s\002 added to ignore list."), param.c_str());
}
else
@@ -84,10 +85,10 @@ class CommandMSIgnore : public Command
{
ListFormatter list(source.GetAccount());
list.AddColumn(_("Mask"));
- for (unsigned i = 0; i < mi->ignores.size(); ++i)
+ for (const auto &ignore : mi->ignores)
{
ListFormatter::ListEntry entry;
- entry["Mask"] = mi->ignores[i];
+ entry["Mask"] = ignore;
list.AddEntry(entry);
}
@@ -96,8 +97,8 @@ class CommandMSIgnore : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
else
@@ -106,7 +107,7 @@ class CommandMSIgnore : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -118,11 +119,12 @@ class CommandMSIgnore : public Command
}
};
-class MSIgnore : public Module
+class MSIgnore final
+ : public Module
{
CommandMSIgnore commandmsignore;
- public:
+public:
MSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsignore(this)
{
diff --git a/modules/commands/ms_info.cpp b/modules/memoserv/ms_info.cpp
index 8edcb2a40..91acaabde 100644
--- a/modules/commands/ms_info.cpp
+++ b/modules/memoserv/ms_info.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandMSInfo : public Command
+class CommandMSInfo final
+ : public Command
{
- public:
+public:
CommandMSInfo(Module *creator) : Command(creator, "memoserv/info", 0, 1)
{
this->SetDesc(_("Displays information about your memos"));
this->SetSyntax(_("[\037nick\037 | \037channel\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
NickCore *nc = source.nc;
const MemoInfo *mi;
@@ -80,18 +81,19 @@ class CommandMSInfo : public Command
}
else
{
- unsigned count = 0, i, end;
- for (i = 0, end = mi->memos->size(); i < end; ++i)
+ size_t count = 0;
+ for (size_t i = 0; i < mi->memos->size(); ++i)
if (mi->GetMemo(i)->unread)
++count;
+
if (count == mi->memos->size())
- source.Reply(_("%s currently has \002%d\002 memos; all of them are unread."), nname.c_str(), count);
+ source.Reply(_("%s currently has \002%zu\002 memos; all of them are unread."), nname.c_str(), count);
else if (!count)
- source.Reply(_("%s currently has \002%d\002 memos."), nname.c_str(), mi->memos->size());
+ source.Reply(_("%s currently has \002%zu\002 memos."), nname.c_str(), mi->memos->size());
else if (count == 1)
- source.Reply(_("%s currently has \002%d\002 memos, of which \0021\002 is unread."), nname.c_str(), mi->memos->size());
+ source.Reply(_("%s currently has \002%zu\002 memos, of which \0021\002 is unread."), nname.c_str(), mi->memos->size());
else
- source.Reply(_("%s currently has \002%d\002 memos, of which \002%d\002 are unread."), nname.c_str(), mi->memos->size(), count);
+ source.Reply(_("%s currently has \002%zu\002 memos, of which \002%zu\002 are unread."), nname.c_str(), mi->memos->size(), count);
}
if (!mi->memomax)
{
@@ -137,18 +139,19 @@ class CommandMSInfo : public Command
}
else
{
- unsigned count = 0, i, end;
- for (i = 0, end = mi->memos->size(); i < end; ++i)
+ size_t count = 0;
+ for (size_t i = 0; i < mi->memos->size(); ++i)
if (mi->GetMemo(i)->unread)
++count;
+
if (count == mi->memos->size())
- source.Reply(_("You currently have \002%d\002 memos; all of them are unread."), count);
+ source.Reply(_("You currently have \002%zu\002 memos; all of them are unread."), count);
else if (!count)
- source.Reply(_("You currently have \002%d\002 memos."), mi->memos->size());
+ source.Reply(_("You currently have \002%zu\002 memos."), mi->memos->size());
else if (count == 1)
- source.Reply(_("You currently have \002%d\002 memos, of which \0021\002 is unread."), mi->memos->size());
+ source.Reply(_("You currently have \002%zu\002 memos, of which \0021\002 is unread."), mi->memos->size());
else
- source.Reply(_("You currently have \002%d\002 memos, of which \002%d\002 are unread."), mi->memos->size(), count);
+ source.Reply(_("You currently have \002%zu\002 memos, of which \002%zu\002 are unread."), mi->memos->size(), count);
}
if (!mi->memomax)
@@ -197,7 +200,7 @@ class CommandMSInfo : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -216,11 +219,12 @@ class CommandMSInfo : public Command
}
};
-class MSInfo : public Module
+class MSInfo final
+ : public Module
{
CommandMSInfo commandmsinfo;
- public:
+public:
MSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsinfo(this)
{
diff --git a/modules/commands/ms_list.cpp b/modules/memoserv/ms_list.cpp
index eb1b5cfa3..d421efe86 100644
--- a/modules/commands/ms_list.cpp
+++ b/modules/memoserv/ms_list.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandMSList : public Command
+class CommandMSList final
+ : public Command
{
- public:
+public:
CommandMSList(Module *creator) : Command(creator, "memoserv/list", 0, 2)
{
this->SetDesc(_("List your memos"));
this->SetSyntax(_("[\037channel\037] [\037list\037 | NEW]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string param = !params.empty() ? params[0] : "", chan;
@@ -65,17 +66,18 @@ class CommandMSList : public Command
if (!param.empty() && isdigit(param[0]))
{
- class MemoListCallback : public NumberList
+ class MemoListCallback final
+ : public NumberList
{
ListFormatter &list;
CommandSource &source;
const MemoInfo *mi;
- public:
+ public:
MemoListCallback(ListFormatter &_list, CommandSource &_source, const MemoInfo *_mi, const Anope::string &numlist) : NumberList(numlist, false), list(_list), source(_source), mi(_mi)
{
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > mi->memos->size())
return;
@@ -83,7 +85,7 @@ class CommandMSList : public Command
const Memo *m = mi->GetMemo(number - 1);
ListFormatter::ListEntry entry;
- entry["Number"] = (m->unread ? "* " : " ") + stringify(number);
+ entry["Number"] = (m->unread ? "* " : " ") + Anope::ToString(number);
entry["Sender"] = m->sender;
entry["Date/Time"] = Anope::strftime(m->time, source.GetAccount());
this->list.AddEntry(entry);
@@ -118,7 +120,7 @@ class CommandMSList : public Command
const Memo *m = mi->GetMemo(i);
ListFormatter::ListEntry entry;
- entry["Number"] = (m->unread ? "* " : " ") + stringify(i + 1);
+ entry["Number"] = (m->unread ? "* " : " ") + Anope::ToString(i + 1);
entry["Sender"] = m->sender;
entry["Date/Time"] = Anope::strftime(m->time, source.GetAccount());
list.AddEntry(entry);
@@ -129,13 +131,13 @@ class CommandMSList : public Command
list.Process(replies);
source.Reply(_("Memos for %s:"), ci ? ci->name.c_str() : source.GetNick().c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -149,11 +151,12 @@ class CommandMSList : public Command
}
};
-class MSList : public Module
+class MSList final
+ : public Module
{
CommandMSList commandmslist;
- public:
+public:
MSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmslist(this)
{
diff --git a/modules/commands/ms_read.cpp b/modules/memoserv/ms_read.cpp
index aa2f19ec4..d1a773838 100644
--- a/modules/commands/ms_read.cpp
+++ b/modules/memoserv/ms_read.cpp
@@ -47,25 +47,26 @@ static void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Ano
m->receipt = false;
}
-class MemoListCallback : public NumberList
+class MemoListCallback final
+ : public NumberList
{
CommandSource &source;
MemoInfo *mi;
const ChannelInfo *ci;
bool found;
- public:
+public:
MemoListCallback(CommandSource &_source, MemoInfo *_mi, const ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), source(_source), mi(_mi), ci(_ci)
{
found = false;
}
- ~MemoListCallback()
+ ~MemoListCallback() override
{
if (!found)
source.Reply(_("No memos to display."));
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > mi->memos->size())
return;
@@ -90,9 +91,9 @@ class MemoListCallback : public NumberList
if (Command::FindCommandFromService("memoserv/del", bi, cmd))
{
if (ci)
- source.Reply(_("To delete, type: \002%s%s %s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
+ source.Reply(_("To delete, type: \002%s %s %s %d\002"), bi->GetQueryCommand().c_str(), cmd.c_str(), ci->name.c_str(), index + 1);
else
- source.Reply(_("To delete, type: \002%s%s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), index + 1);
+ source.Reply(_("To delete, type: \002%s %s %d\002"), bi->GetQueryCommand().c_str(), cmd.c_str(), index + 1);
}
source.Reply("%s", m->text.c_str());
@@ -104,16 +105,17 @@ class MemoListCallback : public NumberList
}
};
-class CommandMSRead : public Command
+class CommandMSRead final
+ : public Command
{
- public:
+public:
CommandMSRead(Module *creator) : Command(creator, "memoserv/read", 1, 2)
{
this->SetDesc(_("Read a memo or memos"));
this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | NEW | ALL}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
MemoInfo *mi;
@@ -192,7 +194,7 @@ class CommandMSRead : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -209,11 +211,12 @@ class CommandMSRead : public Command
}
};
-class MSRead : public Module
+class MSRead final
+ : public Module
{
CommandMSRead commandmsread;
- public:
+public:
MSRead(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsread(this)
{
diff --git a/modules/commands/ms_rsend.cpp b/modules/memoserv/ms_rsend.cpp
index b6c322c0f..8bcb7b3d9 100644
--- a/modules/commands/ms_rsend.cpp
+++ b/modules/memoserv/ms_rsend.cpp
@@ -16,23 +16,24 @@ namespace
ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
}
-class CommandMSRSend : public Command
+class CommandMSRSend final
+ : public Command
{
- public:
+public:
CommandMSRSend(Module *creator) : Command(creator, "memoserv/rsend", 2, 2)
{
this->SetDesc(_("Sends a memo and requests a read receipt"));
this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!memoserv)
return;
if (Anope::ReadOnly && !source.IsOper())
{
- source.Reply(MEMO_SEND_DISABLED);
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -55,7 +56,11 @@ class CommandMSRSend : public Command
if (result == MemoServService::MEMO_INVALID_TARGET)
source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str());
else if (result == MemoServService::MEMO_TOO_FAST)
- source.Reply(_("Please wait %d seconds before using the %s command again."), Config->GetModule("memoserv")->Get<time_t>("senddelay"), source.command.c_str());
+ {
+ auto lastmemosend = source.GetUser() ? source.GetUser()->lastmemosend : 0;
+ auto waitperiod = (lastmemosend + Config->GetModule("memoserv")->Get<unsigned long>("senddelay")) - Anope::CurTime;
+ source.Reply(_("Please wait %s before using the %s command again."), Anope::Duration(waitperiod, source.GetAccount()).c_str(), source.command.c_str());
+ }
else if (result == MemoServService::MEMO_TARGET_FULL)
source.Reply(_("Sorry, %s currently has too many memos and cannot receive more."), nick.c_str());
else
@@ -73,7 +78,7 @@ class CommandMSRSend : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -88,11 +93,12 @@ class CommandMSRSend : public Command
}
};
-class MSRSend : public Module
+class MSRSend final
+ : public Module
{
CommandMSRSend commandmsrsend;
- public:
+public:
MSRSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsrsend(this)
{
diff --git a/modules/commands/ms_send.cpp b/modules/memoserv/ms_send.cpp
index 339d2ac6a..e1ab3169d 100644
--- a/modules/commands/ms_send.cpp
+++ b/modules/memoserv/ms_send.cpp
@@ -16,16 +16,17 @@ namespace
ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
}
-class CommandMSSend : public Command
+class CommandMSSend final
+ : public Command
{
- public:
+public:
CommandMSSend(Module *creator) : Command(creator, "memoserv/send", 2, 2)
{
this->SetDesc(_("Send a memo to a nick or channel"));
this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!memoserv)
return;
@@ -35,7 +36,7 @@ class CommandMSSend : public Command
if (Anope::ReadOnly && !source.IsOper())
{
- source.Reply(MEMO_SEND_DISABLED);
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -54,12 +55,16 @@ class CommandMSSend : public Command
else if (result == MemoServService::MEMO_INVALID_TARGET)
source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str());
else if (result == MemoServService::MEMO_TOO_FAST)
- source.Reply(_("Please wait %d seconds before using the %s command again."), Config->GetModule("memoserv")->Get<time_t>("senddelay"), source.command.c_str());
+ {
+ auto lastmemosend = source.GetUser() ? source.GetUser()->lastmemosend : 0;
+ auto waitperiod = (lastmemosend + Config->GetModule("memoserv")->Get<unsigned long>("senddelay")) - Anope::CurTime;
+ source.Reply(_("Please wait %s before using the %s command again."), Anope::Duration(waitperiod, source.GetAccount()).c_str(), source.command.c_str());
+ }
else if (result == MemoServService::MEMO_TARGET_FULL)
source.Reply(_("Sorry, %s currently has too many memos and cannot receive more."), nick.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -71,11 +76,12 @@ class CommandMSSend : public Command
}
};
-class MSSend : public Module
+class MSSend final
+ : public Module
{
CommandMSSend commandmssend;
- public:
+public:
MSSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmssend(this)
{
diff --git a/modules/commands/ms_sendall.cpp b/modules/memoserv/ms_sendall.cpp
index bc26719b9..dfff37033 100644
--- a/modules/commands/ms_sendall.cpp
+++ b/modules/memoserv/ms_sendall.cpp
@@ -16,16 +16,17 @@ namespace
ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
}
-class CommandMSSendAll : public Command
+class CommandMSSendAll final
+ : public Command
{
- public:
+public:
CommandMSSendAll(Module *creator) : Command(creator, "memoserv/sendall", 1, 1)
{
this->SetDesc(_("Send a memo to all registered users"));
this->SetSyntax(_("\037memo-text\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!memoserv)
return;
@@ -34,10 +35,8 @@ class CommandMSSendAll : public Command
Log(LOG_ADMIN, source, this) << "to send " << text;
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- const NickCore *nc = it->second;
-
if (nc != source.nc)
memoserv->Send(source.GetNick(), nc->display, text);
}
@@ -45,7 +44,7 @@ class CommandMSSendAll : public Command
source.Reply(_("A massmemo has been sent to all registered users."));
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -54,11 +53,12 @@ class CommandMSSendAll : public Command
}
};
-class MSSendAll : public Module
+class MSSendAll final
+ : public Module
{
CommandMSSendAll commandmssendall;
- public:
+public:
MSSendAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmssendall(this)
{
diff --git a/modules/commands/ms_set.cpp b/modules/memoserv/ms_set.cpp
index 4e309db4c..cce30581b 100644
--- a/modules/commands/ms_set.cpp
+++ b/modules/memoserv/ms_set.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandMSSet : public Command
+class CommandMSSet final
+ : public Command
{
- private:
+private:
void DoNotify(CommandSource &source, const std::vector<Anope::string> &params, MemoInfo *mi)
{
const Anope::string &param = params[1];
@@ -134,12 +135,8 @@ class CommandMSSet : public Command
else
nc->Shrink<bool>("MEMO_HARDMAX");
}
- limit = -1;
- try
- {
- limit = convertTo<int16_t>(p1);
- }
- catch (const ConvertException &) { }
+
+ limit = Anope::Convert<int16_t>(p1, -1);
}
else
{
@@ -159,12 +156,8 @@ class CommandMSSet : public Command
return;
}
int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos");
- limit = -1;
- try
- {
- limit = convertTo<int16_t>(p1);
- }
- catch (const ConvertException &) { }
+ limit = Anope::Convert<int16_t>(p1, -1);
+
/* The first character is a digit, but we could still go negative
* from overflow... watch out! */
if (limit < 0 || (max_memos > 0 && limit > max_memos))
@@ -200,20 +193,20 @@ class CommandMSSet : public Command
}
return;
}
- public:
+public:
CommandMSSet(Module *creator) : Command(creator, "memoserv/set", 2, 5)
{
this->SetDesc(_("Set options related to memos"));
this->SetSyntax(_("\037option\037 \037parameters\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
MemoInfo *mi = &source.nc->memos;
if (Anope::ReadOnly)
- source.Reply(_("Sorry, memo option setting is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
else if (cmd.equals_ci("NOTIFY"))
return this->DoNotify(source, params, mi);
else if (cmd.equals_ci("LIMIT"))
@@ -226,7 +219,7 @@ class CommandMSSet : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (subcommand.empty())
{
@@ -239,8 +232,8 @@ class CommandMSSet : public Command
" LIMIT Sets the maximum number of memos you can\n"
" receive\n"
" \n"
- "Type \002%s%s HELP %s \037option\037\002 for more information\n"
- "on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
+ "Type \002%s HELP %s \037option\037\002 for more information\n"
+ "on a specific option."), source.service->GetQueryCommand().c_str(), source.command.c_str());
}
else if (subcommand.equals_ci("NOTIFY"))
source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n"
@@ -298,12 +291,13 @@ class CommandMSSet : public Command
}
};
-class MSSet : public Module
+class MSSet final
+ : public Module
{
CommandMSSet commandmsset;
SerializableExtensibleItem<bool> memo_signon, memo_receive, memo_mail, memo_hardmax;
- public:
+public:
MSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsset(this), memo_signon(this, "MEMO_SIGNON"), memo_receive(this, "MEMO_RECEIVE"), memo_mail(this, "MEMO_MAIL"),
memo_hardmax(this, "MEMO_HARDMAX")
diff --git a/modules/commands/ms_staff.cpp b/modules/memoserv/ms_staff.cpp
index 8994f6a72..919ee451f 100644
--- a/modules/commands/ms_staff.cpp
+++ b/modules/memoserv/ms_staff.cpp
@@ -16,32 +16,31 @@ namespace
ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
}
-class CommandMSStaff : public Command
+class CommandMSStaff final
+ : public Command
{
- public:
+public:
CommandMSStaff(Module *creator) : Command(creator, "memoserv/staff", 1, 1)
{
this->SetDesc(_("Send a memo to all opers/admins"));
this->SetSyntax(_("\037memo-text\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!memoserv)
return;
const Anope::string &text = params[0];
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- const NickCore *nc = it->second;
-
if (source.nc != nc && nc->IsServicesOper())
memoserv->Send(source.GetNick(), nc->display, text, true);
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -51,11 +50,12 @@ class CommandMSStaff : public Command
}
};
-class MSStaff : public Module
+class MSStaff final
+ : public Module
{
CommandMSStaff commandmsstaff;
- public:
+public:
MSStaff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandmsstaff(this)
{
diff --git a/modules/pseudoclients/nickserv.cpp b/modules/nickserv/nickserv.cpp
index 4d8a0e611..25d9a364e 100644
--- a/modules/pseudoclients/nickserv.cpp
+++ b/modules/nickserv/nickserv.cpp
@@ -16,20 +16,26 @@ static std::set<NickServCollide *> collides;
/** Timer for colliding nicks to force people off of nicknames
*/
-class NickServCollide : public Timer
+class NickServCollide final
+ : public Timer
{
NickServService *service;
Reference<User> u;
time_t ts;
Reference<NickAlias> na;
- public:
- NickServCollide(Module *me, NickServService *nss, User *user, NickAlias *nick, time_t delay) : Timer(me, delay), service(nss), u(user), ts(user->timestamp), na(nick)
+public:
+ NickServCollide(Module *me, NickServService *nss, User *user, NickAlias *nick, time_t delay)
+ : Timer(me, delay)
+ , service(nss)
+ , u(user)
+ , ts(user->timestamp)
+ , na(nick)
{
collides.insert(this);
}
- ~NickServCollide()
+ ~NickServCollide() override
{
collides.erase(this);
}
@@ -44,7 +50,7 @@ class NickServCollide : public Timer
return na;
}
- void Tick(time_t t) anope_override
+ void Tick() override
{
if (!u || !na)
return;
@@ -58,17 +64,21 @@ class NickServCollide : public Timer
/** Timer for removing HELD status from nicks.
*/
-class NickServHeld : public Timer
+class NickServHeld final
+ : public Timer
{
Reference<NickAlias> na;
Anope::string nick;
- public:
- NickServHeld(Module *me, NickAlias *n, long l) : Timer(me, l), na(n), nick(na->nick)
+public:
+ NickServHeld(Module *me, NickAlias *n, time_t l)
+ : Timer(me, l)
+ , na(n)
+ , nick(na->nick)
{
n->Extend<bool>("HELD");
}
- void Tick(time_t)
+ void Tick() override
{
if (na)
na->Shrink<bool>("HELD");
@@ -80,13 +90,17 @@ static Anope::map<NickServRelease *> NickServReleases;
/** Timer for releasing nicks to be available for use
*/
-class NickServRelease : public User, public Timer
+class NickServRelease final
+ : public User
+ , public Timer
{
Anope::string nick;
- public:
- NickServRelease(Module *me, NickAlias *na, time_t delay) : User(na->nick, Config->GetModule("nickserv")->Get<const Anope::string>("enforceruser", "user"),
- Config->GetModule("nickserv")->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", IRCD->UID_Retrieve(), NULL), Timer(me, delay), nick(na->nick)
+public:
+ NickServRelease(Module *me, NickAlias *na, time_t delay)
+ : User(na->nick, Config->GetModule(me)->Get<const Anope::string>("enforceruser", "user"), Config->GetModule(me)->Get<const Anope::string>("enforcerhost", Me->GetName()), "", "", Me, "Services Enforcer", Anope::CurTime, "", {}, IRCD->UID_Retrieve(), NULL)
+ , Timer(me, delay)
+ , nick(na->nick)
{
/* Erase the current release timer and use the new one */
Anope::map<NickServRelease *>::iterator nit = NickServReleases.find(this->nick);
@@ -96,21 +110,25 @@ class NickServRelease : public User, public Timer
delete nit->second;
}
- NickServReleases.insert(std::make_pair(this->nick, this));
+ NickServReleases.emplace(this->nick, this);
IRCD->SendClientIntroduction(this);
}
- ~NickServRelease()
+ ~NickServRelease() override
{
IRCD->SendQuit(this, "");
NickServReleases.erase(this->nick);
}
- void Tick(time_t t) anope_override { }
+ void Tick() override
+ {
+ }
};
-class NickServCore : public Module, public NickServService
+class NickServCore final
+ : public Module
+ , public NickServService
{
Reference<BotInfo> NickServ;
std::vector<Anope::string> defaults;
@@ -122,41 +140,59 @@ class NickServCore : public Module, public NickServService
{
collided.Unset(na);
- new NickServHeld(this, na, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
+ new NickServHeld(this, na, Config->GetModule(this)->Get<time_t>("releasetimeout", "1m"));
if (IRCD->CanSVSHold)
- IRCD->SendSVSHold(na->nick, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
+ IRCD->SendSVSHold(na->nick, Config->GetModule(this)->Get<time_t>("releasetimeout", "1m"));
else
- new NickServRelease(this, na, Config->GetModule("nickserv")->Get<time_t>("releasetimeout", "1m"));
+ new NickServRelease(this, na, Config->GetModule(this)->Get<time_t>("releasetimeout", "1m"));
}
}
- public:
+public:
NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
NickServService(this), held(this, "HELD"), collided(this, "COLLIDED")
{
}
- ~NickServCore()
+ ~NickServCore() override
{
OnShutdown();
}
- void OnShutdown() anope_override
+ void OnShutdown() override
{
/* On shutdown, restart, or mod unload, remove all of our holds for nicks (svshold or qlines)
* because some IRCds do not allow us to have these automatically expire
*/
- for (nickalias_map::const_iterator it = NickAliasList->begin(); it != NickAliasList->end(); ++it)
- this->Release(it->second);
+ for (const auto &[_, na] : *NickAliasList)
+ this->Release(na);
}
- void OnRestart() anope_override
+ void OnRestart() override
{
OnShutdown();
}
- void Validate(User *u) anope_override
+ bool IsGuestNick(const Anope::string &nick) const override
+ {
+ const auto guestnick = Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####");
+ if (guestnick.empty())
+ return false; // No guest nick.
+
+ const auto minlen = std::min(nick.length(), guestnick.length());
+ for (size_t idx = 0; idx < minlen; ++idx)
+ {
+ if (guestnick[idx] == '#' && !isdigit(nick[idx]))
+ return false;
+
+ if (Anope::tolower(guestnick[idx]) != Anope::tolower(nick[idx]))
+ return false;
+ }
+ return true;
+ }
+
+ void Validate(User *u) override
{
NickAlias *na = NickAlias::Find(u->nick);
if (!na)
@@ -172,27 +208,14 @@ class NickServCore : public Module, public NickServService
else if (MOD_RESULT == EVENT_ALLOW)
return;
- if (!na->nc->HasExt("NS_SECURE") && u->IsRecognized())
- {
- na->last_seen = Anope::CurTime;
- na->last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
- na->last_realname = u->realname;
- return;
- }
-
if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
return;
- bool on_access = u->IsRecognized(false);
-
- if (on_access || !na->nc->HasExt("KILL_IMMED"))
+ if (!na->nc->HasExt("KILL_IMMED"))
{
- if (na->nc->HasExt("NS_SECURE"))
- u->SendMessage(NickServ, NICK_IS_SECURE, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
- else
- u->SendMessage(NickServ, NICK_IS_REGISTERED, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
+ u->SendMessage(NickServ, NICK_IS_SECURE, NickServ->GetQueryCommand().c_str());
}
- if (na->nc->HasExt("KILLPROTECT") && !on_access)
+ if (na->nc->HasExt("KILLPROTECT"))
{
if (na->nc->HasExt("KILL_IMMED"))
{
@@ -215,7 +238,7 @@ class NickServCore : public Module, public NickServService
}
- void OnUserLogin(User *u) anope_override
+ void OnUserLogin(User *u) override
{
NickAlias *na = NickAlias::Find(u->nick);
if (na && *na->nc == u->Account() && !Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && !na->nc->HasExt("UNCONFIRMED"))
@@ -223,43 +246,60 @@ class NickServCore : public Module, public NickServService
const Anope::string &modesonid = Config->GetModule(this)->Get<Anope::string>("modesonid");
if (!modesonid.empty())
- u->SetModes(NickServ, "%s", modesonid.c_str());
+ u->SetModes(NickServ, modesonid);
}
- void Collide(User *u, NickAlias *na) anope_override
+ void Collide(User *u, NickAlias *na) override
{
if (na)
collided.Set(na);
if (IRCD->CanSVSNick)
{
- unsigned nicklen = Config->GetBlock("networkinfo")->Get<unsigned>("nicklen");
- const Anope::string &guestprefix = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
-
+ auto guestnickok = false;
Anope::string guestnick;
+ for (auto i = 0; i < 10; ++i)
+ {
+ guestnick.clear();
+ for (auto guestnickchr : Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####").substr(0, IRCD->MaxNick))
+ {
+ if (guestnickchr == '#')
+ guestnick.append(Anope::ToString(abs(Anope::RandomNumber()) % 10));
+ else
+ guestnick.push_back(guestnickchr);
+ }
+
+ // A guest nick is valid if it is non-empty and is not in use.
+ if (!guestnick.empty() && !User::Find(guestnick, true))
+ {
+ guestnickok = true;
+ break;
+ }
+ }
- int i = 0;
- do
+ // If we can't find a guest nick and the IRCd supports
+ // uids then we should use that as the backup guest
+ // nickname.
+ if (!guestnickok && IRCD->RequiresID)
{
- guestnick = guestprefix + stringify(static_cast<uint16_t>(rand()));
- if (guestnick.length() > nicklen)
- guestnick = guestnick.substr(0, nicklen);
+ guestnickok = true;
+ guestnick = u->GetUID();
}
- while (User::Find(guestnick) && i++ < 10);
- if (i == 11)
- u->Kill(*NickServ, "Services nickname-enforcer kill");
- else
+ if (guestnickok)
{
u->SendMessage(*NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str());
IRCD->SendForceNickChange(u, guestnick, Anope::CurTime);
+ return;
}
}
- else
- u->Kill(*NickServ, "Services nickname-enforcer kill");
+
+ // We can't change the user's nickname or we can't find an
+ // acceptable guest nick, give them the boot.
+ u->Kill(*NickServ, "Enforcement of services protected nickname");
}
- void Release(NickAlias *na) anope_override
+ void Release(NickAlias *na) override
{
if (held.HasExt(na))
{
@@ -279,7 +319,7 @@ class NickServCore : public Module, public NickServService
collided.Unset(na); /* clear pending collide */
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
const Anope::string &nsnick = conf->GetModule(this)->Get<const Anope::string>("client");
@@ -292,18 +332,17 @@ class NickServCore : public Module, public NickServService
NickServ = bi;
- spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "ns_secure memo_signon memo_receive")).GetTokens(defaults);
+ spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "memo_signon memo_receive")).GetTokens(defaults);
if (defaults.empty())
{
- defaults.push_back("NS_SECURE");
- defaults.push_back("MEMO_SIGNON");
- defaults.push_back("MEMO_RECEIVE");
+ defaults.emplace_back("MEMO_SIGNON");
+ defaults.emplace_back("MEMO_RECEIVE");
}
else if (defaults[0].equals_ci("none"))
defaults.clear();
}
- void OnDelNick(NickAlias *na) anope_override
+ void OnDelNick(NickAlias *na) override
{
User *u = User::Find(na->nick);
if (u && u->Account() == na->nc)
@@ -314,7 +353,7 @@ class NickServCore : public Module, public NickServService
}
}
- void OnDelCore(NickCore *nc) anope_override
+ void OnDelCore(NickCore *nc) override
{
Log(NickServ, "nick") << "Deleting nickname group " << nc->display;
@@ -330,42 +369,40 @@ class NickServCore : public Module, public NickServService
nc->users.clear();
}
- void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) anope_override
+ void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) override
{
Log(LOG_NORMAL, "nick", NickServ) << "Changing " << nc->display << " nickname group display to " << newdisplay;
}
- void OnNickIdentify(User *u) anope_override
+ void OnNickIdentify(User *u) override
{
Configuration::Block *block = Config->GetModule(this);
if (block->Get<bool>("modeonid", "yes"))
-
- for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
+ {
+ for (const auto &[_, cc] : u->chans)
{
- ChanUserContainer *cc = it->second;
Channel *c = cc->chan;
if (c)
c->SetCorrectModes(u, true);
}
+ }
const Anope::string &modesonid = block->Get<const Anope::string>("modesonid");
if (!modesonid.empty())
- u->SetModes(NickServ, "%s", modesonid.c_str());
+ u->SetModes(NickServ, modesonid);
if (block->Get<bool>("forceemail", "yes") && u->Account()->email.empty())
{
- u->SendMessage(NickServ, _("You must now supply an e-mail for your nick.\n"
- "This e-mail will allow you to retrieve your password in\n"
+ u->SendMessage(NickServ, _("You must now supply an email for your nick.\n"
+ "This email will allow you to retrieve your password in\n"
"case you forget it."));
- u->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n"
- "Your privacy is respected; this e-mail won't be given to\n"
- "any third-party person."), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
+ u->SendMessage(NickServ, _("Type \002%s SET EMAIL \037email\037\002 in order to set your email."),
+ NickServ->GetQueryCommand().c_str());
}
- for (std::set<NickServCollide *>::iterator it = collides.begin(); it != collides.end(); ++it)
+ for (auto *c : collides)
{
- NickServCollide *c = *it;
if (c->GetUser() == u && c->GetNick() && c->GetNick()->nc == u->Account())
{
delete c;
@@ -374,24 +411,23 @@ class NickServCore : public Module, public NickServService
}
}
- void OnNickGroup(User *u, NickAlias *target) anope_override
+ void OnNickGroup(User *u, NickAlias *target) override
{
if (!target->nc->HasExt("UNCONFIRMED"))
u->SetMode(NickServ, "REGISTERED");
}
- void OnNickUpdate(User *u) anope_override
+ void OnNickUpdate(User *u) override
{
- for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
+ for (const auto &[_, cc] : u->chans)
{
- ChanUserContainer *cc = it->second;
Channel *c = cc->chan;
if (c)
c->SetCorrectModes(u, true);
}
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (u->Quitting() || !u->server->IsSynced() || u->server->IsULined())
return;
@@ -405,19 +441,17 @@ class NickServCore : public Module, public NickServService
this->Validate(u);
}
- void OnPostUserLogoff(User *u) anope_override
+ void OnPostUserLogoff(User *u) override
{
NickAlias *na = NickAlias::Find(u->nick);
if (na)
OnCancel(u, na);
}
- void OnServerSync(Server *s) anope_override
+ void OnServerSync(Server *s) override
{
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u] : UserListByNick)
{
- User *u = it->second;
-
if (u->server == s)
{
if (u->HasMode("REGISTERED") && !u->IsIdentified(true))
@@ -428,7 +462,7 @@ class NickServCore : public Module, public NickServService
}
}
- void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
+ void OnUserNickChange(User *u, const Anope::string &oldnick) override
{
NickAlias *old_na = NickAlias::Find(oldnick), *na = NickAlias::Find(u->nick);
/* If the new nick isn't registered or it's registered and not yours */
@@ -452,13 +486,13 @@ class NickServCore : public Module, public NickServService
OnCancel(u, old_na);
}
- void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override
+ void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
{
if (u->server->IsSynced() && mname == "REGISTERED" && !u->IsIdentified(true))
u->RemoveMode(NickServ, mname);
}
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *NickServ)
return EVENT_CONTINUE;
@@ -466,19 +500,19 @@ class NickServCore : public Module, public NickServService
source.Reply(_("\002%s\002 allows you to register a nickname and\n"
"prevent others from using it. The following\n"
"commands allow for registration and maintenance of\n"
- "nicknames; to use them, type \002%s%s \037command\037\002.\n"
+ "nicknames; to use them, type \002%s \037command\037\002.\n"
"For more information on a specific command, type\n"
- "\002%s%s %s \037command\037\002.\n"), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), source.command.c_str());
+ "\002%s %s \037command\037\002.\n"), NickServ->nick.c_str(), NickServ->GetQueryCommand().c_str(), NickServ->GetQueryCommand().c_str(), source.command.c_str());
else
source.Reply(_("\002%s\002 allows you to register an account.\n"
"The following commands allow for registration and maintenance of\n"
- "accounts; to use them, type \002%s%s \037command\037\002.\n"
+ "accounts; to use them, type \002%s \037command\037\002.\n"
"For more information on a specific command, type\n"
- "\002%s%s %s \037command\037\002.\n"), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str(), source.command.c_str());
+ "\002%s %s \037command\037\002.\n"), NickServ->nick.c_str(), NickServ->GetQueryCommand().c_str(), NickServ->GetQueryCommand().c_str(), source.command.c_str());
return EVENT_CONTINUE;
}
- void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *NickServ)
return;
@@ -487,41 +521,41 @@ class NickServCore : public Module, public NickServService
"Services Operators can also drop any nickname without needing\n"
"to identify for the nick, and may view the access list for\n"
"any nickname."));
- time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "21d");
+ time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "1y");
if (nickserv_expire >= 86400)
source.Reply(_(" \n"
"Accounts that are not used anymore are subject to\n"
"the automatic expiration, i.e. they will be deleted\n"
- "after %d days if not used."), nickserv_expire / 86400);
+ "after %lu days if not used."), (unsigned long)nickserv_expire / 86400);
}
- void OnNickCoreCreate(NickCore *nc) anope_override
+ void OnNickCoreCreate(NickCore *nc) override
{
/* Set default flags */
- for (unsigned i = 0; i < defaults.size(); ++i)
- nc->Extend<bool>(defaults[i].upper());
+ for (const auto &def : defaults)
+ nc->Extend<bool>(def.upper());
}
- void OnUserQuit(User *u, const Anope::string &msg) anope_override
+ void OnUserQuit(User *u, const Anope::string &msg) override
{
if (u->server && !u->server->GetQuitReason().empty() && Config->GetModule(this)->Get<bool>("hidenetsplitquit"))
return;
/* Update last quit and last seen for the user */
NickAlias *na = NickAlias::Find(u->nick);
- if (na && !na->nc->HasExt("NS_SUSPENDED") && (u->IsRecognized() || u->IsIdentified(true)))
+ if (na && !na->nc->HasExt("NS_SUSPENDED") && u->IsIdentified(true))
{
na->last_seen = Anope::CurTime;
na->last_quit = msg;
}
}
- void OnExpireTick() anope_override
+ void OnExpireTick() override
{
if (Anope::NoExpire || Anope::ReadOnly)
return;
- time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "21d");
+ time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "90d");
for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; )
{
@@ -529,7 +563,7 @@ class NickServCore : public Module, public NickServService
++it;
User *u = User::Find(na->nick, true);
- if (u && (u->IsIdentified(true) || u->IsRecognized()))
+ if (u && u->IsIdentified(true))
na->last_seen = Anope::CurTime;
bool expire = false;
@@ -537,22 +571,25 @@ class NickServCore : public Module, public NickServService
if (nickserv_expire && Anope::CurTime - na->last_seen >= nickserv_expire)
expire = true;
+ if (na->nc->na == na && na->nc->aliases->size() > 1 && Config->GetModule("nickserv")->Get<bool>("preservedisplay"))
+ expire = false;
+
FOREACH_MOD(OnPreNickExpire, (na, expire));
if (expire)
{
- Log(LOG_NORMAL, "nickserv/expire", NickServ) << "Expiring nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")";
+ Log(LOG_NORMAL, "nickserv/expire", NickServ) << "Expiring nickname " << na->nick << " (group: " << na->nc->display << ") (email: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")";
FOREACH_MOD(OnNickExpire, (na));
delete na;
}
}
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
{
if (!na->nc->HasExt("UNCONFIRMED"))
{
- time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "21d");
+ time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire", "1y");
if (!na->HasExt("NS_NO_EXPIRE") && nickserv_expire && !Anope::NoExpire && (source.HasPriv("nickserv/auspex") || na->last_seen != Anope::CurTime))
info[_("Expires")] = Anope::strftime(na->last_seen + nickserv_expire, source.GetAccount());
}
diff --git a/modules/commands/ns_ajoin.cpp b/modules/nickserv/ns_ajoin.cpp
index 5dae09ec1..8643a2c1b 100644
--- a/modules/commands/ns_ajoin.cpp
+++ b/modules/nickserv/ns_ajoin.cpp
@@ -13,13 +13,15 @@
struct AJoinEntry;
-struct AJoinList : Serialize::Checker<std::vector<AJoinEntry *> >
+struct AJoinList final
+ : Serialize::Checker<std::vector<AJoinEntry *> >
{
AJoinList(Extensible *) : Serialize::Checker<std::vector<AJoinEntry *> >("AJoinEntry") { }
~AJoinList();
};
-struct AJoinEntry : Serializable
+struct AJoinEntry final
+ : Serializable
{
Serialize::Reference<NickCore> owner;
Anope::string channel;
@@ -27,7 +29,7 @@ struct AJoinEntry : Serializable
AJoinEntry(Extensible *) : Serializable("AJoinEntry") { }
- ~AJoinEntry()
+ ~AJoinEntry() override
{
AJoinList *channels = owner->GetExt<AJoinList>("ajoinlist");
if (channels)
@@ -38,17 +40,17 @@ struct AJoinEntry : Serializable
}
}
- void Serialize(Serialize::Data &sd) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
if (!this->owner)
return;
- sd["owner"] << this->owner->display;
- sd["channel"] << this->channel;
- sd["key"] << this->key;
+ data.Store("owner", this->owner->display);
+ data.Store("channel", this->channel);
+ data.Store("key", this->key);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &sd)
{
Anope::string sowner;
@@ -82,13 +84,14 @@ struct AJoinEntry : Serializable
AJoinList::~AJoinList()
{
- for (unsigned i = 0; i < (*this)->size(); ++i)
- delete (*this)->at(i);
+ for (const auto *ajoin : *(*this))
+ delete ajoin;
}
-class CommandNSAJoin : public Command
+class CommandNSAJoin final
+ : public Command
{
- void DoList(CommandSource &source, NickCore *nc)
+ static void DoList(CommandSource &source, NickCore *nc)
{
AJoinList *channels = nc->Require<AJoinList>("ajoinlist");
@@ -102,7 +105,7 @@ class CommandNSAJoin : public Command
{
AJoinEntry *aj = (*channels)->at(i);
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Channel"] = aj->channel;
entry["Key"] = aj->key;
list.AddEntry(entry);
@@ -113,8 +116,8 @@ class CommandNSAJoin : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
@@ -143,7 +146,7 @@ class CommandNSAJoin : public Command
}
else if (i != (*channels)->size())
alreadyadded += chan + ", ";
- else if (IRCD->IsChannelValid(chan) == false)
+ else if (!IRCD->IsChannelValid(chan))
source.Reply(CHAN_X_INVALID, chan.c_str());
else
{
@@ -155,7 +158,7 @@ class CommandNSAJoin : public Command
continue;
}
- AJoinEntry *entry = new AJoinEntry(nc);
+ auto *entry = new AJoinEntry(nc);
entry->owner = nc;
entry->channel = chan;
entry->key = key;
@@ -224,7 +227,7 @@ class CommandNSAJoin : public Command
nc->Shrink<AJoinList>("ajoinlist");
}
- public:
+public:
CommandNSAJoin(Module *creator) : Command(creator, "nickserv/ajoin", 1, 4)
{
this->SetDesc(_("Manage your auto join list"));
@@ -233,7 +236,7 @@ class CommandNSAJoin : public Command
this->SetSyntax(_("LIST [\037nickname\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
Anope::string nick, param, param2;
@@ -285,7 +288,7 @@ class CommandNSAJoin : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -297,13 +300,14 @@ class CommandNSAJoin : public Command
}
};
-class NSAJoin : public Module
+class NSAJoin final
+ : public Module
{
CommandNSAJoin commandnsajoin;
ExtensibleItem<AJoinList> ajoinlist;
Serialize::Type ajoinentry_type;
- public:
+public:
NSAJoin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsajoin(this), ajoinlist(this, "ajoinlist"),
ajoinentry_type("AJoinEntry", AJoinEntry::Unserialize)
@@ -314,7 +318,7 @@ class NSAJoin : public Module
}
- void OnUserLogin(User *u) anope_override
+ void OnUserLogin(User *u) override
{
BotInfo *NickServ = Config->GetClient("NickServ");
if (!NickServ)
@@ -327,9 +331,8 @@ class NSAJoin : public Module
/* Set +r now, so we can ajoin users into +R channels */
ModeManager::ProcessModes();
- for (unsigned i = 0; i < (*channels)->size(); ++i)
+ for (auto *entry : *(*channels))
{
- AJoinEntry *entry = (*channels)->at(i);
Channel *c = Channel::Find(entry->channel);
ChannelInfo *ci;
@@ -356,11 +359,11 @@ class NSAJoin : public Module
continue;
else if (c->HasMode("ADMINONLY") && !u->HasMode("ADMIN"))
continue;
- else if (c->HasMode("SSL") && !(u->HasMode("SSL") || u->HasExt("ssl")))
+ else if (c->HasMode("SSL") && !u->IsSecurelyConnected())
continue;
- else if (c->MatchesList(u, "BAN") == true && c->MatchesList(u, "EXCEPT") == false)
+ else if (c->MatchesList(u, "BAN") && !c->MatchesList(u, "EXCEPT"))
need_invite = true;
- else if (c->HasMode("INVITE") && c->MatchesList(u, "INVITEOVERRIDE") == false)
+ else if (c->HasMode("INVITE") && !c->MatchesList(u, "INVITEOVERRIDE"))
need_invite = true;
if (c->HasMode("KEY"))
@@ -379,13 +382,11 @@ class NSAJoin : public Module
Anope::string l;
if (c->GetParam("LIMIT", l))
{
- try
+ if (auto limit = Anope::TryConvert<unsigned>(l))
{
- unsigned limit = convertTo<unsigned>(l);
- if (c->users.size() >= limit)
+ if (c->users.size() >= limit.value())
need_invite = true;
}
- catch (const ConvertException &) { }
}
}
}
diff --git a/modules/commands/ns_alist.cpp b/modules/nickserv/ns_alist.cpp
index eea33e3f7..526288aca 100644
--- a/modules/commands/ns_alist.cpp
+++ b/modules/nickserv/ns_alist.cpp
@@ -11,21 +11,22 @@
#include "module.h"
-class CommandNSAList : public Command
+class CommandNSAList final
+ : public Command
{
static bool ChannelSort(ChannelInfo *ci1, ChannelInfo *ci2)
{
return ci::less()(ci1->name, ci2->name);
}
- public:
+public:
CommandNSAList(Module *creator) : Command(creator, "nickserv/alist", 0, 2)
{
this->SetDesc(_("List channels you have access on"));
this->SetSyntax(_("[\037nickname\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string nick = source.GetNick();
NickCore *nc = source.nc;
@@ -51,15 +52,14 @@ class CommandNSAList : public Command
nc->GetChannelReferences(queue);
std::sort(queue.begin(), queue.end(), ChannelSort);
- for (unsigned i = 0; i < queue.size(); ++i)
+ for (auto *ci : queue)
{
- ChannelInfo *ci = queue[i];
ListFormatter::ListEntry entry;
if (ci->GetFounder() == nc)
{
++chan_count;
- entry["Number"] = stringify(chan_count);
+ entry["Number"] = Anope::ToString(chan_count);
entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
entry["Access"] = Language::Translate(source.GetAccount(), _("Founder"));
entry["Description"] = ci->desc;
@@ -70,7 +70,7 @@ class CommandNSAList : public Command
if (ci->GetSuccessor() == nc)
{
++chan_count;
- entry["Number"] = stringify(chan_count);
+ entry["Number"] = Anope::ToString(chan_count);
entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
entry["Access"] = Language::Translate(source.GetAccount(), _("Successor"));
entry["Description"] = ci->desc;
@@ -84,12 +84,10 @@ class CommandNSAList : public Command
++chan_count;
- entry["Number"] = stringify(chan_count);
+ entry["Number"] = Anope::ToString(chan_count);
entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
- for (unsigned j = 0; j < access.paths.size(); ++j)
+ for (auto &p : access.paths)
{
- ChanAccess::Path &p = access.paths[j];
-
// not interested in indirect access
if (p.size() != 1)
continue;
@@ -113,14 +111,14 @@ class CommandNSAList : public Command
{
source.Reply(_("Channels that \002%s\002 has access on:"), nc->display.c_str());
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of list - %d channels shown."), chan_count);
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -134,11 +132,12 @@ class CommandNSAList : public Command
}
};
-class NSAList : public Module
+class NSAList final
+ : public Module
{
CommandNSAList commandnsalist;
- public:
+public:
NSAList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsalist(this)
{
diff --git a/modules/commands/ns_cert.cpp b/modules/nickserv/ns_cert.cpp
index 4db53db54..9a697df17 100644
--- a/modules/commands/ns_cert.cpp
+++ b/modules/nickserv/ns_cert.cpp
@@ -12,30 +12,43 @@
#include "module.h"
#include "modules/ns_cert.h"
-static Anope::hash_map<NickCore *> certmap;
+static Anope::unordered_map<NickCore *> certmap;
-struct CertServiceImpl : CertService
+struct CertServiceImpl final
+ : CertService
{
CertServiceImpl(Module *o) : CertService(o) { }
- NickCore* FindAccountFromCert(const Anope::string &cert) anope_override
+ NickCore *FindAccountFromCert(const Anope::string &cert) override
{
- Anope::hash_map<NickCore *>::iterator it = certmap.find(cert);
+ Anope::unordered_map<NickCore *>::iterator it = certmap.find(cert);
if (it != certmap.end())
return it->second;
return NULL;
}
+
+ void ReplaceCert(const Anope::string &oldcert, const Anope::string &newcert) override
+ {
+ auto *nc = FindAccountFromCert(oldcert);
+ if (!nc)
+ return;
+
+ auto *cl = nc->GetExt<NSCertList>("certificates");
+ if (cl)
+ cl->ReplaceCert(oldcert, newcert);
+ }
};
-struct NSCertListImpl : NSCertList
+struct NSCertListImpl final
+ : NSCertList
{
Serialize::Reference<NickCore> nc;
std::vector<Anope::string> certs;
- public:
+public:
NSCertListImpl(Extensible *obj) : nc(anope_dynamic_static_cast<NickCore *>(obj)) { }
- ~NSCertListImpl()
+ ~NSCertListImpl() override
{
ClearCert();
}
@@ -46,7 +59,7 @@ struct NSCertListImpl : NSCertList
*
* Adds a new entry into the cert list.
*/
- void AddCert(const Anope::string &entry) anope_override
+ void AddCert(const Anope::string &entry) override
{
this->certs.push_back(entry);
certmap[entry] = nc;
@@ -60,14 +73,14 @@ struct NSCertListImpl : NSCertList
*
* Retrieves an entry from the certificate list corresponding to the given index.
*/
- Anope::string GetCert(unsigned entry) const anope_override
+ Anope::string GetCert(unsigned entry) const override
{
if (entry >= this->certs.size())
return "";
return this->certs[entry];
}
- unsigned GetCertCount() const anope_override
+ unsigned GetCertCount() const override
{
return this->certs.size();
}
@@ -79,7 +92,7 @@ struct NSCertListImpl : NSCertList
*
* Search for an fingerprint within the cert list.
*/
- bool FindCert(const Anope::string &entry) const anope_override
+ bool FindCert(const Anope::string &entry) const override
{
return std::find(this->certs.begin(), this->certs.end(), entry) != this->certs.end();
}
@@ -90,7 +103,7 @@ struct NSCertListImpl : NSCertList
*
* Removes the specified fingerprint from the cert list.
*/
- void EraseCert(const Anope::string &entry) anope_override
+ void EraseCert(const Anope::string &entry) override
{
std::vector<Anope::string>::iterator it = std::find(this->certs.begin(), this->certs.end(), entry);
if (it != this->certs.end())
@@ -101,29 +114,51 @@ struct NSCertListImpl : NSCertList
}
}
+ void ReplaceCert(const Anope::string &oldentry, const Anope::string &newentry) override
+ {
+ auto it = std::find(this->certs.begin(), this->certs.end(), oldentry);
+ if (it == this->certs.end())
+ return; // We can't replace a non-existent cert.
+
+ FOREACH_MOD(OnNickEraseCert, (this->nc, oldentry));
+ certmap.erase(oldentry);
+
+ if (std::find(this->certs.begin(), this->certs.end(), newentry) != this->certs.end())
+ {
+ // The cert we're upgrading to already exists.
+ this->certs.erase(it);
+ return;
+ }
+
+ *it = newentry;
+ certmap[newentry] = nc;
+ FOREACH_MOD(OnNickAddCert, (this->nc, newentry));
+ }
+
/** Clears the entire nick's cert list
*
* Deletes all the memory allocated in the certificate list vector and then clears the vector.
*/
- void ClearCert() anope_override
+ void ClearCert() override
{
FOREACH_MOD(OnNickClearCert, (this->nc));
- for (unsigned i = 0; i < certs.size(); ++i)
- certmap.erase(certs[i]);
+ for (const auto &cert : certs)
+ certmap.erase(cert);
this->certs.clear();
}
- void Check() anope_override
+ void Check() override
{
if (this->certs.empty())
nc->Shrink<NSCertList>("certificates");
}
- struct ExtensibleItem : ::ExtensibleItem<NSCertListImpl>
+ struct ExtensibleItem final
+ : ::ExtensibleItem<NSCertListImpl>
{
ExtensibleItem(Module *m, const Anope::string &ename) : ::ExtensibleItem<NSCertListImpl>(m, ename) { }
- void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
if (s->GetSerializableType()->GetName() != "NickCore")
return;
@@ -133,11 +168,13 @@ struct NSCertListImpl : NSCertList
if (c == NULL || !c->GetCertCount())
return;
+ std::ostringstream oss;
for (unsigned i = 0; i < c->GetCertCount(); ++i)
- data["cert"] << c->GetCert(i) << " ";
+ oss << c->GetCert(i) << " ";
+ data.Store("cert", oss.str());
}
- void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
{
if (s->GetSerializableType()->GetName() != "NickCore")
return;
@@ -148,8 +185,8 @@ struct NSCertListImpl : NSCertList
Anope::string buf;
data["cert"] >> buf;
spacesepstream sep(buf);
- for (unsigned i = 0; i < c->certs.size(); ++i)
- certmap.erase(c->certs[i]);
+ for (const auto &cert : c->certs)
+ certmap.erase(cert);
c->certs.clear();
while (sep.GetToken(buf))
{
@@ -160,9 +197,10 @@ struct NSCertListImpl : NSCertList
};
};
-class CommandNSCert : public Command
+class CommandNSCert final
+ : public Command
{
- private:
+private:
void DoAdd(CommandSource &source, NickCore *nc, Anope::string certfp)
{
NSCertList *cl = nc->Require<NSCertList>("certificates");
@@ -233,7 +271,7 @@ class CommandNSCert : public Command
source.Reply(_("\002%s\002 deleted from %s's certificate list."), certfp.c_str(), nc->display.c_str());
}
- void DoList(CommandSource &source, const NickCore *nc)
+ static void DoList(CommandSource &source, const NickCore *nc)
{
NSCertList *cl = nc->GetExt<NSCertList>("certificates");
@@ -251,7 +289,7 @@ class CommandNSCert : public Command
}
}
- public:
+public:
CommandNSCert(Module *creator) : Command(creator, "nickserv/cert", 1, 3)
{
this->SetDesc(_("Modify the nickname client certificate list"));
@@ -260,7 +298,7 @@ class CommandNSCert : public Command
this->SetSyntax(_("LIST [\037nickname\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
Anope::string nick, certfp;
@@ -282,7 +320,7 @@ class CommandNSCert : public Command
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
return;
}
- else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access"))
+ else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/cert"))
{
source.Reply(ACCESS_DENIED);
return;
@@ -312,7 +350,7 @@ class CommandNSCert : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -338,13 +376,14 @@ class CommandNSCert : public Command
}
};
-class NSCert : public Module
+class NSCert final
+ : public Module
{
CommandNSCert commandnscert;
NSCertListImpl::ExtensibleItem certs;
CertServiceImpl cs;
- public:
+public:
NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnscert(this), certs(this, "certificates"), cs(this)
{
@@ -352,7 +391,7 @@ class NSCert : public Module
throw ModuleException("Your IRCd does not support ssl client certificates");
}
- void OnFingerprint(User *u) anope_override
+ void OnFingerprint(User *u) override
{
BotInfo *NickServ = Config->GetClient("NickServ");
if (!NickServ || u->IsIdentified())
@@ -379,7 +418,19 @@ class NSCert : public Module
Log(NickServ) << u->GetMask() << " automatically identified for account " << nc->display << " via SSL certificate fingerprint";
}
- EventReturn OnNickValidate(User *u, NickAlias *na) anope_override
+ void OnNickRegister(User *u, NickAlias *na, const Anope::string &pass) override
+ {
+ if (!Config->GetModule(this)->Get<bool>("automatic", "yes") || !u || u->fingerprint.empty())
+ return;
+
+ auto *cl = certs.Require(na->nc);
+ cl->AddCert(u->fingerprint);
+
+ auto *NickServ = Config->GetClient("NickServ");
+ u->SendMessage(NickServ, _("Your SSL certificate fingerprint \002%s\002 has been automatically added to your certificate list."), u->fingerprint.c_str());
+ }
+
+ EventReturn OnNickValidate(User *u, NickAlias *na) override
{
NSCertList *cl = certs.Get(na->nc);
if (!u->fingerprint.empty() && cl && cl->FindCert(u->fingerprint))
diff --git a/modules/nickserv/ns_drop.cpp b/modules/nickserv/ns_drop.cpp
new file mode 100644
index 000000000..791db0bfb
--- /dev/null
+++ b/modules/nickserv/ns_drop.cpp
@@ -0,0 +1,124 @@
+/* NickServ core functions
+ *
+ * (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"
+
+class CommandNSDrop final
+ : public Command
+{
+private:
+ PrimitiveExtensibleItem<Anope::string> dropcode;
+
+public:
+ CommandNSDrop(Module *creator)
+ : Command(creator, "nickserv/drop", 1, 2)
+ , dropcode(creator, "nickname-dropcode")
+ {
+ this->SetSyntax(_("\037nickname\037 [\037code\037]"));
+ this->SetDesc(_("Cancel the registration of a nickname"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ const Anope::string &nick = params[0];
+
+ if (Anope::ReadOnly && !source.HasPriv("nickserv/drop"))
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ NickAlias *na = NickAlias::Find(nick);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
+ return;
+ }
+
+ bool is_mine = source.GetAccount() == na->nc;
+
+ if (!is_mine && !source.HasPriv("nickserv/drop"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && !is_mine && na->nc->IsServicesOper())
+ {
+ source.Reply(_("You may not drop other Services Operators' nicknames."));
+ return;
+ }
+
+ if (na->nc->na == na && na->nc->aliases->size() > 1 && Config->GetModule("nickserv")->Get<bool>("preservedisplay") && !source.HasPriv("nickserv/drop/display"))
+ {
+ source.Reply(_("You may not drop \002%s\002 as it is the display nick for the account."), na->nick.c_str());
+ return;
+ }
+
+ auto *code = dropcode.Get(na);
+ if (params.size() < 2 || ((!code || !code->equals_ci(params[1])) && (!source.HasPriv("nickserv/drop/override") || params[1] != "OVERRIDE")))
+ {
+ if (!code)
+ {
+ code = na->Extend<Anope::string>("nickname-dropcode");
+ *code = Anope::Random(15);
+ }
+
+ source.Reply(CONFIRM_DROP, na->nick.c_str(), source.service->GetQueryCommand().c_str(),
+ na->nick.c_str(), code->c_str());
+ return;
+ }
+
+ FOREACH_MOD(OnNickDrop, (source, na));
+
+ Log(!is_mine ? LOG_ADMIN : LOG_COMMAND, source, this) << "to drop nickname " << na->nick << " (group: " << na->nc->display << ") (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
+ delete na;
+
+ source.Reply(_("Nickname \002%s\002 has been dropped."), nick.c_str());
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Drops the given nick from the database. Once your nickname\n"
+ "is dropped you may lose all of your access and channels that\n"
+ "you may own. Any other user will be able to gain control of\n"
+ "this nick."));
+
+ source.Reply(" ");
+ if (!source.HasPriv("nickserv/drop"))
+ source.Reply(_("You may drop any nick within your group."));
+ else
+ source.Reply(_("As a Services Operator, you may drop any nick."));
+
+ source.Reply(" ");
+ if (source.HasPriv("nickserv/drop/override"))
+ source.Reply(_("Additionally, Services Operators with the \037nickserv/drop/override\037 permission can\n"
+ "replace \037code\037 with \002OVERRIDE\002 to drop without a confirmation code."));
+ return true;
+ }
+};
+
+class NSDrop final
+ : public Module
+{
+ CommandNSDrop commandnsdrop;
+
+public:
+ NSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ commandnsdrop(this)
+ {
+
+ }
+};
+
+MODULE_INIT(NSDrop)
diff --git a/modules/commands/ns_getemail.cpp b/modules/nickserv/ns_getemail.cpp
index 47ee84679..6e8b55bca 100644
--- a/modules/commands/ns_getemail.cpp
+++ b/modules/nickserv/ns_getemail.cpp
@@ -15,26 +15,26 @@
#include "module.h"
-class CommandNSGetEMail : public Command
+class CommandNSGetEmail final
+ : public Command
{
- public:
- CommandNSGetEMail(Module *creator) : Command(creator, "nickserv/getemail", 1, 1)
+public:
+ CommandNSGetEmail(Module *creator)
+ : Command(creator, "nickserv/getemail", 1, 1)
{
this->SetDesc(_("Matches and returns all users that registered using given email"));
this->SetSyntax(_("\037email\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &email = params[0];
int j = 0;
Log(LOG_ADMIN, source, this) << "on " << email;
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- const NickCore *nc = it->second;
-
if (!nc->email.empty() && Anope::Match(nc->email, email))
{
++j;
@@ -51,7 +51,7 @@ class CommandNSGetEMail : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -60,15 +60,19 @@ class CommandNSGetEMail : public Command
}
};
-class NSGetEMail : public Module
+class NSGetEmail final
+ : public Module
{
- CommandNSGetEMail commandnsgetemail;
- public:
- NSGetEMail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsgetemail(this)
+private:
+ CommandNSGetEmail commandnsgetemail;
+
+public:
+ NSGetEmail(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandnsgetemail(this)
{
}
};
-MODULE_INIT(NSGetEMail)
+MODULE_INIT(NSGetEmail)
diff --git a/modules/commands/ns_group.cpp b/modules/nickserv/ns_group.cpp
index ec82a5f0b..0ccad3735 100644
--- a/modules/commands/ns_group.cpp
+++ b/modules/nickserv/ns_group.cpp
@@ -12,17 +12,20 @@
#include "module.h"
#include "modules/ns_cert.h"
-class NSGroupRequest : public IdentifyRequest
+static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
+
+class NSGroupRequest final
+ : public IdentifyRequest
{
CommandSource source;
Command *cmd;
Anope::string nick;
Reference<NickAlias> target;
- public:
+public:
NSGroupRequest(Module *o, CommandSource &src, Command *c, const Anope::string &n, NickAlias *targ, const Anope::string &pass) : IdentifyRequest(o, targ->nc->display, pass), source(src), cmd(c), nick(n), target(targ) { }
- void OnSuccess() anope_override
+ void OnSuccess() override
{
User *u = source.GetUser();
@@ -67,7 +70,7 @@ class NSGroupRequest : public IdentifyRequest
u->lastnickreg = Anope::CurTime;
}
- void OnFail() anope_override
+ void OnFail() override
{
User *u = source.GetUser();
@@ -83,9 +86,10 @@ class NSGroupRequest : public IdentifyRequest
}
};
-class CommandNSGroup : public Command
+class CommandNSGroup final
+ : public Command
{
- public:
+public:
CommandNSGroup(Module *creator) : Command(creator, "nickserv/group", 0, 2)
{
this->SetDesc(_("Join a group"));
@@ -93,14 +97,14 @@ class CommandNSGroup : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
User *user = source.GetUser();
Anope::string nick;
if (params.empty())
{
- NickCore* core = source.GetAccount();
+ NickCore *core = source.GetAccount();
if (core)
nick = core->display;
}
@@ -117,7 +121,7 @@ class CommandNSGroup : public Command
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, nickname grouping is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -128,25 +132,27 @@ class CommandNSGroup : public Command
}
if (Config->GetModule("nickserv")->Get<bool>("restrictopernicks"))
- for (unsigned i = 0; i < Oper::opers.size(); ++i)
+ {
+ for (auto *o : Oper::opers)
{
- Oper *o = Oper::opers[i];
-
if (user != NULL && !user->HasMode("OPER") && user->nick.find_ci(o->name) != Anope::string::npos)
{
source.Reply(NICK_CANNOT_BE_REGISTERED, user->nick.c_str());
return;
}
}
+ }
NickAlias *target, *na = NickAlias::Find(source.GetNick());
- const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay");
unsigned maxaliases = Config->GetModule(this->owner)->Get<unsigned>("maxaliases");
if (!(target = NickAlias::Find(nick)))
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
else if (user && Anope::CurTime < user->lastnickreg + reg_delay)
- source.Reply(_("Please wait %d seconds before using the GROUP command again."), (reg_delay + user->lastnickreg) - Anope::CurTime);
+ {
+ auto waitperiod = (unsigned long)(reg_delay + user->lastnickreg) - Anope::CurTime;
+ source.Reply(_("Please wait %s before using the GROUP command again."), Anope::Duration(waitperiod, source.GetAccount()).c_str());
+ }
else if (target->nc->HasExt("NS_SUSPENDED"))
{
Log(LOG_COMMAND, source, this) << "and tried to group to SUSPENDED nick " << target->nick;
@@ -160,12 +166,8 @@ class CommandNSGroup : public Command
source.Reply(NICK_IDENTIFY_REQUIRED);
else if (maxaliases && target->nc->aliases->size() >= maxaliases && !target->nc->IsServicesOper())
source.Reply(_("There are too many nicks in your group."));
- else if (source.GetNick().length() <= guestnick.length() + 7 &&
- source.GetNick().length() >= guestnick.length() + 1 &&
- !source.GetNick().find_ci(guestnick) && !source.GetNick().substr(guestnick.length()).find_first_not_of("1234567890"))
- {
+ else if (nickserv && nickserv->IsGuestNick(source.GetNick()))
source.Reply(NICK_CANNOT_BE_REGISTERED, source.GetNick().c_str());
- }
else
{
bool ok = false;
@@ -176,9 +178,9 @@ class CommandNSGroup : public Command
if (user != NULL && !user->fingerprint.empty() && cl && cl->FindCert(user->fingerprint))
ok = true;
- if (ok == false && !pass.empty())
+ if (!ok && !pass.empty())
{
- NSGroupRequest *req = new NSGroupRequest(owner, source, this, source.GetNick(), target, pass);
+ auto *req = new NSGroupRequest(owner, source, this, source.GetNick(), target, pass);
FOREACH_MOD(OnCheckAuthentication, (source.GetUser(), req));
req->Dispatch();
}
@@ -194,7 +196,7 @@ class CommandNSGroup : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -228,16 +230,17 @@ class CommandNSGroup : public Command
}
};
-class CommandNSUngroup : public Command
+class CommandNSUngroup final
+ : public Command
{
- public:
+public:
CommandNSUngroup(Module *creator) : Command(creator, "nickserv/ungroup", 0, 1)
{
this->SetDesc(_("Remove a nick from a group"));
this->SetSyntax(_("[\037nick\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string nick = !params.empty() ? params[0] : "";
NickAlias *na = NickAlias::Find(!nick.empty() ? nick : source.GetNick());
@@ -259,7 +262,7 @@ class CommandNSUngroup : public Command
if (na->nick.equals_ci(oldcore->display))
oldcore->SetDisplay(oldcore->aliases->front());
- NickCore *nc = new NickCore(na->nick);
+ auto *nc = new NickCore(na->nick);
na->nc = nc;
nc->aliases->push_back(na);
@@ -278,7 +281,7 @@ class CommandNSUngroup : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -291,15 +294,16 @@ class CommandNSUngroup : public Command
}
};
-class CommandNSGList : public Command
+class CommandNSGList final
+ : public Command
{
- public:
+public:
CommandNSGList(Module *creator) : Command(creator, "nickserv/glist", 0, 1)
{
this->SetDesc(_("Lists all nicknames in your group"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = !params.empty() ? params[0] : "";
const NickCore *nc;
@@ -325,12 +329,10 @@ class CommandNSGList : public Command
ListFormatter list(source.GetAccount());
list.AddColumn(_("Nick")).AddColumn(_("Expires"));
- time_t nickserv_expire = Config->GetModule("nickserv")->Get<time_t>("expire", "21d"),
+ time_t nickserv_expire = Config->GetModule("nickserv")->Get<time_t>("expire", "90d"),
unconfirmed_expire = Config->GetModule("ns_register")->Get<time_t>("unconfirmedexpire", "1d");
- for (unsigned i = 0; i < nc->aliases->size(); ++i)
+ for (auto *na2 : *nc->aliases)
{
- const NickAlias *na2 = nc->aliases->at(i);
-
Anope::string expires;
if (na2->HasExt("NS_NO_EXPIRE"))
expires = NO_EXPIRE;
@@ -351,13 +353,13 @@ class CommandNSGList : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
- source.Reply(_("%d nickname(s) in the group."), nc->aliases->size());
+ source.Reply(nc->aliases->size(), N_("%zu nickname in the group.", "%zu nicknames in the group."), nc->aliases->size());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (source.IsServicesOper())
source.Reply(_("Syntax: \002%s [\037nickname\037]\002\n"
@@ -378,13 +380,14 @@ class CommandNSGList : public Command
}
};
-class NSGroup : public Module
+class NSGroup final
+ : public Module
{
CommandNSGroup commandnsgroup;
CommandNSUngroup commandnsungroup;
CommandNSGList commandnsglist;
- public:
+public:
NSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsgroup(this), commandnsungroup(this), commandnsglist(this)
{
diff --git a/modules/commands/ns_identify.cpp b/modules/nickserv/ns_identify.cpp
index 37d8c32b2..a7a2b4bf7 100644
--- a/modules/commands/ns_identify.cpp
+++ b/modules/nickserv/ns_identify.cpp
@@ -11,15 +11,16 @@
#include "module.h"
-class NSIdentifyRequest : public IdentifyRequest
+class NSIdentifyRequest final
+ : public IdentifyRequest
{
CommandSource source;
Command *cmd;
- public:
+public:
NSIdentifyRequest(Module *o, CommandSource &s, Command *c, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(o, acc, pass), source(s), cmd(c) { }
- void OnSuccess() anope_override
+ void OnSuccess() override
{
if (!source.GetUser())
return;
@@ -40,7 +41,7 @@ class NSIdentifyRequest : public IdentifyRequest
}
}
- void OnFail() anope_override
+ void OnFail() override
{
if (source.GetUser())
{
@@ -57,9 +58,10 @@ class NSIdentifyRequest : public IdentifyRequest
}
};
-class CommandNSIdentify : public Command
+class CommandNSIdentify final
+ : public Command
{
- public:
+public:
CommandNSIdentify(Module *creator) : Command(creator, "nickserv/identify", 1, 2)
{
this->SetDesc(_("Identify yourself with your password"));
@@ -68,7 +70,7 @@ class CommandNSIdentify : public Command
this->RequireUser(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
User *u = source.GetUser();
@@ -95,12 +97,12 @@ class CommandNSIdentify : public Command
return;
}
- NSIdentifyRequest *req = new NSIdentifyRequest(owner, source, this, na ? na->nc->display : nick, pass);
+ auto *req = new NSIdentifyRequest(owner, source, this, na ? na->nc->display : nick, pass);
FOREACH_MOD(OnCheckAuthentication, (u, req));
req->Dispatch();
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -113,11 +115,12 @@ class CommandNSIdentify : public Command
}
};
-class NSIdentify : public Module
+class NSIdentify final
+ : public Module
{
CommandNSIdentify commandnsidentify;
- public:
+public:
NSIdentify(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsidentify(this)
{
diff --git a/modules/commands/ns_info.cpp b/modules/nickserv/ns_info.cpp
index a5a87fe2d..d67fe0a18 100644
--- a/modules/commands/ns_info.cpp
+++ b/modules/nickserv/ns_info.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandNSInfo : public Command
+class CommandNSInfo final
+ : public Command
{
- public:
+public:
CommandNSInfo(Module *creator) : Command(creator, "nickserv/info", 0, 2)
{
this->SetDesc(_("Displays information about a given nickname"));
@@ -21,10 +22,37 @@ class CommandNSInfo : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
+ Anope::string nick;
+ if (params.empty())
+ {
+ // Use the display of the source if logged in; otherwise, use their nick.
+ nick = source.nc ? source.nc->na->nick : source.GetNick();
+ }
+ else if (params[0][0] == '=' && params[0].length() > 1)
+ {
+ // Look up the account of the specified user.
+ nick = params[0].substr(1);
+ auto *u = User::Find(nick);
+ if (!u)
+ {
+ source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
+ return;
+ }
+ if (!u->AccountNick())
+ {
+ source.Reply(_("User \002%s\002 isn't currently logged in to an account."), nick.c_str());
+ return;
+ }
+ nick = u->AccountNick()->nick;
+ }
+ else
+ {
+ // Just use the nick the user specified.
+ nick = params[0];
+ }
- const Anope::string &nick = params.size() ? params[0] : (source.nc ? source.nc->display : source.GetNick());
NickAlias *na = NickAlias::Find(nick);
bool has_auspex = source.HasPriv("nickserv/auspex");
@@ -61,6 +89,7 @@ class CommandNSInfo : public Command
InfoFormatter info(source.nc);
info[_("Account")] = na->nc->display;
+ info[_("Account id")] = Anope::ToString(na->nc->GetId());
if (nick_online)
{
bool shown = false;
@@ -87,7 +116,8 @@ class CommandNSInfo : public Command
info[_("Last seen address")] = na->last_realhost;
}
- info[_("Registered")] = Anope::strftime(na->time_registered, source.GetAccount());
+ info[_("Account registered")] = Anope::strftime(na->nc->time_registered, source.GetAccount());
+ info[_("Nick registered")] = Anope::strftime(na->time_registered, source.GetAccount());
if (!nick_online)
info[_("Last seen")] = Anope::strftime(na->last_seen, source.GetAccount());
@@ -100,13 +130,8 @@ class CommandNSInfo : public Command
if (show_hidden)
{
- if (na->HasVhost())
- {
- if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
- info[_("VHost")] = na->GetVhostIdent() + "@" + na->GetVhostHost();
- else
- info[_("VHost")] = na->GetVhostHost();
- }
+ if (na->HasVHost())
+ info[_("VHost")] = na->GetVHostMask();
}
FOREACH_MOD(OnNickInfo, (source, na, info, show_hidden));
@@ -114,12 +139,12 @@ class CommandNSInfo : public Command
std::vector<Anope::string> replies;
info.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -134,9 +159,10 @@ class CommandNSInfo : public Command
};
-class CommandNSSetHide : public Command
+class CommandNSSetHide
+ : public Command
{
- public:
+public:
CommandNSSetHide(Module *creator, const Anope::string &sname = "nickserv/set/hide", size_t min = 2) : Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Hide certain pieces of nickname information"));
@@ -169,8 +195,8 @@ class CommandNSSetHide : public Command
if (param.equals_ci("EMAIL"))
{
flag = "HIDE_EMAIL";
- onmsg = _("The E-mail address of \002%s\002 will now be hidden from %s INFO displays.");
- offmsg = _("The E-mail address of \002%s\002 will now be shown in %s INFO displays.");
+ onmsg = _("The email address of \002%s\002 will now be hidden from %s INFO displays.");
+ offmsg = _("The email address of \002%s\002 will now be shown in %s INFO displays.");
}
else if (param.equals_ci("USERMASK"))
{
@@ -212,18 +238,18 @@ class CommandNSSetHide : public Command
this->OnSyntaxError(source, "HIDE");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, params[0], params[1]);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s \002INFO\002 on your\n"
- "nick. You can hide your E-mail address (\002EMAIL\002), last seen\n"
+ "nick. You can hide your email address (\002EMAIL\002), last seen\n"
"user@host mask (\002USERMASK\002), your services access status\n"
"(\002STATUS\002) and last quit message (\002QUIT\002).\n"
"The second parameter specifies whether the information should\n"
@@ -232,27 +258,28 @@ class CommandNSSetHide : public Command
}
};
-class CommandNSSASetHide : public CommandNSSetHide
+class CommandNSSASetHide final
+ : public CommandNSSetHide
{
- public:
+public:
CommandNSSASetHide(Module *creator) : CommandNSSetHide(creator, "nickserv/saset/hide", 3)
{
this->SetSyntax(_("\037nickname\037 {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->ClearSyntax();
this->Run(source, params[0], params[1], params[2]);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s \002INFO\002 on the\n"
- "nick. You can hide the E-mail address (\002EMAIL\002), last seen\n"
+ "nick. You can hide the email address (\002EMAIL\002), last seen\n"
"user@host mask (\002USERMASK\002), the services access status\n"
"(\002STATUS\002) and last quit message (\002QUIT\002).\n"
"The second parameter specifies whether the information should\n"
@@ -261,7 +288,8 @@ class CommandNSSASetHide : public CommandNSSetHide
}
};
-class NSInfo : public Module
+class NSInfo final
+ : public Module
{
CommandNSInfo commandnsinfo;
@@ -270,7 +298,7 @@ class NSInfo : public Module
SerializableExtensibleItem<bool> hide_email, hide_usermask, hide_status, hide_quit;
- public:
+public:
NSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsinfo(this), commandnssethide(this), commandnssasethide(this),
hide_email(this, "HIDE_EMAIL"), hide_usermask(this, "HIDE_MASK"), hide_status(this, "HIDE_STATUS"),
diff --git a/modules/commands/ns_list.cpp b/modules/nickserv/ns_list.cpp
index 490dc04e7..c322d259b 100644
--- a/modules/commands/ns_list.cpp
+++ b/modules/nickserv/ns_list.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandNSList : public Command
+class CommandNSList final
+ : public Command
{
- public:
+public:
CommandNSList(Module *creator) : Command(creator, "nickserv/list", 1, 2)
{
this->SetDesc(_("List all registered nicknames that match a given pattern"));
this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string pattern = params[0];
@@ -38,17 +39,17 @@ class CommandNSList : public Command
Anope::string n1, n2;
sepstream(pattern.substr(1), '-').GetToken(n1, 0);
sepstream(pattern, '-').GetToken(n2, 1);
- try
- {
- from = convertTo<int>(n1);
- to = convertTo<int>(n2);
- }
- catch (const ConvertException &)
+
+ auto num1 = Anope::TryConvert<int>(n1);
+ auto num2 = Anope::TryConvert<int>(n2);
+ if (!num1.has_value() || !num2.has_value())
{
source.Reply(LIST_INCORRECT_RANGE);
return;
}
+ from = num1.value();
+ to = num2.value();
pattern = "*";
}
@@ -75,13 +76,11 @@ class CommandNSList : public Command
list.AddColumn(_("Nick")).AddColumn(_("Last usermask"));
Anope::map<NickAlias *> ordered_map;
- for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
- ordered_map[it->first] = it->second;
+ for (const auto &[nick, na] : *NickAliasList)
+ ordered_map[nick] = na;
- for (Anope::map<NickAlias *>::const_iterator it = ordered_map.begin(), it_end = ordered_map.end(); it != it_end; ++it)
+ for (const auto &[_, na] : ordered_map)
{
- const NickAlias *na = it->second;
-
/* Don't show private nicks to non-services admins. */
if (na->nc->HasExt("NS_PRIVATE") && !is_servadmin && na->nc != mync)
continue;
@@ -125,14 +124,14 @@ class CommandNSList : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of list - %d/%d matches shown."), nnicks > listmax ? listmax : nnicks, nnicks);
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -178,9 +177,10 @@ class CommandNSList : public Command
};
-class CommandNSSetPrivate : public Command
+class CommandNSSetPrivate
+ : public Command
{
- public:
+public:
CommandNSSetPrivate(Module *creator, const Anope::string &sname = "nickserv/set/private", size_t min = 1) : Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Prevent the nickname from appearing in the LIST command"));
@@ -224,12 +224,12 @@ class CommandNSSetPrivate : public Command
this->OnSyntaxError(source, "PRIVATE");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, params[0]);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -243,21 +243,22 @@ class CommandNSSetPrivate : public Command
}
};
-class CommandNSSASetPrivate : public CommandNSSetPrivate
+class CommandNSSASetPrivate final
+ : public CommandNSSetPrivate
{
- public:
+public:
CommandNSSASetPrivate(Module *creator) : CommandNSSetPrivate(creator, "nickserv/saset/private", 2)
{
this->ClearSyntax();
this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, params[0], params[1]);
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -272,7 +273,8 @@ class CommandNSSASetPrivate : public CommandNSSetPrivate
};
-class NSList : public Module
+class NSList final
+ : public Module
{
CommandNSList commandnslist;
@@ -281,14 +283,14 @@ class NSList : public Module
SerializableExtensibleItem<bool> priv;
- public:
+public:
NSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnslist(this), commandnssetprivate(this), commandnssasetprivate(this),
priv(this, "NS_PRIVATE")
{
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_all) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_all) override
{
if (!show_all)
return;
diff --git a/modules/commands/ns_logout.cpp b/modules/nickserv/ns_logout.cpp
index 60738a9ea..90f9f295a 100644
--- a/modules/commands/ns_logout.cpp
+++ b/modules/nickserv/ns_logout.cpp
@@ -13,16 +13,17 @@
static ServiceReference<NickServService> NickServService("NickServService", "NickServ");
-class CommandNSLogout : public Command
+class CommandNSLogout final
+ : public Command
{
- public:
+public:
CommandNSLogout(Module *creator) : Command(creator, "nickserv/logout", 0, 2)
{
this->SetDesc(_("Reverses the effect of the IDENTIFY command"));
this->SetSyntax(_("[\037nickname\037 [REVALIDATE]]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = !params.empty() ? params[0] : "";
@@ -59,7 +60,7 @@ class CommandNSLogout : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -69,18 +70,19 @@ class CommandNSLogout : public Command
"yourself.\n"
" \n"
"With a parameter, does the same for the given nick. If you\n"
- "specify \002REVALIDATE\002 as well, Services will ask the given nick\n"
+ "specify \002REVALIDATE\002 as well, services will ask the given nick\n"
"to re-identify. This is limited to \002Services Operators\002."));
return true;
}
};
-class NSLogout : public Module
+class NSLogout final
+ : public Module
{
CommandNSLogout commandnslogout;
- public:
+public:
NSLogout(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnslogout(this)
{
diff --git a/modules/ns_maxemail.cpp b/modules/nickserv/ns_maxemail.cpp
index 23cb80405..45409188d 100644
--- a/modules/ns_maxemail.cpp
+++ b/modules/nickserv/ns_maxemail.cpp
@@ -12,12 +12,13 @@
#include "module.h"
-class NSMaxEmail : public Module
+class NSMaxEmail final
+ : public Module
{
- bool clean;
+ bool clean = false;
/* strip dots from username, and remove anything after the first + */
- Anope::string CleanMail(const Anope::string &email)
+ static Anope::string CleanMail(const Anope::string &email)
{
size_t host = email.find('@');
if (host == Anope::string::npos)
@@ -62,10 +63,8 @@ class NSMaxEmail : public Module
Anope::string cleanemail = clean ? CleanMail(email) : email;
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- const NickCore *nc = it->second;
-
Anope::string cleannc = clean ? CleanMail(nc->email) : nc->email;
if (unc != nc && cleanemail.equals_ci(cleannc))
@@ -75,18 +74,17 @@ class NSMaxEmail : public Module
return count;
}
- public:
+public:
NSMaxEmail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
- , clean(false)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
clean = conf->GetModule(this)->Get<bool>("remove_aliases", "true");
}
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
{
if (source.IsOper())
return EVENT_CONTINUE;
diff --git a/modules/commands/ns_recover.cpp b/modules/nickserv/ns_recover.cpp
index 756218361..4656f54e7 100644
--- a/modules/commands/ns_recover.cpp
+++ b/modules/nickserv/ns_recover.cpp
@@ -16,23 +16,24 @@ static ServiceReference<NickServService> nickserv("NickServService", "NickServ")
typedef std::map<Anope::string, ChannelStatus> NSRecoverInfo;
-class NSRecoverSvsnick
+class NSRecoverSvsnick final
{
- public:
+public:
Reference<User> from;
Anope::string to;
};
-class NSRecoverRequest : public IdentifyRequest
+class NSRecoverRequest final
+ : public IdentifyRequest
{
CommandSource source;
Command *cmd;
Anope::string user;
- public:
+public:
NSRecoverRequest(Module *o, CommandSource &src, Command *c, const Anope::string &nick, const Anope::string &pass) : IdentifyRequest(o, nick, pass), source(src), cmd(c), user(nick) { }
- void OnSuccess() anope_override
+ void OnSuccess() override
{
User *u = User::Find(user, true);
if (!source.GetUser() || !source.service)
@@ -58,7 +59,7 @@ class NSRecoverRequest : public IdentifyRequest
// same person that is executing the command, so kill them off (old GHOST command).
else if (u->Account() == na->nc)
{
- if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
+ if (!source.GetAccount())
{
source.GetUser()->Login(u->Account());
Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << u->Account()->display;
@@ -69,8 +70,8 @@ class NSRecoverRequest : public IdentifyRequest
if (!u->chans.empty())
{
NSRecoverInfo *ei = source.GetUser()->Extend<NSRecoverInfo>("recover");
- for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
- (*ei)[it->first->name] = it->second->status;
+ for (auto &[chan, cuc] : u->chans)
+ (*ei)[chan->name] = cuc->status;
}
}
@@ -89,7 +90,7 @@ class NSRecoverRequest : public IdentifyRequest
/* User is not identified or not identified to the same account as the person using this command */
else
{
- if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
+ if (!source.GetAccount())
{
source.GetUser()->Login(na->nc); // Identify the user using the command if they arent identified
Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << na->nick << " (" << na->nc->display << ")";
@@ -124,7 +125,7 @@ class NSRecoverRequest : public IdentifyRequest
}
}
- void OnFail() anope_override
+ void OnFail() override
{
if (NickAlias::Find(GetAccount()) != NULL)
{
@@ -141,9 +142,10 @@ class NSRecoverRequest : public IdentifyRequest
}
};
-class CommandNSRecover : public Command
+class CommandNSRecover final
+ : public Command
{
- public:
+public:
CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2)
{
this->SetDesc(_("Regains control of your nick"));
@@ -151,7 +153,7 @@ class CommandNSRecover : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = params[0];
const Anope::string &pass = params.size() > 1 ? params[1] : "";
@@ -180,8 +182,6 @@ class CommandNSRecover : public Command
bool ok = false;
if (source.GetAccount() == na->nc)
ok = true;
- else if (!na->nc->HasExt("NS_SECURE") && source.GetUser() && na->nc->IsOnAccess(source.GetUser()))
- ok = true;
NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
if (source.GetUser() && !source.GetUser()->fingerprint.empty() && cl && cl->FindCert(source.GetUser()->fingerprint))
@@ -190,9 +190,9 @@ class CommandNSRecover : public Command
if (source.HasPriv("nickserv/recover"))
ok = true;
- if (ok == false && !pass.empty())
+ if (!ok && !pass.empty())
{
- NSRecoverRequest *req = new NSRecoverRequest(owner, source, this, na->nick, pass);
+ auto *req = new NSRecoverRequest(owner, source, this, na->nick, pass);
FOREACH_MOD(OnCheckAuthentication, (source.GetUser(), req));
req->Dispatch();
}
@@ -207,7 +207,7 @@ class CommandNSRecover : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -221,13 +221,14 @@ class CommandNSRecover : public Command
}
};
-class NSRecover : public Module
+class NSRecover final
+ : public Module
{
CommandNSRecover commandnsrecover;
PrimitiveExtensibleItem<NSRecoverInfo> recover;
PrimitiveExtensibleItem<NSRecoverSvsnick> svsnick;
- public:
+public:
NSRecover(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsrecover(this), recover(this, "recover"), svsnick(this, "svsnick")
{
@@ -237,7 +238,7 @@ class NSRecover : public Module
}
- void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
+ void OnUserNickChange(User *u, const Anope::string &oldnick) override
{
if (Config->GetModule(this)->Get<bool>("restoreonrecover"))
{
@@ -272,7 +273,7 @@ class NSRecover : public Module
}
}
- void OnJoinChannel(User *u, Channel *c) anope_override
+ void OnJoinChannel(User *u, Channel *c) override
{
if (Config->GetModule(this)->Get<bool>("restoreonrecover"))
{
@@ -283,8 +284,8 @@ class NSRecover : public Module
NSRecoverInfo::iterator it = ei->find(c->name);
if (it != ei->end())
{
- for (size_t i = 0; i < it->second.Modes().length(); ++i)
- c->SetMode(c->WhoSends(), ModeManager::FindChannelModeByChar(it->second.Modes()[i]), u->GetUID());
+ for (auto mode : it->second.Modes())
+ c->SetMode(c->WhoSends(), ModeManager::FindChannelModeByChar(mode), u->GetUID());
ei->erase(it);
if (ei->empty())
diff --git a/modules/commands/ns_register.cpp b/modules/nickserv/ns_register.cpp
index 7abf26978..38fa55ca5 100644
--- a/modules/commands/ns_register.cpp
+++ b/modules/nickserv/ns_register.cpp
@@ -13,9 +13,12 @@
static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi);
-class CommandNSConfirm : public Command
+static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
+
+class CommandNSConfirm final
+ : public Command
{
- public:
+public:
CommandNSConfirm(Module *creator) : Command(creator, "nickserv/confirm", 1, 2)
{
this->SetDesc(_("Confirm a passcode"));
@@ -23,7 +26,7 @@ class CommandNSConfirm : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string *code = source.nc ? source.nc->GetExt<Anope::string>("passcode") : NULL;
bool confirming_other = !code || *code != params[0];
@@ -34,7 +37,7 @@ class CommandNSConfirm : public Command
NickAlias *na = NickAlias::Find(nick);
if (na == NULL)
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
- else if (na->nc->HasExt("UNCONFIRMED") == false)
+ else if (!na->nc->HasExt("UNCONFIRMED"))
source.Reply(_("Nick \002%s\002 is already confirmed."), na->nick.c_str());
else
{
@@ -90,7 +93,7 @@ class CommandNSConfirm : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -108,15 +111,16 @@ class CommandNSConfirm : public Command
return true;
}
- void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) anope_override
+ void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) override
{
source.Reply(NICK_CONFIRM_INVALID);
}
};
-class CommandNSRegister : public Command
+class CommandNSRegister final
+ : public Command
{
- public:
+public:
CommandNSRegister(Module *creator) : Command(creator, "nickserv/register", 1, 2)
{
this->SetDesc(_("Register a nickname"));
@@ -127,18 +131,17 @@ class CommandNSRegister : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
User *u = source.GetUser();
Anope::string u_nick = source.GetNick();
- size_t nicklen = u_nick.length();
Anope::string pass = params[0];
Anope::string email = params.size() > 1 ? params[1] : "";
const Anope::string &nsregister = Config->GetModule(this->owner)->Get<const Anope::string>("registration");
if (Anope::ReadOnly)
{
- source.Reply(_("Sorry, nickname registration is temporarily disabled."));
+ source.Reply(READ_ONLY_MODE);
return;
}
@@ -152,17 +155,13 @@ class CommandNSRegister : public Command
time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay");
if (u && !u->HasMode("OPER") && nickregdelay && Anope::CurTime - u->timestamp < nickregdelay)
{
- source.Reply(_("You must have been using this nick for at least %d seconds to register."), nickregdelay);
+ auto waitperiod = (u->timestamp + nickregdelay) - Anope::CurTime;
+ source.Reply(_("You must wait %s before registering your nick."),
+ Anope::Duration(waitperiod, source.GetAccount()).c_str());
return;
}
- /* Prevent "Guest" nicks from being registered. -TheShadow */
-
- /* Guest nick can now have a series of between 1 and 7 digits.
- * --lara
- */
- const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest");
- if (nicklen <= guestnick.length() + 7 && nicklen >= guestnick.length() + 1 && !u_nick.find_ci(guestnick) && u_nick.substr(guestnick.length()).find_first_not_of("1234567890") == Anope::string::npos)
+ if (nickserv && nickserv->IsGuestNick(u_nick))
{
source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str());
return;
@@ -182,10 +181,8 @@ class CommandNSRegister : public Command
if (Config->GetModule("nickserv")->Get<bool>("restrictopernicks"))
{
- for (unsigned i = 0; i < Oper::opers.size(); ++i)
+ for (auto *o : Oper::opers)
{
- Oper *o = Oper::opers[i];
-
if (!source.IsOper() && u_nick.find_ci(o->name) != Anope::string::npos)
{
source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str());
@@ -194,27 +191,41 @@ class CommandNSRegister : public Command
}
}
- unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
+ unsigned int minpasslen = Config->GetModule("nickserv")->Get<unsigned>("minpasslen", "10");
+ unsigned int maxpasslen = Config->GetModule("nickserv")->Get<unsigned>("maxpasslen", "50");
if (Config->GetModule("nickserv")->Get<bool>("forceemail", "yes") && email.empty())
this->OnSyntaxError(source, "");
else if (u && Anope::CurTime < u->lastnickreg + reg_delay)
- source.Reply(_("Please wait %d seconds before using the REGISTER command again."), (u->lastnickreg + reg_delay) - Anope::CurTime);
+ {
+ auto waitperiod = (unsigned long)(u->lastnickreg + reg_delay) - Anope::CurTime;
+ source.Reply(_("Please wait %s before using the REGISTER command again."),
+ Anope::Duration(waitperiod, source.GetAccount()).c_str());
+ }
else if (NickAlias::Find(u_nick) != NULL)
source.Reply(NICK_ALREADY_REGISTERED, u_nick.c_str());
- else if (pass.equals_ci(u_nick) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && pass.length() < 5))
+ else if (pass.equals_ci(u_nick))
source.Reply(MORE_OBSCURE_PASSWORD);
- else if (pass.length() > passlen)
- source.Reply(PASSWORD_TOO_LONG, passlen);
+ else if (pass.length() < minpasslen)
+ source.Reply(PASSWORD_TOO_SHORT, minpasslen);
+ else if (pass.length() > maxpasslen)
+ source.Reply(PASSWORD_TOO_LONG, maxpasslen);
else if (!email.empty() && !Mail::Validate(email))
source.Reply(MAIL_X_INVALID, email.c_str());
else
{
- NickCore *nc = new NickCore(u_nick);
- NickAlias *na = new NickAlias(u_nick, nc);
- Anope::Encrypt(pass, nc->pass);
+ Anope::string encpass;
+ if (!Anope::Encrypt(pass, encpass))
+ {
+ source.Reply(_("Accounts can not be registered right now. Please try again later."));
+ return;
+ }
+
+ auto *nc = new NickCore(u_nick);
+ auto *na = new NickAlias(u_nick, nc);
if (!email.empty())
nc->email = email;
+ nc->pass = encpass;
if (u)
{
@@ -226,15 +237,7 @@ class CommandNSRegister : public Command
Log(LOG_COMMAND, source, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
- if (na->nc->GetAccessCount())
- source.Reply(_("Nickname \002%s\002 registered under your user@host-mask: %s"), u_nick.c_str(), na->nc->GetAccess(0).c_str());
- else
- source.Reply(_("Nickname \002%s\002 registered."), u_nick.c_str());
-
- Anope::string tmp_pass;
- if (Anope::Decrypt(na->nc->pass, tmp_pass) == 1)
- source.Reply(_("Your password is \002%s\002 - remember this for later use."), tmp_pass.c_str());
-
+ source.Reply(_("Nickname \002%s\002 registered."), u_nick.c_str());
if (nsregister.equals_ci("admin"))
{
nc->Extend<bool>("UNCONFIRMED");
@@ -266,8 +269,9 @@ class CommandNSRegister : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
+ unsigned int minpasslen = Config->GetModule("nickserv")->Get<unsigned>("minpasslen", "10");
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Registers your nickname in the %s database. Once\n"
@@ -285,17 +289,16 @@ class CommandNSRegister : public Command
"your nickname as a password is a much worse idea ;) and,\n"
"in fact, %s will not allow it. Also, short\n"
"passwords are vulnerable to trial-and-error searches, so\n"
- "you should choose a password at least 5 characters long.\n"
+ "you should choose a password at least %u characters long.\n"
"Finally, the space character cannot be used in passwords."),
- source.service->nick.c_str(), source.service->nick.c_str());
+ source.service->nick.c_str(), source.service->nick.c_str(),
+ minpasslen);
if (!Config->GetModule("nickserv")->Get<bool>("forceemail", "yes"))
{
source.Reply(" ");
source.Reply(_("The \037email\037 parameter is optional and will set the email\n"
- "for your nick immediately.\n"
- "Your privacy is respected; this e-mail won't be given to\n"
- "any third-party person. You may also wish to \002SET HIDE\002 it\n"
+ "for your nick immediately. You may also wish to \002SET HIDE\002 it\n"
"after registering if it isn't the default setting already."));
}
@@ -308,15 +311,16 @@ class CommandNSRegister : public Command
}
};
-class CommandNSResend : public Command
+class CommandNSResend final
+ : public Command
{
- public:
+public:
CommandNSResend(Module *creator) : Command(creator, "nickserv/resend", 0, 0)
{
this->SetDesc(_("Resend registration confirmation email"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!Config->GetModule(this->owner)->Get<const Anope::string>("registration").equals_ci("mail"))
{
@@ -347,7 +351,7 @@ class CommandNSResend : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (!Config->GetModule(this->owner)->Get<const Anope::string>("registration").equals_ci("mail"))
return false;
@@ -358,14 +362,15 @@ class CommandNSResend : public Command
return true;
}
- void OnServHelp(CommandSource &source) anope_override
+ void OnServHelp(CommandSource &source) override
{
if (Config->GetModule(this->owner)->Get<const Anope::string>("registration").equals_ci("mail"))
Command::OnServHelp(source);
}
};
-class NSRegister : public Module
+class NSRegister final
+ : public Module
{
CommandNSRegister commandnsregister;
CommandNSConfirm commandnsconfirm;
@@ -374,7 +379,7 @@ class NSRegister : public Module
SerializableExtensibleItem<bool> unconfirmed;
SerializableExtensibleItem<Anope::string> passcode;
- public:
+public:
NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsregister(this), commandnsconfirm(this), commandnsrsend(this), unconfirmed(this, "UNCONFIRMED"),
passcode(this, "passcode")
@@ -383,7 +388,7 @@ class NSRegister : public Module
throw ModuleException("Module " + this->name + " will not load with registration disabled.");
}
- void OnNickIdentify(User *u) anope_override
+ void OnNickIdentify(User *u) override
{
BotInfo *NickServ;
if (unconfirmed.HasExt(u->Account()) && (NickServ = Config->GetClient("NickServ")))
@@ -393,7 +398,7 @@ class NSRegister : public Module
u->SendMessage(NickServ, _("All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."));
else
u->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you."));
- const NickAlias *this_na = NickAlias::Find(u->Account()->display);
+ const NickAlias *this_na = u->AccountNick();
time_t time_registered = Anope::CurTime - this_na->time_registered;
time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d");
if (unconfirmed_expire > time_registered)
@@ -401,7 +406,7 @@ class NSRegister : public Module
}
}
- void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+ void OnPreNickExpire(NickAlias *na, bool &expire) override
{
if (unconfirmed.HasExt(na->nc))
{
@@ -420,7 +425,7 @@ static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi)
if (code == NULL)
{
code = na->nc->Extend<Anope::string>("passcode");
- *code = Anope::Random(9);
+ *code = Anope::Random(15);
}
Anope::string subject = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("registration_subject").c_str()),
diff --git a/modules/commands/ns_resetpass.cpp b/modules/nickserv/ns_resetpass.cpp
index 09427e38a..fbb8d1540 100644
--- a/modules/commands/ns_resetpass.cpp
+++ b/modules/nickserv/ns_resetpass.cpp
@@ -13,9 +13,10 @@
static bool SendResetEmail(User *u, const NickAlias *na, BotInfo *bi);
-class CommandNSResetPass : public Command
+class CommandNSResetPass final
+ : public Command
{
- public:
+public:
CommandNSResetPass(Module *creator) : Command(creator, "nickserv/resetpass", 2, 2)
{
this->SetDesc(_("Helps you reset lost passwords"));
@@ -23,7 +24,7 @@ class CommandNSResetPass : public Command
this->AllowUnregistered(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const NickAlias *na;
@@ -45,7 +46,7 @@ class CommandNSResetPass : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -56,18 +57,19 @@ class CommandNSResetPass : public Command
}
};
-struct ResetInfo
+struct ResetInfo final
{
Anope::string code;
time_t time;
};
-class NSResetPass : public Module
+class NSResetPass final
+ : public Module
{
CommandNSResetPass commandnsresetpass;
PrimitiveExtensibleItem<ResetInfo> reset;
- public:
+public:
NSResetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsresetpass(this), reset(this, "reset")
{
@@ -75,7 +77,7 @@ class NSResetPass : public Module
throw ModuleException("Not using mail.");
}
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
{
if (command->name == "nickserv/confirm" && params.size() > 1)
{
@@ -114,7 +116,7 @@ class NSResetPass : public Module
{
source.GetUser()->Identify(na);
}
-
+
source.Reply(_("You are now identified for your nick. Change your password now."));
}
else
diff --git a/modules/nickserv/ns_set.cpp b/modules/nickserv/ns_set.cpp
new file mode 100644
index 000000000..a1291fe26
--- /dev/null
+++ b/modules/nickserv/ns_set.cpp
@@ -0,0 +1,828 @@
+/* NickServ core functions
+ *
+ * (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"
+
+class CommandNSSet final
+ : public Command
+{
+public:
+ CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3)
+ {
+ this->SetDesc(_("Set nickname options and information"));
+ this->SetSyntax(_("\037option\037 \037parameters\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->OnSyntaxError(source, "");
+ return;
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets various nickname options. \037option\037 can be one of:"));
+
+ Anope::string this_name = source.command;
+ bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
+ hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
+ for (const auto &[c_name, info] : source.service->commands)
+ {
+ if (c_name.find_ci(this_name + " ") == 0)
+ {
+ if (info.hide)
+ continue;
+
+ ServiceReference<Command> c("Command", info.name);
+ // XXX dup
+ if (!c)
+ continue;
+ else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
+ continue;
+ else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
+ continue;
+
+ source.command = c_name;
+ c->OnServHelp(source);
+ }
+ }
+
+ source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
+ "on a specific option."), source.service->GetQueryCommand().c_str(), this_name.c_str());
+
+ return true;
+ }
+};
+
+class CommandNSSASet final
+ : public Command
+{
+public:
+ CommandNSSASet(Module *creator) : Command(creator, "nickserv/saset", 2, 4)
+ {
+ this->SetDesc(_("Set SET-options on another nickname"));
+ this->SetSyntax(_("\037option\037 \037nickname\037 \037parameters\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->OnSyntaxError(source, "");
+ return;
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets various nickname options. \037option\037 can be one of:"));
+
+ Anope::string this_name = source.command;
+ for (const auto &[c_name, info] : source.service->commands)
+ {
+ if (c_name.find_ci(this_name + " ") == 0)
+ {
+ ServiceReference<Command> command("Command", info.name);
+ if (command)
+ {
+ source.command = c_name;
+ command->OnServHelp(source);
+ }
+ }
+ }
+
+ source.Reply(_("Type \002%s HELP %s \037option\037\002 for more information\n"
+ "on a specific option. The options will be set on the given\n"
+ "\037nickname\037."), source.service->GetQueryCommand().c_str(), this_name.c_str());
+ return true;
+ }
+};
+
+class CommandNSSetPassword final
+ : public Command
+{
+public:
+ CommandNSSetPassword(Module *creator) : Command(creator, "nickserv/set/password", 1)
+ {
+ this->SetDesc(_("Set your nickname password"));
+ this->SetSyntax(_("\037new-password\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ const Anope::string &param = params[0];
+ unsigned len = param.length();
+
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ if (source.GetNick().equals_ci(param))
+ {
+ source.Reply(MORE_OBSCURE_PASSWORD);
+ return;
+ }
+
+ unsigned int minpasslen = Config->GetModule("nickserv")->Get<unsigned>("minpasslen", "10");
+ if (len < minpasslen)
+ {
+ source.Reply(PASSWORD_TOO_SHORT, minpasslen);
+ return;
+ }
+
+ unsigned int maxpasslen = Config->GetModule("nickserv")->Get<unsigned>("maxpasslen", "50");
+ if (len > maxpasslen)
+ {
+ source.Reply(PASSWORD_TOO_LONG, maxpasslen);
+ return;
+ }
+
+ if (!Anope::Encrypt(param, source.nc->pass))
+ {
+ source.Reply(_("Passwords can not be changed right now. Please try again later."));
+ return;
+ }
+
+ Log(LOG_COMMAND, source, this) << "to change their password";
+ source.Reply(_("Password for \002%s\002 changed."), source.nc->display.c_str());
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Changes the password used to identify you as the nick's\n"
+ "owner."));
+ return true;
+ }
+};
+
+class CommandNSSASetPassword final
+ : public Command
+{
+public:
+ CommandNSSASetPassword(Module *creator) : Command(creator, "nickserv/saset/password", 2, 2)
+ {
+ this->SetDesc(_("Set the nickname password"));
+ this->SetSyntax(_("\037nickname\037 \037new-password\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *setter_na = NickAlias::Find(params[0]);
+ if (setter_na == NULL)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+ NickCore *nc = setter_na->nc;
+
+ size_t len = params[1].length();
+
+ if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper())
+ {
+ source.Reply(_("You may not change the password of other Services Operators."));
+ return;
+ }
+
+ if (nc->display.equals_ci(params[1]))
+ {
+ source.Reply(MORE_OBSCURE_PASSWORD);
+ return;
+ }
+
+ unsigned int minpasslen = Config->GetModule("nickserv")->Get<unsigned>("minpasslen", "10");
+ if (len < minpasslen)
+ {
+ source.Reply(PASSWORD_TOO_SHORT, minpasslen);
+ return;
+ }
+
+ unsigned int maxpasslen = Config->GetModule("nickserv")->Get<unsigned>("maxpasslen", "50");
+ if (len > maxpasslen)
+ {
+ source.Reply(PASSWORD_TOO_LONG, maxpasslen);
+ return;
+ }
+
+ if (!Anope::Encrypt(params[1], nc->pass))
+ {
+ source.Reply(_("Passwords can not be changed right now. Please try again later."));
+ return;
+ }
+
+ Log(LOG_ADMIN, source, this) << "to change the password of " << nc->display;
+ source.Reply(_("Password for \002%s\002 changed."), nc->display.c_str());
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Changes the password used to identify as the nick's owner."));
+ return true;
+ }
+};
+
+class CommandNSSetAutoOp
+ : public Command
+{
+public:
+ CommandNSSetAutoOp(Module *creator, const Anope::string &sname = "nickserv/set/autoop", size_t min = 1) : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Sets whether services should set channel status modes on you automatically."));
+ this->SetSyntax("{ON | OFF}");
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (na == NULL)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (param.equals_ci("ON"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable autoop for " << na->nc->display;
+ nc->Extend<bool>("AUTOOP");
+ source.Reply(_("Services will from now on set status modes on %s in channels."), nc->display.c_str());
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable autoop for " << na->nc->display;
+ nc->Shrink<bool>("AUTOOP");
+ source.Reply(_("Services will no longer set status modes on %s in channels."), nc->display.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "AUTOOP");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ BotInfo *bi = Config->GetClient("ChanServ");
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets whether you will be given your channel status modes automatically.\n"
+ "Set to \002ON\002 to allow %s to set status modes on you automatically\n"
+ "when entering channels. Note that depending on channel settings some modes\n"
+ "may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ");
+ return true;
+ }
+};
+
+class CommandNSSASetAutoOp final
+ : public CommandNSSetAutoOp
+{
+public:
+ CommandNSSASetAutoOp(Module *creator) : CommandNSSetAutoOp(creator, "nickserv/saset/autoop", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ BotInfo *bi = Config->GetClient("ChanServ");
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets whether the given nickname will be given its status modes\n"
+ "in channels automatically. Set to \002ON\002 to allow %s\n"
+ "to set status modes on the given nickname automatically when it\n"
+ "is entering channels. Note that depending on channel settings\n"
+ "some modes may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ");
+ return true;
+ }
+};
+
+class CommandNSSetNeverOp
+ : public Command
+{
+public:
+ CommandNSSetNeverOp(Module *creator, const Anope::string &sname = "nickserv/set/neverop", size_t min = 1) : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Sets whether you can be added to a channel access list."));
+ this->SetSyntax("{ON | OFF}");
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (na == NULL)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (param.equals_ci("ON"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable neverop for " << na->nc->display;
+ nc->Extend<bool>("NEVEROP");
+ source.Reply(_("%s can no longer be added to channel access lists."), nc->display.c_str());
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable neverop for " << na->nc->display;
+ nc->Shrink<bool>("NEVEROP");
+ source.Reply(_("%s can now be added to channel access lists."), nc->display.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "NEVEROP");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets whether you can be added to a channel access list."));
+ return true;
+ }
+};
+
+class CommandNSSASetNeverOp final
+ : public CommandNSSetNeverOp
+{
+public:
+ CommandNSSASetNeverOp(Module *creator) : CommandNSSetNeverOp(creator, "nickserv/saset/neverop", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets whether the given nickname can be added to a channel access list."));
+ return true;
+ }
+};
+
+class CommandNSSetDisplay
+ : public Command
+{
+public:
+ CommandNSSetDisplay(Module *creator, const Anope::string &sname = "nickserv/set/display", size_t min = 1) : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Set the display of your group in services"));
+ this->SetSyntax(_("\037new-display\037"));
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ NickAlias *user_na = NickAlias::Find(user), *na = NickAlias::Find(param);
+
+ if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
+ {
+ source.Reply(_("This command may not be used on this network because nickname ownership is disabled."));
+ return;
+ }
+ if (user_na == NULL)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ else if (!na || *na->nc != *user_na->nc)
+ {
+ source.Reply(_("The new display MUST be a nickname of the nickname group %s."), user_na->nc->display.c_str());
+ return;
+ }
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, user_na->nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ Log(user_na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the display of " << user_na->nc->display << " to " << na->nick;
+
+ user_na->nc->SetDisplay(na);
+
+ /* Send updated account name */
+ for (std::list<User *>::iterator it = user_na->nc->users.begin(); it != user_na->nc->users.end(); ++it)
+ {
+ User *u = *it;
+ IRCD->SendLogin(u, user_na);
+ }
+
+ source.Reply(NICK_SET_DISPLAY_CHANGED, user_na->nc->display.c_str());
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Changes the display used to refer to your nickname group in\n"
+ "services. The new display MUST be a nick of your group."));
+ return true;
+ }
+};
+
+class CommandNSSASetDisplay final
+ : public CommandNSSetDisplay
+{
+public:
+ CommandNSSASetDisplay(Module *creator) : CommandNSSetDisplay(creator, "nickserv/saset/display", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 \037new-display\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Changes the display used to refer to the nickname group in\n"
+ "services. The new display MUST be a nick of the group."));
+ return true;
+ }
+};
+
+class CommandNSSetEmail
+ : public Command
+{
+ static bool SendConfirmMail(User *u, NickCore *nc, BotInfo *bi, const Anope::string &new_email)
+ {
+ Anope::string code = Anope::Random(15);
+
+ std::pair<Anope::string, Anope::string> *n = nc->Extend<std::pair<Anope::string, Anope::string> >("ns_set_email");
+ n->first = new_email;
+ n->second = code;
+
+ Anope::string subject = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_subject"),
+ message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message");
+
+ subject = subject.replace_all_cs("%e", nc->email);
+ subject = subject.replace_all_cs("%E", new_email);
+ subject = subject.replace_all_cs("%n", nc->display);
+ subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
+ subject = subject.replace_all_cs("%c", code);
+
+ message = message.replace_all_cs("%e", nc->email);
+ message = message.replace_all_cs("%E", new_email);
+ message = message.replace_all_cs("%n", nc->display);
+ message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
+ message = message.replace_all_cs("%c", code);
+
+ Anope::string old = nc->email;
+ nc->email = new_email;
+ bool b = Mail::Send(u, nc, bi, subject, message);
+ nc->email = old;
+ return b;
+ }
+
+public:
+ CommandNSSetEmail(Module *creator, const Anope::string &cname = "nickserv/set/email", size_t min = 0) : Command(creator, cname, min, min + 1)
+ {
+ this->SetDesc(_("Associate an email address with your nickname"));
+ this->SetSyntax(_("\037address\037"));
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ if (nc->HasExt("UNCONFIRMED"))
+ {
+ source.Reply(_("You may not change the email of an unconfirmed account."));
+ return;
+ }
+
+ if (param.empty() && Config->GetModule("nickserv")->Get<bool>("forceemail", "yes"))
+ {
+ source.Reply(_("You cannot unset the email on this network."));
+ return;
+ }
+ else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper())
+ {
+ source.Reply(_("You may not change the email of other Services Operators."));
+ return;
+ }
+ else if (!param.empty() && !Mail::Validate(param))
+ {
+ source.Reply(MAIL_X_INVALID, param.c_str());
+ return;
+ }
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ const auto nsmailreg = Config->GetModule("ns_register")->Get<const Anope::string>("registration").equals_ci("mail");
+ if (!param.empty() && Config->GetModule("nickserv")->Get<bool>("confirmemailchanges", nsmailreg ? "yes" : "no") && !source.IsServicesOper())
+ {
+ if (SendConfirmMail(source.GetUser(), source.GetAccount(), source.service, param))
+ {
+ Log(LOG_COMMAND, source, this) << "to request changing the email of " << nc->display << " to " << param;
+ source.Reply(_("A confirmation email has been sent to \002%s\002. Follow the instructions in it to change your email address."), param.c_str());
+ }
+ }
+ else
+ {
+ if (!param.empty())
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the email of " << nc->display << " to " << param;
+ nc->email = param;
+ source.Reply(_("Email address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
+ }
+ else
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the email of " << nc->display;
+ nc->email.clear();
+ source.Reply(_("Email address for \002%s\002 unset."), nc->display.c_str());
+ }
+ }
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params.size() ? params[0] : "");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Associates the given email address with your nickname.\n"
+ "This address will be displayed whenever someone requests\n"
+ "information on the nickname with the \002INFO\002 command."));
+ return true;
+ }
+};
+
+class CommandNSSASetEmail final
+ : public CommandNSSetEmail
+{
+public:
+ CommandNSSASetEmail(Module *creator) : CommandNSSetEmail(creator, "nickserv/saset/email", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 \037address\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params.size() > 1 ? params[1] : "");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Associates the given email address with the nickname."));
+ return true;
+ }
+};
+
+class CommandNSSASetNoexpire final
+ : public Command
+{
+public:
+ CommandNSSASetNoexpire(Module *creator) : Command(creator, "nickserv/saset/noexpire", 1, 2)
+ {
+ this->SetDesc(_("Prevent the nickname from expiring"));
+ this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ NickAlias *na = NickAlias::Find(params[0]);
+ if (na == NULL)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ Anope::string param = params.size() > 1 ? params[1] : "";
+
+ if (param.equals_ci("ON"))
+ {
+ Log(LOG_ADMIN, source, this) << "to enable noexpire for " << na->nick << " (" << na->nc->display << ")";
+ na->Extend<bool>("NS_NO_EXPIRE");
+ source.Reply(_("Nick %s \002will not\002 expire."), na->nick.c_str());
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ Log(LOG_ADMIN, source, this) << "to disable noexpire for " << na->nick << " (" << na->nc->display << ")";
+ na->Shrink<bool>("NS_NO_EXPIRE");
+ source.Reply(_("Nick %s \002will\002 expire."), na->nick.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "NOEXPIRE");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Sets whether the given nickname will expire. Setting this\n"
+ "to \002ON\002 prevents the nickname from expiring."));
+ return true;
+ }
+};
+
+class NSSet final
+ : public Module
+{
+ CommandNSSet commandnsset;
+ CommandNSSASet commandnssaset;
+
+ CommandNSSetAutoOp commandnssetautoop;
+ CommandNSSASetAutoOp commandnssasetautoop;
+
+ CommandNSSetNeverOp commandnssetneverop;
+ CommandNSSASetNeverOp commandnssasetneverop;
+
+ CommandNSSetDisplay commandnssetdisplay;
+ CommandNSSASetDisplay commandnssasetdisplay;
+
+ CommandNSSetEmail commandnssetemail;
+ CommandNSSASetEmail commandnssasetemail;
+
+ CommandNSSetPassword commandnssetpassword;
+ CommandNSSASetPassword commandnssasetpassword;
+
+ CommandNSSASetNoexpire commandnssasetnoexpire;
+
+ SerializableExtensibleItem<bool> autoop, neverop, noexpire;
+
+ /* email, passcode */
+ PrimitiveExtensibleItem<std::pair<Anope::string, Anope::string > > ns_set_email;
+
+public:
+ NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ commandnsset(this), commandnssaset(this),
+ commandnssetautoop(this), commandnssasetautoop(this),
+ commandnssetneverop(this), commandnssasetneverop(this),
+ commandnssetdisplay(this), commandnssasetdisplay(this),
+ commandnssetemail(this), commandnssasetemail(this),
+ commandnssetpassword(this), commandnssasetpassword(this),
+ commandnssasetnoexpire(this),
+
+ autoop(this, "AUTOOP"), neverop(this, "NEVEROP"),
+ noexpire(this, "NS_NO_EXPIRE"),
+ ns_set_email(this, "ns_set_email")
+ {
+ }
+
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
+ {
+ NickCore *uac = source.nc;
+
+ if (command->name == "nickserv/confirm" && !params.empty() && uac)
+ {
+ std::pair<Anope::string, Anope::string> *n = ns_set_email.Get(uac);
+ if (n)
+ {
+ if (params[0] == n->second)
+ {
+ uac->email = n->first;
+ Log(LOG_COMMAND, source, command) << "to confirm their email address change to " << uac->email;
+ source.Reply(_("Your email address has been changed to \002%s\002."), uac->email.c_str());
+ ns_set_email.Unset(uac);
+ return EVENT_STOP;
+ }
+ }
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) override
+ {
+ if (chan->ci)
+ {
+ /* Only give modes if autoop is set */
+ give_modes &= !user->IsIdentified() || autoop.HasExt(user->Account());
+ }
+ }
+
+ void OnPreNickExpire(NickAlias *na, bool &expire) override
+ {
+ if (noexpire.HasExt(na))
+ expire = false;
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
+ {
+ if (!show_hidden)
+ return;
+
+ if (autoop.HasExt(na->nc))
+ info.AddOption(_("Auto-op"));
+ if (neverop.HasExt(na->nc))
+ info.AddOption(_("Never-op"));
+ if (noexpire.HasExt(na))
+ info.AddOption(_("No expire"));
+ }
+
+ void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
+ {
+ if (u->IsIdentified() && setter.GetUser() == u)
+ u->Account()->last_modes = u->GetModeList();
+ }
+
+ void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override
+ {
+ if (u->IsIdentified() && setter.GetUser() == u)
+ u->Account()->last_modes = u->GetModeList();
+ }
+};
+
+MODULE_INIT(NSSet)
diff --git a/modules/nickserv/ns_set_keepmodes.cpp b/modules/nickserv/ns_set_keepmodes.cpp
new file mode 100644
index 000000000..e31b33dac
--- /dev/null
+++ b/modules/nickserv/ns_set_keepmodes.cpp
@@ -0,0 +1,206 @@
+/* NickServ core functions
+ *
+ * (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"
+
+class CommandNSSetKeepModes
+ : public Command
+{
+public:
+ CommandNSSetKeepModes(Module *creator, const Anope::string &sname = "nickserv/set/keepmodes", size_t min = 1)
+ : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Enable or disable keep modes"));
+ this->SetSyntax("{ON | OFF}");
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (param.equals_ci("ON"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable keepmodes for " << nc->display;
+ nc->Extend<bool>("NS_KEEP_MODES");
+ source.Reply(_("Keep modes for %s is now \002on\002."), nc->display.c_str());
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable keepmodes for " << nc->display;
+ nc->Shrink<bool>("NS_KEEP_MODES");
+ source.Reply(_("Keep modes for %s is now \002off\002."), nc->display.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Enables or disables keepmodes for your nick. If keep\n"
+ "modes is enabled, services will remember your usermodes\n"
+ "and attempt to re-set them the next time you authenticate."));
+ return true;
+ }
+};
+
+class CommandNSSASetKeepModes final
+ : public CommandNSSetKeepModes
+{
+public:
+ CommandNSSASetKeepModes(Module *creator)
+ : CommandNSSetKeepModes(creator, "nickserv/saset/keepmodes", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Enables or disables keepmodes for the given nick. If keep\n"
+ "modes is enabled, services will remember users' usermodes\n"
+ "and attempt to re-set them the next time they authenticate."));
+ return true;
+ }
+};
+
+
+class NSSetKeepModes final
+ : public Module
+{
+private:
+ CommandNSSetKeepModes commandnssetkeepmodes;
+ CommandNSSASetKeepModes commandnssasetkeepmodes;
+
+ struct KeepModes final
+ : SerializableExtensibleItem<bool>
+ {
+ KeepModes(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { }
+
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
+ {
+ SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data);
+
+ if (s->GetSerializableType()->GetName() != "NickCore")
+ return;
+
+ const NickCore *nc = anope_dynamic_static_cast<const NickCore *>(s);
+ Anope::string modes;
+ for (const auto &[last_mode, last_value] : nc->last_modes)
+ {
+ if (!modes.empty())
+ modes += " ";
+ modes += last_mode;
+ if (!last_value.empty())
+ modes += "," + last_value;
+ }
+ data.Store("last_modes", modes);
+ }
+
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
+ {
+ SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data);
+
+ if (s->GetSerializableType()->GetName() != "NickCore")
+ return;
+
+ NickCore *nc = anope_dynamic_static_cast<NickCore *>(s);
+ Anope::string modes;
+ data["last_modes"] >> modes;
+ nc->last_modes.clear();
+ for (spacesepstream sep(modes); sep.GetToken(modes);)
+ {
+ size_t c = modes.find(',');
+ if (c == Anope::string::npos)
+ nc->last_modes.emplace(modes, "");
+ else
+ nc->last_modes.emplace(modes.substr(0, c), modes.substr(c + 1));
+ }
+ }
+ } keep_modes;
+
+public:
+ NSSetKeepModes(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandnssetkeepmodes(this)
+ , commandnssasetkeepmodes(this)
+ , keep_modes(this, "NS_KEEP_MODES")
+ {
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
+ {
+ if (!show_hidden)
+ return;
+
+ if (keep_modes.HasExt(na->nc))
+ info.AddOption(_("Keep modes"));
+ }
+
+ void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
+ {
+ if (u->IsIdentified() && setter.GetUser() == u)
+ u->Account()->last_modes = u->GetModeList();
+ }
+
+ void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override
+ {
+ if (u->IsIdentified() && setter.GetUser() == u)
+ u->Account()->last_modes = u->GetModeList();
+ }
+
+ void OnUserLogin(User *u) override
+ {
+ if (keep_modes.HasExt(u->Account()))
+ {
+ const auto norestore = Config->GetModule(this)->Get<const Anope::string>("norestore");
+ User::ModeList modes = u->Account()->last_modes;
+ for (const auto &[last_mode, last_value] : modes)
+ {
+ auto *um = ModeManager::FindUserModeByName(last_mode);
+ if (um && um->CanSet(nullptr) && norestore.find(um->mchar) == Anope::string::npos)
+ u->SetMode(nullptr, last_mode, last_value);
+ }
+ }
+ }
+};
+
+MODULE_INIT(NSSetKeepModes)
diff --git a/modules/nickserv/ns_set_kill.cpp b/modules/nickserv/ns_set_kill.cpp
new file mode 100644
index 000000000..8447bf74f
--- /dev/null
+++ b/modules/nickserv/ns_set_kill.cpp
@@ -0,0 +1,189 @@
+/* NickServ core functions
+ *
+ * (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"
+
+class CommandNSSetKill
+ : public Command
+{
+public:
+ CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1)
+ : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Turn protection on or off"));
+ this->SetSyntax("{ON | QUICK | IMMED | OFF}");
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
+ {
+ source.Reply(_("This command may not be used on this network because nickname ownership is disabled."));
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (param.equals_ci("ON"))
+ {
+ nc->Extend<bool>("KILLPROTECT");
+ nc->Shrink<bool>("KILL_QUICK");
+ nc->Shrink<bool>("KILL_IMMED");
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display;
+ source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str());
+ }
+ else if (param.equals_ci("QUICK"))
+ {
+ nc->Extend<bool>("KILLPROTECT");
+ nc->Extend<bool>("KILL_QUICK");
+ nc->Shrink<bool>("KILL_IMMED");
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display;
+ source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str());
+ }
+ else if (param.equals_ci("IMMED"))
+ {
+ if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed"))
+ {
+ nc->Extend<bool>("KILLPROTECT");
+ nc->Shrink<bool>("KILL_QUICK");
+ nc->Extend<bool>("KILL_IMMED");
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display;
+ source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str());
+ }
+ else
+ source.Reply(_("The \002IMMED\002 option is not available on this network."));
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ nc->Shrink<bool>("KILLPROTECT");
+ nc->Shrink<bool>("KILL_QUICK");
+ nc->Shrink<bool>("KILL_IMMED");
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display;
+ source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "KILL");
+
+ return;
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Turns the automatic protection option for your nick\n"
+ "on or off. With protection on, if another user\n"
+ "tries to take your nick, they will be given one minute to\n"
+ "change to another nick, after which %s will forcibly change\n"
+ "their nick.\n"
+ " \n"
+ "If you select \002QUICK\002, the user will be given only 20 seconds\n"
+ "to change nicks instead of the usual 60. If you select\n"
+ "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
+ "warned first or given a chance to change their nick; please\n"
+ "do not use this option unless necessary. Also, your\n"
+ "network's administrators may have disabled this option."), source.service->nick.c_str());
+ return true;
+ }
+};
+
+class CommandNSSASetKill final
+ : public CommandNSSetKill
+{
+public:
+ CommandNSSASetKill(Module *creator)
+ : CommandNSSetKill(creator, "nickserv/saset/kill", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Turns the automatic protection option for the nick\n"
+ "on or off. With protection on, if another user\n"
+ "tries to take the nick, they will be given one minute to\n"
+ "change to another nick, after which %s will forcibly change\n"
+ "their nick.\n"
+ " \n"
+ "If you select \002QUICK\002, the user will be given only 20 seconds\n"
+ "to change nicks instead of the usual 60. If you select\n"
+ "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n"
+ "warned first or given a chance to change their nick; please\n"
+ "do not use this option unless necessary. Also, your\n"
+ "network's administrators may have disabled this option."), source.service->nick.c_str());
+ return true;
+ }
+};
+
+class NSSetKill final
+ : public Module
+{
+private:
+ CommandNSSetKill commandnssetkill;
+ CommandNSSASetKill commandnssasetkill;
+ SerializableExtensibleItem<bool> killprotect, kill_quick, kill_immed;
+
+public:
+ NSSetKill(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandnssetkill(this)
+ , commandnssasetkill(this)
+ , killprotect(this, "KILLPROTECT")
+ , kill_quick(this, "KILL_QUICK")
+ , kill_immed(this, "KILL_IMMED")
+ {
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
+ {
+ if (!show_hidden)
+ return;
+
+ if (kill_immed.HasExt(na->nc))
+ info.AddOption(_("Immediate protection"));
+ else if (kill_quick.HasExt(na->nc))
+ info.AddOption(_("Quick protection"));
+ else if (killprotect.HasExt(na->nc))
+ info.AddOption(_("Protection"));
+ }
+};
+
+MODULE_INIT(NSSetKill)
diff --git a/modules/nickserv/ns_set_language.cpp b/modules/nickserv/ns_set_language.cpp
new file mode 100644
index 000000000..1cffc3aed
--- /dev/null
+++ b/modules/nickserv/ns_set_language.cpp
@@ -0,0 +1,160 @@
+/* NickServ core functions
+ *
+ * (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"
+
+class CommandNSSetLanguage
+ : public Command
+{
+protected:
+ Anope::map<Anope::string> &languages;
+
+public:
+ CommandNSSetLanguage(Module *creator, Anope::map<Anope::string> &langs, const Anope::string &sname = "nickserv/set/language", size_t min = 1)
+ : Command(creator, sname, min, min + 1)
+ , languages(langs)
+ {
+ this->SetDesc(_("Set the language services will use when messaging you"));
+ this->SetSyntax(_("\037language\037"));
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ auto lang = languages.end();
+ for (auto it = languages.begin(); it != languages.end(); ++it)
+ {
+ auto &[langcode, langname] = *it;
+ if (langcode.find_ci(param) != 0)
+ continue; // Language does not match.
+
+ if (lang != languages.end())
+ {
+ source.Reply(_("Multiple languages matched \002%s\002. Please be more specific."), param.c_str());
+ return;
+ }
+
+ lang = it;
+ }
+
+ if (lang == languages.end())
+ {
+ this->OnSyntaxError(source, "");
+ return;
+ }
+
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << lang->first;
+
+ nc->language = lang->first;
+ if (source.GetAccount() == nc)
+ source.Reply(_("Language changed to \002%s\002."), lang->second.c_str());
+ else
+ source.Reply(_("Language for \002%s\002 changed to \002%s\002."), nc->display.c_str(), lang->second.c_str());
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &param) override
+ {
+ this->Run(source, source.nc->display, param[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Changes the language services uses when sending messages to\n"
+ "you (for example, when responding to a command you send).\n"
+ "\037language\037 should be chosen from the following list of\n"
+ "supported languages:"));
+
+ for (const auto &[langcode, langname] : languages)
+ source.Reply(" %s (%s)", langcode.c_str(), langname.c_str());
+
+ return true;
+ }
+};
+
+class CommandNSSASetLanguage final
+ : public CommandNSSetLanguage
+{
+public:
+ CommandNSSASetLanguage(Module *creator, Anope::map<Anope::string> &langs)
+ : CommandNSSetLanguage(creator, langs, "nickserv/saset/language", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 \037language\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Changes the language services uses when sending messages to\n"
+ "the given user (for example, when responding to a command they send).\n"
+ "\037language\037 should be chosen from the following list of\n"
+ "supported languages:"));
+
+ for (const auto &[langcode, langname] : languages)
+ source.Reply(" %s (%s)", langcode.c_str(), langname.c_str());
+
+ return true;
+ }
+};
+
+class NSSetLanguage final
+ : public Module
+{
+private:
+ CommandNSSetLanguage commandnssetlanguage;
+ CommandNSSASetLanguage commandnssasetlanguage;
+ Anope::map<Anope::string> languages;
+
+public:
+ NSSetLanguage(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandnssetlanguage(this, languages)
+ , commandnssasetlanguage(this, languages)
+ {
+#ifndef HAVE_LOCALIZATION
+ throw ModuleException("Anope was not built with localization support");
+#endif
+
+ // Build a list of languages. This only needs to happen once as we
+ // only load the languages on boot.
+ languages.emplace("en_US.UTF-8", "English");
+ for (const auto &language : Language::Languages)
+ languages.emplace(language, Language::Translate(language.c_str(), _("English")));
+ }
+};
+
+MODULE_INIT(NSSetLanguage)
diff --git a/modules/nickserv/ns_set_message.cpp b/modules/nickserv/ns_set_message.cpp
new file mode 100644
index 000000000..99f5d6782
--- /dev/null
+++ b/modules/nickserv/ns_set_message.cpp
@@ -0,0 +1,137 @@
+/* NickServ core functions
+ *
+ * (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"
+
+class CommandNSSetMessage
+ : public Command
+{
+public:
+ CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1)
+ : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Change the communication method of services"));
+ this->SetSyntax("{ON | OFF}");
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ if (Anope::ReadOnly)
+ {
+ source.Reply(READ_ONLY_MODE);
+ return;
+ }
+
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (param.equals_ci("ON"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
+ nc->Extend<bool>("MSG");
+ source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
+ nc->Shrink<bool>("MSG");
+ source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "MSG");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ Anope::string cmd = source.command;
+ size_t i = cmd.find_last_of(' ');
+ if (i != Anope::string::npos)
+ cmd = cmd.substr(i + 1);
+
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Allows you to choose the way services are communicating with\n"
+ "you. With \002%s\002 set, services will use messages, else they'll\n"
+ "use notices."), cmd.upper().c_str());
+ return true;
+ }
+};
+
+class CommandNSSASetMessage final
+ : public CommandNSSetMessage
+{
+public:
+ CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Allows you to choose the way services are communicating with\n"
+ "the given user. With \002MSG\002 set, services will use messages,\n"
+ "else they'll use notices."));
+ return true;
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+};
+
+
+class NSSetMessage final
+ : public Module
+{
+private:
+ CommandNSSetMessage commandnssetmessage;
+ CommandNSSASetMessage commandnssasetmessage;
+ SerializableExtensibleItem<bool> message;
+
+public:
+ NSSetMessage(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, VENDOR)
+ , commandnssetmessage(this)
+ , commandnssasetmessage(this)
+ , message(this, "MSG")
+ {
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
+ {
+ if (!show_hidden)
+ return;
+ if (message.HasExt(na->nc))
+ info.AddOption(_("Message mode"));
+ }
+};
+
+MODULE_INIT(NSSetMessage)
diff --git a/modules/commands/ns_set_misc.cpp b/modules/nickserv/ns_set_misc.cpp
index 967de9f8b..173f1f2da 100644
--- a/modules/commands/ns_set_misc.cpp
+++ b/modules/nickserv/ns_set_misc.cpp
@@ -21,7 +21,7 @@ static Anope::map<ExtensibleItem<NSMiscData> *> items;
static ExtensibleItem<NSMiscData> *GetItem(const Anope::string &name)
{
- ExtensibleItem<NSMiscData>* &it = items[name];
+ ExtensibleItem<NSMiscData> *&it = items[name];
if (!it)
try
{
@@ -31,7 +31,9 @@ static ExtensibleItem<NSMiscData> *GetItem(const Anope::string &name)
return it;
}
-struct NSMiscData : MiscData, Serializable
+struct NSMiscData final
+ : MiscData
+ , Serializable
{
NSMiscData(Extensible *) : Serializable("NSMiscData") { }
@@ -42,14 +44,14 @@ struct NSMiscData : MiscData, Serializable
data = d;
}
- void Serialize(Serialize::Data &sdata) const anope_override
+ void Serialize(Serialize::Data &sdata) const override
{
- sdata["nc"] << this->object;
- sdata["name"] << this->name;
- sdata["data"] << this->data;
+ sdata.Store("nc", this->object);
+ sdata.Store("name", this->name);
+ sdata.Store("data", this->data);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string snc, sname, sdata;
@@ -88,9 +90,10 @@ static Anope::string GetAttribute(const Anope::string &command)
return command;
}
-class CommandNSSetMisc : public Command
+class CommandNSSetMisc
+ : public Command
{
- public:
+public:
CommandNSSetMisc(Module *creator, const Anope::string &cname = "nickserv/set/misc", size_t min = 0) : Command(creator, cname, min, min + 1)
{
this->SetSyntax(_("[\037parameter\037]"));
@@ -135,12 +138,12 @@ class CommandNSSetMisc : public Command
}
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, source.nc->display, !params.empty() ? params[0] : "");
}
- void OnServHelp(CommandSource &source) anope_override
+ void OnServHelp(CommandSource &source) override
{
if (descriptions.count(source.command))
{
@@ -149,7 +152,7 @@ class CommandNSSetMisc : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (descriptions.count(source.command))
{
@@ -161,41 +164,43 @@ class CommandNSSetMisc : public Command
}
};
-class CommandNSSASetMisc : public CommandNSSetMisc
+class CommandNSSASetMisc final
+ : public CommandNSSetMisc
{
- public:
+public:
CommandNSSASetMisc(Module *creator) : CommandNSSetMisc(creator, "nickserv/saset/misc", 1)
{
this->ClearSyntax();
this->SetSyntax(_("\037nickname\037 [\037parameter\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
this->Run(source, params[0], params.size() > 1 ? params[1] : "");
}
};
-class NSSetMisc : public Module
+class NSSetMisc final
+ : public Module
{
CommandNSSetMisc commandnssetmisc;
CommandNSSASetMisc commandnssasetmisc;
Serialize::Type nsmiscdata_type;
- public:
+public:
NSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnssetmisc(this), commandnssasetmisc(this), nsmiscdata_type("NSMiscData", NSMiscData::Unserialize)
{
me = this;
}
- ~NSSetMisc()
+ ~NSSetMisc() override
{
- for (Anope::map<ExtensibleItem<NSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it)
- delete it->second;
+ for (const auto &[_, data] : items)
+ delete data;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
descriptions.clear();
@@ -218,11 +223,10 @@ class NSSetMisc : public Module
}
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool) override
{
- for (Anope::map<ExtensibleItem<NSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it)
+ for (const auto &[_, e] : items)
{
- ExtensibleItem<NSMiscData> *e = it->second;
NSMiscData *data = e->Get(na->nc);
if (data != NULL)
diff --git a/modules/commands/ns_suspend.cpp b/modules/nickserv/ns_suspend.cpp
index 432c72f8a..6cdce688a 100644
--- a/modules/commands/ns_suspend.cpp
+++ b/modules/nickserv/ns_suspend.cpp
@@ -14,20 +14,22 @@
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
-struct NSSuspendInfo : SuspendInfo, Serializable
+struct NSSuspendInfo final
+ : SuspendInfo
+ , Serializable
{
NSSuspendInfo(Extensible *) : Serializable("NSSuspendInfo") { }
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["nick"] << what;
- data["by"] << by;
- data["reason"] << reason;
- data["time"] << when;
- data["expires"] << expires;
+ data.Store("nick", what);
+ data.Store("by", by);
+ data.Store("reason", reason);
+ data.Store("time", when);
+ data.Store("expires", expires);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string snick;
data["nick"] >> snick;
@@ -52,16 +54,17 @@ struct NSSuspendInfo : SuspendInfo, Serializable
}
};
-class CommandNSSuspend : public Command
+class CommandNSSuspend final
+ : public Command
{
- public:
+public:
CommandNSSuspend(Module *creator) : Command(creator, "nickserv/suspend", 2, 3)
{
this->SetDesc(_("Suspend a given nick"));
this->SetSyntax(_("\037nickname\037 [+\037expiry\037] [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = params[0];
@@ -116,10 +119,8 @@ class CommandNSSuspend : public Command
si->when = Anope::CurTime;
si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0;
- for (unsigned i = 0; i < nc->aliases->size(); ++i)
+ for (auto *na2 : *nc->aliases)
{
- NickAlias *na2 = nc->aliases->at(i);
-
if (na2 && *na2->nc == *na->nc)
{
na2->last_quit = reason;
@@ -142,7 +143,7 @@ class CommandNSSuspend : public Command
FOREACH_MOD(OnNickSuspend, (na));
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -154,16 +155,17 @@ class CommandNSSuspend : public Command
}
};
-class CommandNSUnSuspend : public Command
+class CommandNSUnSuspend final
+ : public Command
{
- public:
+public:
CommandNSUnSuspend(Module *creator) : Command(creator, "nickserv/unsuspend", 1, 1)
{
this->SetDesc(_("Unsuspend a given nick"));
this->SetSyntax(_("\037nickname\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = params[0];
@@ -194,7 +196,7 @@ class CommandNSUnSuspend : public Command
FOREACH_MOD(OnNickUnsuspended, (na));
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -203,7 +205,8 @@ class CommandNSUnSuspend : public Command
}
};
-class NSSuspend : public Module
+class NSSuspend final
+ : public Module
{
CommandNSSuspend commandnssuspend;
CommandNSUnSuspend commandnsunsuspend;
@@ -211,7 +214,7 @@ class NSSuspend : public Module
Serialize::Type suspend_type;
std::vector<Anope::string> show;
- struct trim
+ struct trim final
{
Anope::string operator()(Anope::string s) const
{
@@ -230,21 +233,21 @@ class NSSuspend : public Module
Log(LOG_NORMAL, "nickserv/expire", Config->GetClient("NickServ")) << "Expiring suspend for " << na->nick;
}
- public:
+public:
NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnssuspend(this), commandnsunsuspend(this), suspend(this, "NS_SUSPENDED"),
suspend_type("NSSuspendInfo", NSSuspendInfo::Unserialize)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Anope::string s = conf->GetModule(this)->Get<Anope::string>("show");
commasepstream(s).GetTokens(show);
std::transform(show.begin(), show.end(), show.begin(), trim());
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
{
NSSuspendInfo *s = suspend.Get(na->nc);
if (!s)
@@ -262,7 +265,7 @@ class NSSuspend : public Module
info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount());
}
- void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+ void OnPreNickExpire(NickAlias *na, bool &expire) override
{
NSSuspendInfo *s = suspend.Get(na->nc);
if (!s)
@@ -277,7 +280,7 @@ class NSSuspend : public Module
}
}
- EventReturn OnNickValidate(User *u, NickAlias *na) anope_override
+ EventReturn OnNickValidate(User *u, NickAlias *na) override
{
NSSuspendInfo *s = suspend.Get(na->nc);
if (!s)
diff --git a/modules/commands/ns_update.cpp b/modules/nickserv/ns_update.cpp
index 0ebaa6468..0ce6a5c95 100644
--- a/modules/commands/ns_update.cpp
+++ b/modules/nickserv/ns_update.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandNSUpdate : public Command
+class CommandNSUpdate final
+ : public Command
{
- public:
+public:
CommandNSUpdate(Module *creator) : Command(creator, "nickserv/update", 0, 0)
{
this->SetDesc(_("Updates your current status, i.e. it checks for new memos"));
this->RequireUser(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
User *u = source.GetUser();
NickAlias *na = NickAlias::Find(u->nick);
@@ -36,7 +37,7 @@ class CommandNSUpdate : public Command
source.Reply(_("Status updated (memos, vhost, chmodes, flags)."));
}
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -47,11 +48,12 @@ class CommandNSUpdate : public Command
}
};
-class NSUpdate : public Module
+class NSUpdate final
+ : public Module
{
CommandNSUpdate commandnsupdate;
- public:
+public:
NSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsupdate(this)
{
diff --git a/modules/pseudoclients/operserv.cpp b/modules/operserv/operserv.cpp
index 49c4249fc..a05159179 100644
--- a/modules/pseudoclients/operserv.cpp
+++ b/modules/operserv/operserv.cpp
@@ -11,32 +11,33 @@
#include "module.h"
-class SGLineManager : public XLineManager
+class SGLineManager final
+ : public XLineManager
{
- public:
+public:
SGLineManager(Module *creator) : XLineManager(creator, "xlinemanager/sgline", 'G') { }
- void OnMatch(User *u, XLine *x) anope_override
+ void OnMatch(User *u, XLine *x) override
{
this->Send(u, x);
}
- void OnExpire(const XLine *x) anope_override
+ void OnExpire(const XLine *x) override
{
Log(Config->GetClient("OperServ"), "expire/akill") << "AKILL on \002" << x->mask << "\002 has expired";
}
- void Send(User *u, XLine *x) anope_override
+ void Send(User *u, XLine *x) override
{
IRCD->SendAkill(u, x);
}
- void SendDel(XLine *x) anope_override
+ void SendDel(XLine *x) override
{
IRCD->SendAkillDel(x);
}
- bool Check(User *u, const XLine *x) anope_override
+ bool Check(User *u, const XLine *x) override
{
if (x->regex)
{
@@ -63,24 +64,25 @@ class SGLineManager : public XLineManager
}
};
-class SQLineManager : public XLineManager
+class SQLineManager final
+ : public XLineManager
{
ServiceReference<NickServService> nickserv;
- public:
+public:
SQLineManager(Module *creator) : XLineManager(creator, "xlinemanager/sqline", 'Q'), nickserv("NickServService", "NickServ") { }
- void OnMatch(User *u, XLine *x) anope_override
+ void OnMatch(User *u, XLine *x) override
{
this->Send(u, x);
}
- void OnExpire(const XLine *x) anope_override
+ void OnExpire(const XLine *x) override
{
Log(Config->GetClient("OperServ"), "expire/sqline") << "SQLINE on \002" << x->mask << "\002 has expired";
}
- void Send(User *u, XLine *x) anope_override
+ void Send(User *u, XLine *x) override
{
if (!IRCD->CanSQLine)
{
@@ -105,7 +107,7 @@ class SQLineManager : public XLineManager
}
}
- void SendDel(XLine *x) anope_override
+ void SendDel(XLine *x) override
{
if (!IRCD->CanSQLine || x->IsRegex())
;
@@ -113,7 +115,7 @@ class SQLineManager : public XLineManager
IRCD->SendSQLineDel(x);
}
- bool Check(User *u, const XLine *x) anope_override
+ bool Check(User *u, const XLine *x) override
{
if (x->regex)
return x->regex->Matches(u->nick);
@@ -122,10 +124,8 @@ class SQLineManager : public XLineManager
XLine *CheckChannel(Channel *c)
{
- for (std::vector<XLine *>::const_iterator it = this->GetList().begin(), it_end = this->GetList().end(); it != it_end; ++it)
+ for (auto *x : this->GetList())
{
- XLine *x = *it;
-
if (!Anope::NoExpire && x->expires && x->expires < Anope::CurTime)
continue; // Skip expired lines.
@@ -147,22 +147,23 @@ class SQLineManager : public XLineManager
}
};
-class SNLineManager : public XLineManager
+class SNLineManager final
+ : public XLineManager
{
- public:
+public:
SNLineManager(Module *creator) : XLineManager(creator, "xlinemanager/snline", 'N') { }
- void OnMatch(User *u, XLine *x) anope_override
+ void OnMatch(User *u, XLine *x) override
{
this->Send(u, x);
}
- void OnExpire(const XLine *x) anope_override
+ void OnExpire(const XLine *x) override
{
Log(Config->GetClient("OperServ"), "expire/snline") << "SNLINE on \002" << x->mask << "\002 has expired";
}
- void Send(User *u, XLine *x) anope_override
+ void Send(User *u, XLine *x) override
{
if (IRCD->CanSNLine && !x->IsRegex())
IRCD->SendSGLine(u, x);
@@ -171,13 +172,13 @@ class SNLineManager : public XLineManager
u->Kill(Config->GetClient("OperServ"), "SNLined: " + x->reason);
}
- void SendDel(XLine *x) anope_override
+ void SendDel(XLine *x) override
{
if (IRCD->CanSNLine && !x->IsRegex())
IRCD->SendSGLineDel(x);
}
- bool Check(User *u, const XLine *x) anope_override
+ bool Check(User *u, const XLine *x) override
{
if (x->regex)
return x->regex->Matches(u->realname);
@@ -185,14 +186,15 @@ class SNLineManager : public XLineManager
}
};
-class OperServCore : public Module
+class OperServCore final
+ : public Module
{
Reference<BotInfo> OperServ;
SGLineManager sglines;
SQLineManager sqlines;
SNLineManager snlines;
- public:
+public:
OperServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
sglines(this), sqlines(this), snlines(this)
{
@@ -203,7 +205,7 @@ class OperServCore : public Module
XLineManager::RegisterXLineManager(&snlines);
}
- ~OperServCore()
+ ~OperServCore() override
{
this->sglines.Clear();
this->sqlines.Clear();
@@ -214,7 +216,7 @@ class OperServCore : public Module
XLineManager::UnregisterXLineManager(&snlines);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
const Anope::string &osnick = conf->GetModule(this)->Get<const Anope::string>("client");
@@ -228,7 +230,7 @@ class OperServCore : public Module
OperServ = bi;
}
- EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override
+ EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override
{
if (bi == OperServ && !u->HasMode("OPER") && Config->GetModule(this)->Get<bool>("opersonly"))
{
@@ -240,37 +242,37 @@ class OperServCore : public Module
return EVENT_CONTINUE;
}
- void OnServerQuit(Server *server) anope_override
+ void OnServerQuit(Server *server) override
{
if (server->IsJuped())
Log(server, "squit", OperServ) << "Received SQUIT for juped server " << server->GetName();
}
- void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override
+ void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
{
if (mname == "OPER")
Log(u, "oper", OperServ) << "is now an IRC operator.";
}
- void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) anope_override
+ void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override
{
if (mname == "OPER")
Log(u, "oper", OperServ) << "is no longer an IRC operator";
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (!u->Quitting() && !exempt)
XLineManager::CheckAll(u);
}
- void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
+ void OnUserNickChange(User *u, const Anope::string &oldnick) override
{
if (!u->HasMode("OPER"))
this->sqlines.CheckAllXLines(u);
}
- EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
+ EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
XLine *x = this->sqlines.CheckChannel(c);
if (x)
@@ -283,7 +285,7 @@ class OperServCore : public Module
return EVENT_CONTINUE;
}
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *OperServ)
return EVENT_CONTINUE;
@@ -291,7 +293,7 @@ class OperServCore : public Module
return EVENT_CONTINUE;
}
- void OnLog(Log *l) anope_override
+ void OnLog(Log *l) override
{
if (l->type == LOG_SERVER)
l->bi = OperServ;
diff --git a/modules/commands/os_akill.cpp b/modules/operserv/os_akill.cpp
index cb18dd46b..e904713cf 100644
--- a/modules/commands/os_akill.cpp
+++ b/modules/operserv/os_akill.cpp
@@ -13,17 +13,18 @@
static ServiceReference<XLineManager> akills("XLineManager", "xlinemanager/sgline");
-class AkillDelCallback : public NumberList
+class AkillDelCallback final
+ : public NumberList
{
CommandSource &source;
- unsigned deleted;
+ unsigned deleted = 0;
Command *cmd;
- public:
- AkillDelCallback(CommandSource &_source, const Anope::string &numlist, Command *c) : NumberList(numlist, true), source(_source), deleted(0), cmd(c)
+public:
+ AkillDelCallback(CommandSource &_source, const Anope::string &numlist, Command *c) : NumberList(numlist, true), source(_source), cmd(c)
{
}
- ~AkillDelCallback()
+ ~AkillDelCallback() override
{
if (!deleted)
source.Reply(_("No matching entries on the AKILL list."));
@@ -33,7 +34,7 @@ class AkillDelCallback : public NumberList
source.Reply(_("Deleted %d entries from the AKILL list."), deleted);
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number)
return;
@@ -55,9 +56,10 @@ class AkillDelCallback : public NumberList
}
};
-class CommandOSAKill : public Command
+class CommandOSAKill final
+ : public Command
{
- private:
+private:
void DoAdd(CommandSource &source, const std::vector<Anope::string> &params)
{
Anope::string expiry, mask;
@@ -167,13 +169,13 @@ class CommandOSAKill : public Command
return;
}
- XLine *x = new XLine(mask, source.GetNick(), expires, reason);
+ auto *x = new XLine(mask, source.GetNick(), expires, reason);
if (Config->GetModule("operserv")->Get<bool>("akillids"))
x->id = XLineManager::GenerateUID();
unsigned int affected = 0;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (akills->Check(it->second, x))
+ for (const auto &[_, user] : UserListByNick)
+ if (akills->Check(user, x))
++affected;
float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0;
@@ -186,7 +188,10 @@ class CommandOSAKill : public Command
}
if (!akills->CanAdd(source, mask, expires, reason))
+ {
+ delete x;
return;
+ }
EventReturn MOD_RESULT;
FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, akills));
@@ -262,16 +267,17 @@ class CommandOSAKill : public Command
if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class ListCallback : public NumberList
+ class ListCallback final
+ : public NumberList
{
CommandSource &source;
ListFormatter &list;
- public:
+ public:
ListCallback(CommandSource &_source, ListFormatter &_list, const Anope::string &numstr) : NumberList(numstr, false), source(_source), list(_list)
{
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number)
return;
@@ -282,7 +288,7 @@ class CommandOSAKill : public Command
return;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(number);
+ entry["Number"] = Anope::ToString(number);
entry["Mask"] = x->mask;
entry["Creator"] = x->by;
entry["Created"] = Anope::strftime(x->created, NULL, true);
@@ -304,7 +310,7 @@ class CommandOSAKill : public Command
if (mask.empty() || mask.equals_ci(x->mask) || mask == x->id || Anope::Match(x->mask, mask, false, true))
{
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Mask"] = x->mask;
entry["Creator"] = x->by;
entry["Created"] = Anope::strftime(x->created, NULL, true);
@@ -325,8 +331,8 @@ class CommandOSAKill : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of AKILL list."));
}
@@ -379,7 +385,7 @@ class CommandOSAKill : public Command
if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
}
- public:
+public:
CommandOSAKill(Module *creator) : Command(creator, "operserv/akill", 1, 2)
{
this->SetDesc(_("Manipulate the AKILL list"));
@@ -390,7 +396,7 @@ class CommandOSAKill : public Command
this->SetSyntax("CLEAR");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
@@ -413,12 +419,12 @@ class CommandOSAKill : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows Services Operators to manipulate the AKILL list. If\n"
- "a user matching an AKILL mask attempts to connect, Services\n"
+ "a user matching an AKILL mask attempts to connect, services\n"
"will issue a KILL for that user and, on supported server\n"
"types, will instruct all servers to add a ban for the mask\n"
"which the user matched.\n"
@@ -468,11 +474,12 @@ class CommandOSAKill : public Command
}
};
-class OSAKill : public Module
+class OSAKill final
+ : public Module
{
CommandOSAKill commandosakill;
- public:
+public:
OSAKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosakill(this)
{
diff --git a/modules/commands/os_chankill.cpp b/modules/operserv/os_chankill.cpp
index 1fc034256..3ac583cb7 100644
--- a/modules/commands/os_chankill.cpp
+++ b/modules/operserv/os_chankill.cpp
@@ -13,16 +13,17 @@
static ServiceReference<XLineManager> akills("XLineManager", "xlinemanager/sgline");
-class CommandOSChanKill : public Command
+class CommandOSChanKill final
+ : public Command
{
- public:
+public:
CommandOSChanKill(Module *creator) : Command(creator, "operserv/chankill", 2, 3)
{
this->SetDesc(_("AKILL all users on a specific channel"));
this->SetSyntax(_("[+\037expiry\037] \037channel\037 \037reason\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!akills)
return;
@@ -69,10 +70,8 @@ class CommandOSChanKill : public Command
if ((c = Channel::Find(channel)))
{
- for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : c->users)
{
- ChanUserContainer *uc = it->second;
-
if (uc->user->server == Me || uc->user->HasMode("OPER"))
continue;
@@ -80,7 +79,7 @@ class CommandOSChanKill : public Command
if (akills->HasEntry(akillmask))
continue;
- XLine *x = new XLine(akillmask, source.GetNick(), expires, realreason, XLineManager::GenerateUID());
+ auto *x = new XLine(akillmask, source.GetNick(), expires, realreason, XLineManager::GenerateUID());
akills->AddXLine(x);
akills->OnMatch(uc->user, x);
}
@@ -93,7 +92,7 @@ class CommandOSChanKill : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -104,11 +103,12 @@ class CommandOSChanKill : public Command
}
};
-class OSChanKill : public Module
+class OSChanKill final
+ : public Module
{
CommandOSChanKill commandoschankill;
- public:
+public:
OSChanKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandoschankill(this)
{
diff --git a/modules/commands/os_config.cpp b/modules/operserv/os_config.cpp
index acd6c7a94..22a46efa7 100644
--- a/modules/commands/os_config.cpp
+++ b/modules/operserv/os_config.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSConfig : public Command
+class CommandOSConfig final
+ : public Command
{
- public:
+public:
CommandOSConfig(Module *creator) : Command(creator, "operserv/config", 1, 4)
{
this->SetDesc(_("View and change configuration file settings"));
this->SetSyntax(_("{\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &what = params[0];
@@ -57,19 +58,16 @@ class CommandOSConfig : public Command
for (unsigned i = 0; !show_blocks[i].empty(); ++i)
{
Configuration::Block *block = Config->GetBlock(show_blocks[i]);
- const Configuration::Block::item_map *items = block->GetItems();
-
- if (!items)
- continue;
+ const Configuration::Block::item_map &items = block->GetItems();
ListFormatter lflist(source.GetAccount());
lflist.AddColumn(_("Name")).AddColumn(_("Value"));
- for (Configuration::Block::item_map::const_iterator it = items->begin(), it_end = items->end(); it != it_end; ++it)
+ for (const auto &[name, value] : items)
{
ListFormatter::ListEntry entry;
- entry["Name"] = it->first;
- entry["Value"] = it->second;
+ entry["Name"] = name;
+ entry["Value"] = value;
lflist.AddEntry(entry);
}
@@ -78,8 +76,8 @@ class CommandOSConfig : public Command
source.Reply(_("%s settings:"), block->GetName().c_str());
- for (unsigned j = 0; j < replies.size(); ++j)
- source.Reply(replies[j]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(" ");
}
@@ -90,18 +88,18 @@ class CommandOSConfig : public Command
for (int i = 0; i < Config->CountBlock("module"); ++i)
{
Configuration::Block *block = Config->GetBlock("module", i);
- const Configuration::Block::item_map *items = block->GetItems();
+ const Configuration::Block::item_map &items = block->GetItems();
- if (!items || items->size() <= 1)
+ if (items.size() <= 1)
continue;
ListFormatter::ListEntry entry;
entry["Module Name"] = block->Get<Anope::string>("name");
- for (Configuration::Block::item_map::const_iterator it = items->begin(), it_end = items->end(); it != it_end; ++it)
+ for (const auto &[name, value] : items)
{
- entry["Name"] = it->first;
- entry["Value"] = it->second;
+ entry["Name"] = name;
+ entry["Value"] = value;
lflist.AddEntry(entry);
}
}
@@ -111,8 +109,8 @@ class CommandOSConfig : public Command
source.Reply(_("Module settings:"));
- for (unsigned j = 0; j < replies.size(); ++j)
- source.Reply(replies[j]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of configuration."));
}
@@ -120,7 +118,7 @@ class CommandOSConfig : public Command
this->OnSyntaxError(source, what);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -130,16 +128,17 @@ class CommandOSConfig : public Command
"restarted, or the configuration is reloaded.\n"
" \n"
"Example:\n"
- " \002MODIFY nickserv forcemail no\002"));
+ " \002MODIFY nickserv regdelay 15m\002"));
return true;
}
};
-class OSConfig : public Module
+class OSConfig final
+ : public Module
{
CommandOSConfig commandosconfig;
- public:
+public:
OSConfig(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosconfig(this)
{
diff --git a/modules/commands/os_defcon.cpp b/modules/operserv/os_defcon.cpp
index 7853e07b7..65a6555a6 100644
--- a/modules/commands/os_defcon.cpp
+++ b/modules/operserv/os_defcon.cpp
@@ -28,7 +28,7 @@ enum DefconLevel
bool DefConModesSet = false;
-struct DefconConfig
+struct DefconConfig final
{
std::vector<std::bitset<32> > DefCon;
std::set<Anope::string> DefConModesOn, DefConModesOff;
@@ -72,7 +72,7 @@ struct DefconConfig
bool SetDefConParam(const Anope::string &name, const Anope::string &buf)
{
- return DefConModesOnParams.insert(std::make_pair(name, buf)).second;
+ return DefConModesOnParams.emplace(name, buf).second;
}
void UnsetDefConParam(const Anope::string &name)
@@ -105,22 +105,25 @@ static ServiceReference<GlobalService> GlobalService("GlobalService", "Global");
static Timer *timeout;
-class DefConTimeout : public Timer
+class DefConTimeout final
+ : public Timer
{
int level;
- public:
- DefConTimeout(Module *mod, int newlevel) : Timer(mod, DConfig.timeout), level(newlevel)
+public:
+ DefConTimeout(Module *mod, int newlevel)
+ : Timer(mod, DConfig.timeout)
+ , level(newlevel)
{
timeout = this;
}
- ~DefConTimeout()
+ ~DefConTimeout() override
{
timeout = NULL;
}
- void Tick(time_t) anope_override
+ void Tick() override
{
if (DConfig.defaultlevel != level)
{
@@ -131,12 +134,12 @@ class DefConTimeout : public Timer
if (DConfig.globalondefcon)
{
if (!DConfig.offmessage.empty())
- GlobalService->SendGlobal(NULL, "", DConfig.offmessage);
+ GlobalService->SendSingle(DConfig.offmessage);
else
- GlobalService->SendGlobal(NULL, "", Anope::printf(Language::Translate(_("The Defcon level is now at: \002%d\002")), DConfig.defaultlevel));
+ GlobalService->SendSingle(Anope::printf(Language::Translate(_("The Defcon level is now at: \002%d\002")), DConfig.defaultlevel));
if (!DConfig.message.empty())
- GlobalService->SendGlobal(NULL, "", DConfig.message);
+ GlobalService->SendSingle(DConfig.message);
}
runDefCon();
@@ -144,9 +147,10 @@ class DefConTimeout : public Timer
}
};
-class CommandOSDefcon : public Command
+class CommandOSDefcon final
+ : public Command
{
- void SendLevels(CommandSource &source)
+ static void SendLevels(CommandSource &source)
{
if (DConfig.Check(DEFCON_NO_NEW_CHANNELS))
source.Reply(_("* No new channel registrations"));
@@ -170,14 +174,14 @@ class CommandOSDefcon : public Command
source.Reply(_("* No new memos sent"));
}
- public:
+public:
CommandOSDefcon(Module *creator) : Command(creator, "operserv/defcon", 1, 1)
{
this->SetDesc(_("Manipulate the DefCon system"));
this->SetSyntax(_("[\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &lvl = params[0];
@@ -188,13 +192,7 @@ class CommandOSDefcon : public Command
return;
}
- int newLevel = 0;
- try
- {
- newLevel = convertTo<int>(lvl);
- }
- catch (const ConvertException &) { }
-
+ auto newLevel = Anope::Convert<int>(lvl, 0);
if (newLevel < 1 || newLevel > 5)
{
this->OnSyntaxError(source, "");
@@ -219,12 +217,12 @@ class CommandOSDefcon : public Command
if (DConfig.globalondefcon)
{
if (DConfig.defaultlevel == 5 && !DConfig.offmessage.empty())
- GlobalService->SendGlobal(NULL, "", DConfig.offmessage);
+ GlobalService->SendSingle(DConfig.offmessage);
else if (DConfig.defaultlevel != 5)
{
- GlobalService->SendGlobal(NULL, "", Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel));
+ GlobalService->SendSingle(Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel));
if (!DConfig.message.empty())
- GlobalService->SendGlobal(NULL, "", DConfig.message);
+ GlobalService->SendSingle(DConfig.message);
}
}
@@ -233,7 +231,7 @@ class CommandOSDefcon : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -244,7 +242,8 @@ class CommandOSDefcon : public Command
}
};
-class OSDefcon : public Module
+class OSDefcon final
+ : public Module
{
ServiceReference<SessionService> session_service;
ServiceReference<XLineManager> akills;
@@ -253,7 +252,6 @@ class OSDefcon : public Module
void ParseModeString()
{
int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */
- unsigned char mode;
ChannelMode *cm;
ChannelModeParam *cmp;
Anope::string modes, param;
@@ -265,10 +263,8 @@ class OSDefcon : public Module
ss.GetToken(modes);
/* Loop while there are modes to set */
- for (unsigned i = 0, end = modes.length(); i < end; ++i)
+ for (auto mode : modes)
{
- mode = modes[i];
-
switch (mode)
{
case '+':
@@ -329,13 +325,13 @@ class OSDefcon : public Module
}
}
- public:
+public:
OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), session_service("SessionService", "session"), akills("XLineManager", "xlinemanager/sgline"), commandosdefcon(this)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
DefconConfig dconfig;
@@ -406,7 +402,7 @@ class OSDefcon : public Module
this->ParseModeString();
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &param) override
{
if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOff.count(mode->name) && source.GetUser() && !source.GetBot())
{
@@ -418,7 +414,7 @@ class OSDefcon : public Module
return EVENT_CONTINUE;
}
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &) anope_override
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &) override
{
if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOn.count(mode->name) && source.GetUser() && !source.GetBot())
{
@@ -436,7 +432,7 @@ class OSDefcon : public Module
return EVENT_CONTINUE;
}
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
{
if (DConfig.Check(DEFCON_OPER_ONLY) && !source.IsOper())
{
@@ -483,7 +479,7 @@ class OSDefcon : public Module
return EVENT_CONTINUE;
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (exempt || u->Quitting() || !u->server->IsSynced() || u->server->IsULined())
return;
@@ -535,16 +531,16 @@ class OSDefcon : public Module
}
}
- void OnChannelModeAdd(ChannelMode *cm) anope_override
+ void OnChannelModeAdd(ChannelMode *cm) override
{
if (DConfig.chanmodes.find(cm->mchar) != Anope::string::npos)
this->ParseModeString();
}
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
if (DConfig.Check(DEFCON_FORCE_CHAN_MODES))
- c->SetModes(Config->GetClient("OperServ"), false, "%s", DConfig.chanmodes.c_str());
+ c->SetModes(Config->GetClient("OperServ"), false, DConfig.chanmodes);
}
};
@@ -559,8 +555,8 @@ static void runDefCon()
{
Log(OperServ, "operserv/defcon") << "DEFCON: setting " << DConfig.chanmodes << " on all channels";
DefConModesSet = true;
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
- it->second->SetModes(OperServ, false, "%s", DConfig.chanmodes.c_str());
+ for (const auto &[_, chan] : ChannelList)
+ chan->SetModes(OperServ, false, DConfig.chanmodes);
}
}
}
@@ -575,8 +571,8 @@ static void runDefCon()
if (!newmodes.empty())
{
Log(OperServ, "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels";
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
- it->second->SetModes(OperServ, true, "%s", newmodes.c_str());
+ for (const auto &[_, chan] : ChannelList)
+ chan->SetModes(OperServ, true, newmodes);
}
}
}
@@ -588,14 +584,14 @@ static Anope::string defconReverseModes(const Anope::string &modes)
if (modes.empty())
return "";
Anope::string newmodes;
- for (unsigned i = 0, end = modes.length(); i < end; ++i)
+ for (auto mode : modes)
{
- if (modes[i] == '+')
+ if (mode == '+')
newmodes += '-';
- else if (modes[i] == '-')
+ else if (mode == '-')
newmodes += '+';
else
- newmodes += modes[i];
+ newmodes += mode;
}
return newmodes;
}
diff --git a/modules/commands/os_dns.cpp b/modules/operserv/os_dns.cpp
index efb11a90d..195cd0f25 100644
--- a/modules/commands/os_dns.cpp
+++ b/modules/operserv/os_dns.cpp
@@ -19,7 +19,8 @@ static Serialize::Checker<std::vector<DNSServer *> > dns_servers("DNSServer");
static std::map<Anope::string, std::list<time_t> > server_quit_times;
-struct DNSZone : Serializable
+struct DNSZone final
+ : Serializable
{
Anope::string name;
std::set<Anope::string, ci::less> servers;
@@ -29,22 +30,22 @@ struct DNSZone : Serializable
zones->push_back(this);
}
- ~DNSZone()
+ ~DNSZone() override
{
std::vector<DNSZone *>::iterator it = std::find(zones->begin(), zones->end(), this);
if (it != zones->end())
zones->erase(it);
}
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["name"] << name;
+ data.Store("name", name);
unsigned count = 0;
- for (std::set<Anope::string, ci::less>::iterator it = servers.begin(), it_end = servers.end(); it != it_end; ++it)
- data["server" + stringify(count++)] << *it;
+ for (const auto &server : servers)
+ data.Store("server" + Anope::ToString(count++), server);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
DNSZone *zone;
Anope::string zone_name;
@@ -63,7 +64,7 @@ struct DNSZone : Serializable
for (unsigned count = 0; true; ++count)
{
Anope::string server_str;
- data["server" + stringify(count)] >> server_str;
+ data["server" + Anope::ToString(count)] >> server_str;
if (server_str.empty())
break;
zone->servers.insert(server_str);
@@ -74,37 +75,39 @@ struct DNSZone : Serializable
static DNSZone *Find(const Anope::string &name)
{
- for (unsigned i = 0; i < zones->size(); ++i)
- if (zones->at(i)->name.equals_ci(name))
+ for (auto *zone : *zones)
+ {
+ if (zone->name.equals_ci(name))
{
- DNSZone *z = zones->at(i);
- z->QueueUpdate();
- return z;
+ zone->QueueUpdate();
+ return zone;
}
+ }
return NULL;
}
};
-class DNSServer : public Serializable
+class DNSServer final
+ : public Serializable
{
Anope::string server_name;
std::vector<Anope::string> ips;
- unsigned limit;
+ unsigned limit = 0;
/* wants to be in the pool */
- bool pooled;
+ bool pooled = false;
/* is actually in the pool */
- bool active;
+ bool active = false;
- public:
+public:
std::set<Anope::string, ci::less> zones;
- time_t repool;
+ time_t repool = 0;
- DNSServer(const Anope::string &sn) : Serializable("DNSServer"), server_name(sn), limit(0), pooled(false), active(false), repool(0)
+ DNSServer(const Anope::string &sn) : Serializable("DNSServer"), server_name(sn)
{
dns_servers->push_back(this);
}
- ~DNSServer()
+ ~DNSServer() override
{
std::vector<DNSServer *>::iterator it = std::find(dns_servers->begin(), dns_servers->end(), this);
if (it != dns_servers->end())
@@ -134,24 +137,24 @@ class DNSServer : public Serializable
if (dnsmanager)
{
dnsmanager->UpdateSerial();
- for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it)
- dnsmanager->Notify(*it);
+ for (const auto &zone : zones)
+ dnsmanager->Notify(zone);
}
}
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["server_name"] << server_name;
+ data.Store("server_name", server_name);
for (unsigned i = 0; i < ips.size(); ++i)
- data["ip" + stringify(i)] << ips[i];
- data["limit"] << limit;
- data["pooled"] << pooled;
+ data.Store("ip" + Anope::ToString(i), ips[i]);
+ data.Store("limit", limit);
+ data.Store("pooled", pooled);
unsigned count = 0;
- for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it)
- data["zone" + stringify(count++)] << *it;
+ for (const auto &zone : zones)
+ data.Store("zone" + Anope::ToString(count++), zone);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
DNSServer *req;
Anope::string server_name;
@@ -169,7 +172,7 @@ class DNSServer : public Serializable
for (unsigned i = 0; true; ++i)
{
Anope::string ip_str;
- data["ip" + stringify(i)] >> ip_str;
+ data["ip" + Anope::ToString(i)] >> ip_str;
if (ip_str.empty())
break;
req->ips.push_back(ip_str);
@@ -182,7 +185,7 @@ class DNSServer : public Serializable
for (unsigned i = 0; true; ++i)
{
Anope::string zone_str;
- data["zone" + stringify(i)] >> zone_str;
+ data["zone" + Anope::ToString(i)] >> zone_str;
if (zone_str.empty())
break;
req->zones.insert(zone_str);
@@ -193,10 +196,9 @@ class DNSServer : public Serializable
static DNSServer *Find(const Anope::string &s)
{
- for (unsigned i = 0; i < dns_servers->size(); ++i)
- if (dns_servers->at(i)->GetName().equals_ci(s))
+ for (auto *serv : *dns_servers)
+ if (serv->GetName().equals_ci(s))
{
- DNSServer *serv = dns_servers->at(i);
serv->QueueUpdate();
return serv;
}
@@ -204,9 +206,10 @@ class DNSServer : public Serializable
}
};
-class CommandOSDNS : public Command
+class CommandOSDNS final
+ : public Command
{
- void DisplayPoolState(CommandSource &source)
+ static void DisplayPoolState(CommandSource &source)
{
if (dns_servers->empty())
{
@@ -216,18 +219,17 @@ class CommandOSDNS : public Command
ListFormatter lf(source.GetAccount());
lf.AddColumn(_("Server")).AddColumn(_("IP")).AddColumn(_("Limit")).AddColumn(_("State"));
- for (unsigned i = 0; i < dns_servers->size(); ++i)
+ for (auto *s : *dns_servers)
{
- DNSServer *s = dns_servers->at(i);
Server *srv = Server::Find(s->GetName(), true);
ListFormatter::ListEntry entry;
entry["Server"] = s->GetName();
- entry["Limit"] = s->GetLimit() ? stringify(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None"));
+ entry["Limit"] = s->GetLimit() ? Anope::ToString(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None"));
Anope::string ip_str;
- for (unsigned j = 0; j < s->GetIPs().size(); ++j)
- ip_str += s->GetIPs()[j] + " ";
+ for (const auto &ip : s->GetIPs())
+ ip_str += ip + " ";
ip_str.trim();
if (ip_str.empty())
ip_str = "None";
@@ -254,16 +256,14 @@ class CommandOSDNS : public Command
ListFormatter lf2(source.GetAccount());
lf2.AddColumn(_("Zone")).AddColumn(_("Servers"));
- for (unsigned i = 0; i < zones->size(); ++i)
+ for (auto *z : *zones)
{
- const DNSZone *z = zones->at(i);
-
ListFormatter::ListEntry entry;
entry["Zone"] = z->name;
Anope::string server_str;
- for (std::set<Anope::string, ci::less>::iterator it = z->servers.begin(), it_end = z->servers.end(); it != it_end; ++it)
- server_str += *it + " ";
+ for (const auto &server : z->servers)
+ server_str += server + " ";
server_str.trim();
if (server_str.empty())
@@ -277,8 +277,8 @@ class CommandOSDNS : public Command
lf2.Process(replies);
}
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
void AddZone(CommandSource &source, const std::vector<Anope::string> &params)
@@ -316,9 +316,9 @@ class CommandOSDNS : public Command
Log(LOG_ADMIN, source, this) << "to delete zone " << z->name;
- for (std::set<Anope::string, ci::less>::iterator it = z->servers.begin(), it_end = z->servers.end(); it != it_end; ++it)
+ for (const auto &server : z->servers)
{
- DNSServer *s = DNSServer::Find(*it);
+ DNSServer *s = DNSServer::Find(server);
if (s)
s->zones.erase(z->name);
}
@@ -466,9 +466,9 @@ class CommandOSDNS : public Command
return;
}
- for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it)
+ for (const auto &zone : s->zones)
{
- DNSZone *z = DNSZone::Find(*it);
+ DNSZone *z = DNSZone::Find(zone);
if (z)
z->servers.erase(s->GetName());
}
@@ -494,12 +494,14 @@ class CommandOSDNS : public Command
return;
}
- for (unsigned i = 0; i < s->GetIPs().size(); ++i)
- if (params[2].equals_ci(s->GetIPs()[i]))
+ for (const auto &ip : s->GetIPs())
+ {
+ if (params[2].equals_ci(ip))
{
- source.Reply(_("IP %s already exists for %s."), s->GetIPs()[i].c_str(), s->GetName().c_str());
+ source.Reply(_("IP %s already exists for %s."), ip.c_str(), s->GetName().c_str());
return;
}
+ }
sockaddrs addr(params[2]);
if (!addr.valid())
@@ -518,8 +520,8 @@ class CommandOSDNS : public Command
if (s->Active() && dnsmanager)
{
dnsmanager->UpdateSerial();
- for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it)
- dnsmanager->Notify(*it);
+ for (const auto &zone : s->zones)
+ dnsmanager->Notify(zone);
}
}
@@ -552,8 +554,8 @@ class CommandOSDNS : public Command
if (s->Active() && dnsmanager)
{
dnsmanager->UpdateSerial();
- for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it)
- dnsmanager->Notify(*it);
+ for (const auto &zone : s->zones)
+ dnsmanager->Notify(zone);
}
return;
@@ -562,7 +564,7 @@ class CommandOSDNS : public Command
source.Reply(_("IP %s does not exist for %s."), params[2].c_str(), s->GetName().c_str());
}
- void OnSet(CommandSource &source, const std::vector<Anope::string> &params)
+ static void OnSet(CommandSource &source, const std::vector<Anope::string> &params)
{
DNSServer *s = DNSServer::Find(params[1]);
@@ -577,16 +579,15 @@ class CommandOSDNS : public Command
if (params[2].equals_ci("LIMIT"))
{
- try
+ if (auto l = Anope::TryConvert<unsigned>(params[3]))
{
- unsigned l = convertTo<unsigned>(params[3]);
- s->SetLimit(l);
- if (l)
- source.Reply(_("User limit for %s set to %d."), s->GetName().c_str(), l);
+ s->SetLimit(l.value());
+ if (s->GetLimit())
+ source.Reply(_("User limit for %s set to %d."), s->GetName().c_str(), s->GetLimit());
else
source.Reply(_("User limit for %s removed."), s->GetName().c_str());
}
- catch (const ConvertException &ex)
+ else
{
source.Reply(_("Invalid value for LIMIT. Must be numerical."));
}
@@ -654,7 +655,7 @@ class CommandOSDNS : public Command
Log(LOG_ADMIN, source, this) << "to depool " << s->GetName();
}
- public:
+public:
CommandOSDNS(Module *creator) : Command(creator, "operserv/dns", 0, 4)
{
this->SetDesc(_("Manage DNS zones for this network"));
@@ -669,7 +670,7 @@ class CommandOSDNS : public Command
this->SetSyntax(_("DEPOOL \037server.name\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (params.empty())
this->DisplayPoolState(source);
@@ -695,7 +696,7 @@ class CommandOSDNS : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -717,7 +718,8 @@ class CommandOSDNS : public Command
}
};
-class ModuleDNS : public Module
+class ModuleDNS final
+ : public Module
{
Serialize::Type zone_type, dns_type;
CommandOSDNS commandosdns;
@@ -729,24 +731,20 @@ class ModuleDNS : public Module
bool remove_split_servers;
bool readd_connected_servers;
- time_t last_warn;
+ time_t last_warn = 0;
- public:
+public:
ModuleDNS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
- zone_type("DNSZone", DNSZone::Unserialize), dns_type("DNSServer", DNSServer::Unserialize), commandosdns(this),
- last_warn(0)
+ zone_type("DNSZone", DNSZone::Unserialize), dns_type("DNSServer", DNSServer::Unserialize), commandosdns(this)
{
-
-
- for (unsigned j = 0; j < dns_servers->size(); ++j)
+ for (auto *s : *dns_servers)
{
- DNSServer *s = dns_servers->at(j);
if (s->Pooled() && Server::Find(s->GetName(), true))
s->SetActive(true);
}
}
- ~ModuleDNS()
+ ~ModuleDNS() override
{
for (unsigned i = zones->size(); i > 0; --i)
delete zones->at(i - 1);
@@ -754,7 +752,7 @@ class ModuleDNS : public Module
delete dns_servers->at(i - 1);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
this->ttl = block->Get<time_t>("ttl");
@@ -765,7 +763,7 @@ class ModuleDNS : public Module
this->readd_connected_servers = block->Get<bool>("readd_connected_servers");
}
- void OnNewServer(Server *s) anope_override
+ void OnNewServer(Server *s) override
{
if (s == Me || s->IsJuped())
return;
@@ -780,7 +778,7 @@ class ModuleDNS : public Module
}
}
- void OnServerQuit(Server *s) anope_override
+ void OnServerQuit(Server *s) override
{
DNSServer *dns = DNSServer::Find(s->GetName());
if (remove_split_servers && dns && dns->Pooled() && dns->Active())
@@ -793,7 +791,7 @@ class ModuleDNS : public Module
}
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (!u->Quitting() && u->server)
{
@@ -807,7 +805,7 @@ class ModuleDNS : public Module
}
}
- void OnPreUserLogoff(User *u) anope_override
+ void OnPreUserLogoff(User *u) override
{
if (u && u->server)
{
@@ -852,12 +850,12 @@ class ModuleDNS : public Module
}
}
- void OnDnsRequest(DNS::Query &req, DNS::Query *packet) anope_override
+ void OnDnsRequest(DNS::Query &req, DNS::Query *packet) override
{
if (req.questions.empty())
return;
/* Currently we reply to any QR for A/AAAA */
- const DNS::Question& q = req.questions[0];
+ const DNS::Question &q = req.questions[0];
if (q.type != DNS::QUERY_A && q.type != DNS::QUERY_AAAA && q.type != DNS::QUERY_AXFR && q.type != DNS::QUERY_ANY)
return;
@@ -865,21 +863,21 @@ class ModuleDNS : public Module
size_t answer_size = packet->answers.size();
if (zone)
{
- for (std::set<Anope::string, ci::less>::iterator it = zone->servers.begin(), it_end = zone->servers.end(); it != it_end; ++it)
+ for (const auto &server : zone->servers)
{
- DNSServer *s = DNSServer::Find(*it);
+ DNSServer *s = DNSServer::Find(server);
if (!s || !s->Active())
continue;
- for (unsigned j = 0; j < s->GetIPs().size(); ++j)
+ for (const auto &ip : s->GetIPs())
{
- DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
+ DNS::QueryType q_type = ip.find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type)
{
DNS::ResourceRecord rr(q.name, q_type);
rr.ttl = this->ttl;
- rr.rdata = s->GetIPs()[j];
+ rr.rdata = ip;
packet->answers.push_back(rr);
}
}
@@ -889,21 +887,20 @@ class ModuleDNS : public Module
if (packet->answers.size() == answer_size)
{
/* Default zone */
- for (unsigned i = 0; i < dns_servers->size(); ++i)
+ for (auto *s : *dns_servers)
{
- DNSServer *s = dns_servers->at(i);
if (!s->Active())
continue;
- for (unsigned j = 0; j < s->GetIPs().size(); ++j)
+ for (const auto &ip : s->GetIPs())
{
- DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
+ DNS::QueryType q_type = ip.find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type)
{
DNS::ResourceRecord rr(q.name, q_type);
rr.ttl = this->ttl;
- rr.rdata = s->GetIPs()[j];
+ rr.rdata = ip;
packet->answers.push_back(rr);
}
}
@@ -919,19 +916,17 @@ class ModuleDNS : public Module
}
/* Something messed up, just return them all and hope one is available */
- for (unsigned i = 0; i < dns_servers->size(); ++i)
+ for (auto *s : *dns_servers)
{
- DNSServer *s = dns_servers->at(i);
-
- for (unsigned j = 0; j < s->GetIPs().size(); ++j)
+ for (const auto &ip : s->GetIPs())
{
- DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
+ DNS::QueryType q_type = ip.find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A;
if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type)
{
DNS::ResourceRecord rr(q.name, q_type);
rr.ttl = this->ttl;
- rr.rdata = s->GetIPs()[j];
+ rr.rdata = ip;
packet->answers.push_back(rr);
}
}
diff --git a/modules/commands/os_forbid.cpp b/modules/operserv/os_forbid.cpp
index 42819ab8b..733c433cc 100644
--- a/modules/commands/os_forbid.cpp
+++ b/modules/operserv/os_forbid.cpp
@@ -14,24 +14,26 @@
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
-struct ForbidDataImpl : ForbidData, Serializable
+struct ForbidDataImpl final
+ : ForbidData
+ , Serializable
{
ForbidDataImpl() : Serializable("ForbidData") { }
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
void ForbidDataImpl::Serialize(Serialize::Data &data) const
{
- data["mask"] << this->mask;
- data["creator"] << this->creator;
- data["reason"] << this->reason;
- data["created"] << this->created;
- data["expires"] << this->expires;
- data["type"] << this->type;
+ data.Store("mask", this->mask);
+ data.Store("creator", this->creator);
+ data.Store("reason", this->reason);
+ data.Store("created", this->created);
+ data.Store("expires", this->expires);
+ data.Store("type", this->type);
}
-Serializable* ForbidDataImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *ForbidDataImpl::Unserialize(Serializable *obj, Serialize::Data &data)
{
if (!forbid_service)
return NULL;
@@ -59,7 +61,8 @@ Serializable* ForbidDataImpl::Unserialize(Serializable *obj, Serialize::Data &da
return fb;
}
-class MyForbidService : public ForbidService
+class MyForbidService final
+ : public ForbidService
{
Serialize::Checker<std::vector<ForbidData *>[FT_SIZE - 1]> forbid_data;
@@ -92,22 +95,21 @@ class MyForbidService : public ForbidService
delete fd;
}
- public:
+public:
MyForbidService(Module *m) : ForbidService(m), forbid_data("ForbidData") { }
- ~MyForbidService()
+ ~MyForbidService() override
{
- std::vector<ForbidData *> f = GetForbids();
- for (unsigned i = 0; i < f.size(); ++i)
- delete f[i];
+ for (const auto *forbid : GetForbids())
+ delete forbid;
}
- void AddForbid(ForbidData *d) anope_override
+ void AddForbid(ForbidData *d) override
{
this->forbids(d->type).push_back(d);
}
- void RemoveForbid(ForbidData *d) anope_override
+ void RemoveForbid(ForbidData *d) override
{
std::vector<ForbidData *>::iterator it = std::find(this->forbids(d->type).begin(), this->forbids(d->type).end(), d);
if (it != this->forbids(d->type).end())
@@ -115,12 +117,12 @@ class MyForbidService : public ForbidService
delete d;
}
- ForbidData *CreateForbid() anope_override
+ ForbidData *CreateForbid() override
{
return new ForbidDataImpl();
}
- ForbidData *FindForbid(const Anope::string &mask, ForbidType ftype) anope_override
+ ForbidData *FindForbid(const Anope::string &mask, ForbidType ftype) override
{
for (unsigned i = this->forbids(ftype).size(); i > 0; --i)
{
@@ -138,7 +140,7 @@ class MyForbidService : public ForbidService
return NULL;
}
- ForbidData *FindForbidExact(const Anope::string &mask, ForbidType ftype) anope_override
+ ForbidData *FindForbidExact(const Anope::string &mask, ForbidType ftype) override
{
for (unsigned i = this->forbids(ftype).size(); i > 0; --i)
{
@@ -156,7 +158,7 @@ class MyForbidService : public ForbidService
return NULL;
}
- std::vector<ForbidData *> GetForbids() anope_override
+ std::vector<ForbidData *> GetForbids() override
{
std::vector<ForbidData *> f;
for (unsigned j = FT_NICK; j < FT_SIZE; ++j)
@@ -174,10 +176,11 @@ class MyForbidService : public ForbidService
}
};
-class CommandOSForbid : public Command
+class CommandOSForbid final
+ : public Command
{
ServiceReference<ForbidService> fs;
- public:
+public:
CommandOSForbid(Module *creator) : Command(creator, "operserv/forbid", 1, 5), fs("ForbidService", "forbid")
{
this->SetDesc(_("Forbid usage of nicknames, channels, and emails"));
@@ -186,7 +189,7 @@ class CommandOSForbid : public Command
this->SetSyntax("LIST [NICK|CHAN|EMAIL|REGISTER]");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!this->fs)
return;
@@ -272,8 +275,8 @@ class CommandOSForbid : public Command
{
int na_matches = 0;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- module->OnUserNickChange(it->second, "");
+ for (const auto &[_, user] : UserListByNick)
+ module->OnUserNickChange(user, "");
for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end;)
{
@@ -289,7 +292,7 @@ class CommandOSForbid : public Command
delete na;
}
- source.Reply(_("\002%d\002 nickname(s) dropped."), na_matches);
+ source.Reply(na_matches, N_("\002%d\002 nickname dropped.", "\002%d\002 nicknames dropped."), na_matches);
break;
}
case FT_CHAN:
@@ -309,7 +312,7 @@ class CommandOSForbid : public Command
BotInfo *OperServ = Config->GetClient("OperServ");
if (IRCD->CanSQLineChannel && OperServ)
{
- time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "15s");
+ time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "1m");
XLine x(c->name, OperServ->nick, Anope::CurTime + inhabit, d->reason);
IRCD->SendSQLine(NULL, &x);
}
@@ -330,7 +333,7 @@ class CommandOSForbid : public Command
reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str());
- c->Kick(source.service, u, "%s", reason.c_str());
+ c->Kick(source.service, u, reason);
}
}
@@ -384,32 +387,30 @@ class CommandOSForbid : public Command
ListFormatter list(source.GetAccount());
list.AddColumn(_("Mask")).AddColumn(_("Type")).AddColumn(_("Creator")).AddColumn(_("Expires")).AddColumn(_("Reason"));
- unsigned shown = 0;
- for (unsigned i = 0; i < forbids.size(); ++i)
+ size_t shown = 0;
+ for (auto *forbid : forbids)
{
- ForbidData *d = forbids[i];
-
- if (ftype != FT_SIZE && ftype != d->type)
+ if (ftype != FT_SIZE && ftype != forbid->type)
continue;
Anope::string stype;
- if (d->type == FT_NICK)
+ if (forbid->type == FT_NICK)
stype = "NICK";
- else if (d->type == FT_CHAN)
+ else if (forbid->type == FT_CHAN)
stype = "CHAN";
- else if (d->type == FT_EMAIL)
+ else if (forbid->type == FT_EMAIL)
stype = "EMAIL";
- else if (d->type == FT_REGISTER)
+ else if (forbid->type == FT_REGISTER)
stype = "REGISTER";
else
continue;
ListFormatter::ListEntry entry;
- entry["Mask"] = d->mask;
+ entry["Mask"] = forbid->mask;
entry["Type"] = stype;
- entry["Creator"] = d->creator;
- entry["Expires"] = d->expires ? Anope::strftime(d->expires, NULL, true).c_str() : Language::Translate(source.GetAccount(), _("Never"));
- entry["Reason"] = d->reason;
+ entry["Creator"] = forbid->creator;
+ entry["Expires"] = forbid->expires ? Anope::strftime(forbid->expires, NULL, true).c_str() : Language::Translate(source.GetAccount(), _("Never"));
+ entry["Reason"] = forbid->reason;
list.AddEntry(entry);
++shown;
}
@@ -425,13 +426,13 @@ class CommandOSForbid : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
if (shown >= forbids.size())
source.Reply(_("End of forbid list."));
else
- source.Reply(_("End of forbid list - %d/%d entries shown."), shown, forbids.size());
+ source.Reply(_("End of forbid list - %zu/%zu entries shown."), shown, forbids.size());
}
}
}
@@ -441,7 +442,7 @@ class CommandOSForbid : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -460,20 +461,21 @@ class CommandOSForbid : public Command
}
};
-class OSForbid : public Module
+class OSForbid final
+ : public Module
{
MyForbidService forbidService;
Serialize::Type forbiddata_type;
CommandOSForbid commandosforbid;
- public:
+public:
OSForbid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
forbidService(this), forbiddata_type("ForbidData", ForbidDataImpl::Unserialize), commandosforbid(this)
{
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (u->Quitting() || exempt)
return;
@@ -481,7 +483,7 @@ class OSForbid : public Module
this->OnUserNickChange(u, "");
}
- void OnUserNickChange(User *u, const Anope::string &) anope_override
+ void OnUserNickChange(User *u, const Anope::string &) override
{
if (u->HasMode("OPER"))
return;
@@ -499,7 +501,7 @@ class OSForbid : public Module
}
}
- EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
+ EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
BotInfo *OperServ = Config->GetClient("OperServ");
if (u->HasMode("OPER") || !OperServ)
@@ -511,7 +513,7 @@ class OSForbid : public Module
ServiceReference<ChanServService> chanserv("ChanServService", "ChanServ");
if (IRCD->CanSQLineChannel)
{
- time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "15s");
+ time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "1m");
XLine x(c->name, OperServ->nick, Anope::CurTime + inhabit, d->reason);
IRCD->SendSQLine(NULL, &x);
}
@@ -528,9 +530,9 @@ class OSForbid : public Module
return EVENT_CONTINUE;
}
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
{
- if (command->name == "nickserv/info" && params.size() > 0)
+ if (command->name == "nickserv/info" && !params.empty() && params[0][0] != '=')
{
ForbidData *d = this->forbidService.FindForbid(params[0], FT_NICK);
if (d != NULL)
diff --git a/modules/commands/os_ignore.cpp b/modules/operserv/os_ignore.cpp
index dd8ab7886..ecc1ad3b5 100644
--- a/modules/commands/os_ignore.cpp
+++ b/modules/operserv/os_ignore.cpp
@@ -12,12 +12,14 @@
#include "module.h"
#include "modules/os_ignore.h"
-struct IgnoreDataImpl : IgnoreData, Serializable
+struct IgnoreDataImpl final
+ : IgnoreData
+ , Serializable
{
IgnoreDataImpl() : Serializable("IgnoreData") { }
- ~IgnoreDataImpl();
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+ ~IgnoreDataImpl() override;
+ void Serialize(Serialize::Data &data) const override;
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
IgnoreDataImpl::~IgnoreDataImpl()
@@ -28,13 +30,13 @@ IgnoreDataImpl::~IgnoreDataImpl()
void IgnoreDataImpl::Serialize(Serialize::Data &data) const
{
- data["mask"] << this->mask;
- data["creator"] << this->creator;
- data["reason"] << this->reason;
- data["time"] << this->time;
+ data.Store("mask", this->mask);
+ data.Store("creator", this->creator);
+ data.Store("reason", this->reason);
+ data.Store("time", this->time);
}
-Serializable* IgnoreDataImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *IgnoreDataImpl::Unserialize(Serializable *obj, Serialize::Data &data)
{
if (!ignore_service)
return NULL;
@@ -57,26 +59,27 @@ Serializable* IgnoreDataImpl::Unserialize(Serializable *obj, Serialize::Data &da
}
-class OSIgnoreService : public IgnoreService
+class OSIgnoreService final
+ : public IgnoreService
{
Serialize::Checker<std::vector<IgnoreData *> > ignores;
- public:
+public:
OSIgnoreService(Module *o) : IgnoreService(o), ignores("IgnoreData") { }
- void AddIgnore(IgnoreData *ign) anope_override
+ void AddIgnore(IgnoreData *ign) override
{
ignores->push_back(ign);
}
- void DelIgnore(IgnoreData *ign) anope_override
+ void DelIgnore(IgnoreData *ign) override
{
std::vector<IgnoreData *>::iterator it = std::find(ignores->begin(), ignores->end(), ign);
if (it != ignores->end())
ignores->erase(it);
}
- void ClearIgnores() anope_override
+ void ClearIgnores() override
{
for (unsigned i = ignores->size(); i > 0; --i)
{
@@ -85,12 +88,12 @@ class OSIgnoreService : public IgnoreService
}
}
- IgnoreData *Create() anope_override
+ IgnoreData *Create() override
{
return new IgnoreDataImpl();
}
- IgnoreData *Find(const Anope::string &mask) anope_override
+ IgnoreData *Find(const Anope::string &mask) override
{
User *u = User::Find(mask, true);
std::vector<IgnoreData *>::iterator ign = this->ignores->begin(), ign_end = this->ignores->end();
@@ -148,16 +151,17 @@ class OSIgnoreService : public IgnoreService
return NULL;
}
- std::vector<IgnoreData *> &GetIgnores() anope_override
+ std::vector<IgnoreData *> &GetIgnores() override
{
return *ignores;
}
};
-class CommandOSIgnore : public Command
+class CommandOSIgnore final
+ : public Command
{
- private:
- Anope::string RealMask(const Anope::string &mask)
+private:
+ static Anope::string RealMask(const Anope::string &mask)
{
/* If it s an existing user, we ignore the hostmask. */
User *u = User::Find(mask, true);
@@ -221,7 +225,7 @@ class CommandOSIgnore : public Command
if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
- IgnoreData *ign = new IgnoreDataImpl();
+ auto *ign = new IgnoreDataImpl();
ign->mask = mask;
ign->creator = source.GetNick();
ign->reason = reason;
@@ -241,7 +245,7 @@ class CommandOSIgnore : public Command
}
}
- void DoList(CommandSource &source)
+ static void DoList(CommandSource &source)
{
if (!ignore_service)
return;
@@ -282,8 +286,8 @@ class CommandOSIgnore : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
@@ -335,17 +339,17 @@ class CommandOSIgnore : public Command
return;
}
- public:
+public:
CommandOSIgnore(Module *creator) : Command(creator, "operserv/ignore", 1, 4)
{
- this->SetDesc(_("Modify the Services ignore list"));
+ this->SetDesc(_("Modify the services ignore list"));
this->SetSyntax(_("ADD \037expiry\037 {\037nick\037|\037mask\037} [\037reason\037]"));
this->SetSyntax(_("DEL {\037nick\037|\037mask\037}"));
this->SetSyntax("LIST");
this->SetSyntax("CLEAR");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
@@ -363,17 +367,17 @@ class CommandOSIgnore : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Allows Services Operators to make Services ignore a nick or mask\n"
+ source.Reply(_("Allows Services Operators to make services ignore a nick or mask\n"
"for a certain time or until the next restart. The default\n"
"time format is seconds. You can specify it by using units.\n"
"Valid units are: \037s\037 for seconds, \037m\037 for minutes,\n"
"\037h\037 for hours and \037d\037 for days.\n"
"Combinations of these units are not permitted.\n"
- "To make Services permanently ignore the user, type 0 as time.\n"
+ "To make services permanently ignore the user, type 0 as time.\n"
"When adding a \037mask\037, it should be in the format nick!user@host,\n"
"everything else will be considered a nick. Wildcards are permitted.\n"
" \n"
@@ -391,25 +395,26 @@ class CommandOSIgnore : public Command
}
};
-class OSIgnore : public Module
+class OSIgnore final
+ : public Module
{
Serialize::Type ignoredata_type;
OSIgnoreService osignoreservice;
CommandOSIgnore commandosignore;
- public:
+public:
OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
ignoredata_type("IgnoreData", IgnoreDataImpl::Unserialize), osignoreservice(this), commandosignore(this)
{
}
- void Prioritize() anope_override
+ void Prioritize() override
{
ModuleManager::SetPriority(this, I_OnBotPrivmsg, PRIORITY_FIRST);
}
- EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override
+ EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override
{
if (!u->HasMode("OPER") && this->osignoreservice.Find(u->nick))
return EVENT_STOP;
diff --git a/modules/commands/os_info.cpp b/modules/operserv/os_info.cpp
index 4c81d91d5..3becec624 100644
--- a/modules/commands/os_info.cpp
+++ b/modules/operserv/os_info.cpp
@@ -7,39 +7,44 @@
*/
#include "module.h"
+#include "modules/info.h"
-struct OperInfo : Serializable
+struct OperInfoImpl final
+ : OperInfo
+ , Serializable
{
- Anope::string target;
- Anope::string info;
- Anope::string adder;
- time_t created;
+ OperInfoImpl()
+ : Serializable("OperInfo")
+ {
+ }
- OperInfo() : Serializable("OperInfo"), created(0) { }
- OperInfo(const Anope::string &t, const Anope::string &i, const Anope::string &a, time_t c) :
- Serializable("OperInfo"), target(t), info(i), adder(a), created(c) { }
+ OperInfoImpl(const Anope::string &t, const Anope::string &i, const Anope::string &a, time_t c)
+ : OperInfo(t, i, a, c)
+ , Serializable("OperInfo")
+ {
+ }
- ~OperInfo();
+ ~OperInfoImpl() override;
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["target"] << target;
- data["info"] << info;
- data["adder"] << adder;
- data["created"] << created;
+ data.Store("target", target);
+ data.Store("info", info);
+ data.Store("adder", adder);
+ data.Store("created", created);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
};
-struct OperInfos : Serialize::Checker<std::vector<OperInfo *> >
+struct OperInfos final
+ : OperInfoList
{
- OperInfos(Extensible *) : Serialize::Checker<std::vector<OperInfo *> >("OperInfo") { }
+ OperInfos(Extensible *) { }
- ~OperInfos()
+ OperInfo *Create() override
{
- for (unsigned i = (*this)->size(); i > 0; --i)
- delete (*this)->at(i - 1);
+ return new OperInfoImpl();
}
static Extensible *Find(const Anope::string &target)
@@ -51,7 +56,7 @@ struct OperInfos : Serialize::Checker<std::vector<OperInfo *> >
}
};
-OperInfo::~OperInfo()
+OperInfoImpl::~OperInfoImpl()
{
Extensible *e = OperInfos::Find(target);
if (e)
@@ -66,7 +71,7 @@ OperInfo::~OperInfo()
}
}
-Serializable *OperInfo::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *OperInfoImpl::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string starget;
data["target"] >> starget;
@@ -76,12 +81,12 @@ Serializable *OperInfo::Unserialize(Serializable *obj, Serialize::Data &data)
return NULL;
OperInfos *oi = e->Require<OperInfos>("operinfo");
- OperInfo *o;
+ OperInfoImpl *o;
if (obj)
- o = anope_dynamic_static_cast<OperInfo *>(obj);
+ o = anope_dynamic_static_cast<OperInfoImpl *>(obj);
else
{
- o = new OperInfo();
+ o = new OperInfoImpl();
o->target = starget;
}
data["info"] >> o->info;
@@ -93,9 +98,10 @@ Serializable *OperInfo::Unserialize(Serializable *obj, Serialize::Data &data)
return o;
}
-class CommandOSInfo : public Command
+class CommandOSInfo final
+ : public Command
{
- public:
+public:
CommandOSInfo(Module *creator) : Command(creator, "operserv/info", 2, 3)
{
this->SetDesc(_("Associate oper info with a nick or channel"));
@@ -104,7 +110,7 @@ class CommandOSInfo : public Command
this->SetSyntax(_("CLEAR \037target\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0], target = params[1], info = params.size() > 2 ? params[2] : "";
@@ -148,10 +154,8 @@ class CommandOSInfo : public Command
return;
}
- for (unsigned i = 0; i < (*oi)->size(); ++i)
+ for (auto *o : *(*oi))
{
- OperInfo *o = (*oi)->at(i);
-
if (o->info.equals_ci(info))
{
source.Reply(_("The oper info already exists on \002%s\002."), target.c_str());
@@ -159,7 +163,7 @@ class CommandOSInfo : public Command
}
}
- (*oi)->push_back(new OperInfo(target, info, source.GetNick(), Anope::CurTime));
+ (*oi)->push_back(new OperInfoImpl(target, info, source.GetNick(), Anope::CurTime));
source.Reply(_("Added info to \002%s\002."), target.c_str());
Log(LOG_ADMIN, source, this) << "to add information to " << target;
@@ -236,7 +240,7 @@ class CommandOSInfo : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -247,7 +251,8 @@ class CommandOSInfo : public Command
}
};
-class OSInfo : public Module
+class OSInfo final
+ : public Module
{
CommandOSInfo commandosinfo;
ExtensibleItem<OperInfos> oinfo;
@@ -262,26 +267,25 @@ class OSInfo : public Module
if (!oi)
return;
- for (unsigned i = 0; i < (*oi)->size(); ++i)
+ for (auto *o : *(*oi))
{
- OperInfo *o = (*oi)->at(i);
info[_("Oper Info")] = Anope::printf(_("(by %s on %s) %s"), o->adder.c_str(), Anope::strftime(o->created, source.GetAccount(), true).c_str(), o->info.c_str());
}
}
- public:
+public:
OSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandosinfo(this), oinfo(this, "operinfo"), oinfo_type("OperInfo", OperInfo::Unserialize)
+ commandosinfo(this), oinfo(this, "operinfo"), oinfo_type("OperInfo", OperInfoImpl::Unserialize)
{
}
- void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) override
{
OnInfo(source, na->nc, info);
}
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) override
{
OnInfo(source, ci, info);
}
diff --git a/modules/commands/os_jupe.cpp b/modules/operserv/os_jupe.cpp
index adc86f822..c6823449d 100644
--- a/modules/commands/os_jupe.cpp
+++ b/modules/operserv/os_jupe.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSJupe : public Command
+class CommandOSJupe final
+ : public Command
{
- public:
+public:
CommandOSJupe(Module *creator) : Command(creator, "operserv/jupe", 1, 2)
{
this->SetDesc(_("\"Jupiter\" a server"));
this->SetSyntax(_("\037server\037 [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &jserver = params[0];
const Anope::string &reason = params.size() > 1 ? params[1] : "";
@@ -29,7 +30,7 @@ class CommandOSJupe : public Command
if (!IRCD->IsHostValid(jserver) || jserver.find('.') == Anope::string::npos)
source.Reply(_("Please use a valid server name when juping."));
else if (server == Me || server == Servers::GetUplink())
- source.Reply(_("You can not jupe your Services' pseudoserver or your uplink server."));
+ source.Reply(_("You can not jupe your services' pseudoserver or your uplink server."));
else if (server && server->IsJuped())
source.Reply(_("You can not jupe an already juped server."));
else
@@ -42,19 +43,19 @@ class CommandOSJupe : public Command
IRCD->SendSquit(server, rbuf);
server->Delete(rbuf);
}
- Server *juped_server = new Server(Me, jserver, 1, rbuf, sid, true);
+ auto *juped_server = new Server(Me, jserver, 1, rbuf, sid, true);
IRCD->SendServer(juped_server);
Log(LOG_ADMIN, source, this) << "on " << jserver << " (" << rbuf << ")";
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Tells Services to jupiter a server -- that is, to create\n"
- "a fake \"server\" connected to Services which prevents\n"
+ source.Reply(_("Tells services to jupiter a server -- that is, to create\n"
+ "a fake \"server\" connected to services which prevents\n"
"the real server of that name from connecting. The jupe\n"
"may be removed using a standard \002SQUIT\002. If a reason is\n"
"given, it is placed in the server information field;\n"
@@ -65,11 +66,12 @@ class CommandOSJupe : public Command
}
};
-class OSJupe : public Module
+class OSJupe final
+ : public Module
{
CommandOSJupe commandosjupe;
- public:
+public:
OSJupe(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosjupe(this)
{
diff --git a/modules/commands/os_kick.cpp b/modules/operserv/os_kick.cpp
index 12b3e2c42..667b8aa50 100644
--- a/modules/commands/os_kick.cpp
+++ b/modules/operserv/os_kick.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSKick : public Command
+class CommandOSKick final
+ : public Command
{
- public:
+public:
CommandOSKick(Module *creator) : Command(creator, "operserv/kick", 3, 3)
{
this->SetDesc(_("Kick a user from a channel"));
this->SetSyntax(_("\037channel\037 \037user\037 \037reason\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &chan = params[0];
const Anope::string &nick = params[1];
@@ -55,7 +56,7 @@ class CommandOSKick : public Command
Log(LOG_ADMIN, source, this) << "on " << u2->nick << " in " << c->name << " (" << s << ")";
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -69,11 +70,12 @@ class CommandOSKick : public Command
}
};
-class OSKick : public Module
+class OSKick final
+ : public Module
{
CommandOSKick commandoskick;
- public:
+public:
OSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandoskick(this)
{
diff --git a/modules/commands/os_kill.cpp b/modules/operserv/os_kill.cpp
index 9b40c1b81..e03a022c3 100644
--- a/modules/commands/os_kill.cpp
+++ b/modules/operserv/os_kill.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSKill : public Command
+class CommandOSKill final
+ : public Command
{
- public:
+public:
CommandOSKill(Module *creator) : Command(creator, "operserv/kill", 1, 2)
{
this->SetDesc(_("Kill a user"));
this->SetSyntax(_("\037user\037 [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = params[0];
Anope::string reason = params.size() > 1 ? params[1] : "";
@@ -41,7 +42,7 @@ class CommandOSKill : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -52,11 +53,12 @@ class CommandOSKill : public Command
}
};
-class OSKill : public Module
+class OSKill final
+ : public Module
{
CommandOSKill commandoskill;
- public:
+public:
OSKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandoskill(this)
{
diff --git a/modules/commands/os_list.cpp b/modules/operserv/os_list.cpp
index 8369bc357..a80683054 100644
--- a/modules/commands/os_list.cpp
+++ b/modules/operserv/os_list.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSChanList : public Command
+class CommandOSChanList final
+ : public Command
{
- public:
+public:
CommandOSChanList(Module *creator) : Command(creator, "operserv/chanlist", 0, 2)
{
this->SetDesc(_("Lists all channel records"));
this->SetSyntax(_("[{\037pattern\037 | \037nick\037} [\037SECRET\037]]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &pattern = !params.empty() ? params[0] : "";
const Anope::string &opt = params.size() > 1 ? params[1] : "";
@@ -46,18 +47,20 @@ class CommandOSChanList : public Command
{
source.Reply(_("\002%s\002 channel list:"), u2->nick.c_str());
- for (User::ChanUserList::iterator uit = u2->chans.begin(), uit_end = u2->chans.end(); uit != uit_end; ++uit)
+ for (const auto &[_, cc]: u2->chans)
{
- ChanUserContainer *cc = uit->second;
-
if (!modes.empty())
- for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it)
- if (!cc->chan->HasMode(*it))
+ {
+ for (const auto &mode : modes)
+ {
+ if (!cc->chan->HasMode(mode))
continue;
+ }
+ }
ListFormatter::ListEntry entry;
entry["Name"] = cc->chan->name;
- entry["Users"] = stringify(cc->chan->users.size());
+ entry["Users"] = Anope::ToString(cc->chan->users.size());
entry["Modes"] = cc->chan->GetModes(true, true);
entry["Topic"] = cc->chan->topic;
list.AddEntry(entry);
@@ -69,20 +72,22 @@ class CommandOSChanList : public Command
{
source.Reply(_("Channel list:"));
- for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit)
+ for (const auto &[_, c] : ChannelList)
{
- Channel *c = cit->second;
-
if (!pattern.empty() && !Anope::Match(c->name, pattern, false, true))
continue;
if (!modes.empty())
- for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it)
- if (!c->HasMode(*it))
+ {
+ for (const auto &mode : modes)
+ {
+ if (!c->HasMode(mode))
continue;
+ }
+ }
ListFormatter::ListEntry entry;
entry["Name"] = c->name;
- entry["Users"] = stringify(c->users.size());
+ entry["Users"] = Anope::ToString(c->users.size());
entry["Modes"] = c->GetModes(true, true);
entry["Topic"] = c->topic;
list.AddEntry(entry);
@@ -94,13 +99,13 @@ class CommandOSChanList : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of channel list. \002%u\002 channels shown."), count);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -124,16 +129,17 @@ class CommandOSChanList : public Command
}
};
-class CommandOSUserList : public Command
+class CommandOSUserList final
+ : public Command
{
- public:
+public:
CommandOSUserList(Module *creator) : Command(creator, "operserv/userlist", 0, 2)
{
this->SetDesc(_("Lists all user records"));
this->SetSyntax(_("[{\037pattern\037 | \037channel\037} [\037INVISIBLE\037]]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &pattern = !params.empty() ? params[0] : "";
const Anope::string &opt = params.size() > 1 ? params[1] : "";
@@ -156,14 +162,16 @@ class CommandOSUserList : public Command
{
source.Reply(_("\002%s\002 users list:"), pattern.c_str());
- for (Channel::ChanUserList::iterator cuit = c->users.begin(), cuit_end = c->users.end(); cuit != cuit_end; ++cuit)
+ for (const auto &[_, uc] : c->users)
{
- ChanUserContainer *uc = cuit->second;
-
if (!modes.empty())
- for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it)
- if (!uc->user->HasMode(*it))
+ {
+ for (const auto &mode : modes)
+ {
+ if (!uc->user->HasMode(mode))
continue;
+ }
+ }
ListFormatter::ListEntry entry;
entry["Name"] = uc->user->nick;
@@ -178,8 +186,8 @@ class CommandOSUserList : public Command
{
/* Historically this has been ordered, so... */
Anope::map<User *> ordered_map;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- ordered_map[it->first] = it->second;
+ for (const auto &[nick, user] : UserListByNick)
+ ordered_map[nick] = user;
source.Reply(_("Users list:"));
@@ -197,10 +205,10 @@ class CommandOSUserList : public Command
};
bool match = false;
- for (unsigned int i = 0; i < sizeof(masks) / sizeof(*masks); ++i)
+ for (const auto &mask : masks)
{
/* Check mask with realname included, too */
- if (Anope::Match(masks[i], pattern, false, true) || Anope::Match(masks[i] + "#" + u2->realname, pattern, false, true))
+ if (Anope::Match(mask, pattern, false, true) || Anope::Match(mask + "#" + u2->realname, pattern, false, true))
{
match = true;
break;
@@ -211,9 +219,13 @@ class CommandOSUserList : public Command
continue;
if (!modes.empty())
- for (std::set<Anope::string>::iterator mit = modes.begin(), mit_end = modes.end(); mit != mit_end; ++mit)
- if (!u2->HasMode(*mit))
+ {
+ for (const auto &mode : modes)
+ {
+ if (!u2->HasMode(mode))
continue;
+ }
+ }
}
ListFormatter::ListEntry entry;
@@ -229,14 +241,14 @@ class CommandOSUserList : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of users list. \002%u\002 users shown."), count);
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -260,12 +272,13 @@ class CommandOSUserList : public Command
}
};
-class OSList : public Module
+class OSList final
+ : public Module
{
CommandOSChanList commandoschanlist;
CommandOSUserList commandosuserlist;
- public:
+public:
OSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandoschanlist(this), commandosuserlist(this)
{
diff --git a/modules/commands/os_login.cpp b/modules/operserv/os_login.cpp
index bf0b6b6fb..184d643d6 100644
--- a/modules/commands/os_login.cpp
+++ b/modules/operserv/os_login.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSLogin : public Command
+class CommandOSLogin final
+ : public Command
{
- public:
+public:
CommandOSLogin(Module *creator) : Command(creator, "operserv/login", 1, 1)
{
this->SetSyntax(_("\037password\037"));
this->RequireUser(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &password = params[0];
@@ -45,7 +46,7 @@ class CommandOSLogin : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -55,21 +56,22 @@ class CommandOSLogin : public Command
return true;
}
- const Anope::string GetDesc(CommandSource &source) const anope_override
+ const Anope::string GetDesc(CommandSource &source) const override
{
return Anope::printf(Language::Translate(source.GetAccount(), _("Login to %s")), source.service->nick.c_str());
}
};
-class CommandOSLogout : public Command
+class CommandOSLogout final
+ : public Command
{
- public:
+public:
CommandOSLogout(Module *creator) : Command(creator, "operserv/logout", 0, 0)
{
this->RequireUser(true);
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
User *u = source.GetUser();
Oper *o = source.nc->o;
@@ -87,7 +89,7 @@ class CommandOSLogout : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -97,26 +99,27 @@ class CommandOSLogout : public Command
return true;
}
- const Anope::string GetDesc(CommandSource &source) const anope_override
+ const Anope::string GetDesc(CommandSource &source) const override
{
return Anope::printf(Language::Translate(source.GetAccount(), _("Logout from %s")), source.service->nick.c_str());
}
};
-class OSLogin : public Module
+class OSLogin final
+ : public Module
{
CommandOSLogin commandoslogin;
CommandOSLogout commandoslogout;
ExtensibleItem<bool> os_login;
- public:
+public:
OSLogin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandoslogin(this), commandoslogout(this), os_login(this, "os_login")
{
}
- EventReturn IsServicesOper(User *u) anope_override
+ EventReturn IsServicesOper(User *u) override
{
if (!u->Account()->o->password.empty())
{
diff --git a/modules/commands/os_logsearch.cpp b/modules/operserv/os_logsearch.cpp
index 99604233a..f4f6b9210 100644
--- a/modules/commands/os_logsearch.cpp
+++ b/modules/operserv/os_logsearch.cpp
@@ -13,7 +13,8 @@
static unsigned int HARDMAX = 65536;
-class CommandOSLogSearch : public Command
+class CommandOSLogSearch final
+ : public Command
{
static inline Anope::string CreateLogName(const Anope::string &file, time_t t = Anope::CurTime)
{
@@ -23,17 +24,17 @@ class CommandOSLogSearch : public Command
strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
- return Anope::LogDir + "/" + file + "." + timestamp;
+ return Anope::ExpandLog(file + "." + timestamp);
}
- public:
+public:
CommandOSLogSearch(Module *creator) : Command(creator, "operserv/logsearch", 1, 3)
{
this->SetDesc(_("Searches logs for a matching pattern"));
this->SetSyntax(_("[+\037days\037d] [+\037limit\037l] \037pattern\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
int days = 7, replies = 50;
@@ -46,32 +47,22 @@ class CommandOSLogSearch : public Command
if (params[i].length() > 2)
{
Anope::string dur = params[i].substr(1, params[i].length() - 2);
- try
- {
- days = convertTo<int>(dur);
- if (days <= 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
- {
+ auto d = Anope::Convert<int>(dur, 0);
+ if (d > 0)
+ days = d;
+ else
source.Reply(_("Invalid duration %s, using %d days."), dur.c_str(), days);
- }
}
break;
case 'l':
if (params[i].length() > 2)
{
Anope::string dur = params[i].substr(1, params[i].length() - 2);
- try
- {
- replies = convertTo<int>(dur);
- if (replies <= 0)
- throw ConvertException();
- }
- catch (const ConvertException &)
- {
+ auto r = Anope::Convert<int>(dur, 0);
+ if (r > 0)
+ replies = r;
+ else
source.Reply(_("Invalid limit %s, using %d."), dur.c_str(), replies);
- }
}
break;
default:
@@ -92,7 +83,7 @@ class CommandOSLogSearch : public Command
Log(LOG_ADMIN, source, this) << "for " << search_string;
bool wildcard = search_string.find_first_of("?*") != Anope::string::npos;
- bool regex = search_string.empty() == false && search_string[0] == '/' && search_string[search_string.length() - 1] == '/';
+ bool regex = !search_string.empty() && search_string[0] == '/' && search_string[search_string.length() - 1] == '/';
const Anope::string &logfile_name = Config->GetModule(this->owner)->Get<const Anope::string>("logname");
std::vector<Anope::string> matches;
@@ -127,7 +118,7 @@ class CommandOSLogSearch : public Command
fd.close();
}
- unsigned int found = matches.size();
+ size_t found = matches.size();
if (!found)
{
source.Reply(_("No matches for \002%s\002 found."), search_string.c_str());
@@ -146,17 +137,17 @@ class CommandOSLogSearch : public Command
}
source.Reply(_("Matches for \002%s\002:"), search_string.c_str());
- unsigned int count = 0;
- for (std::vector<Anope::string>::iterator it = matches.begin(), it_end = matches.end(); it != it_end; ++it)
- source.Reply("#%d: %s", ++count, it->c_str());
- source.Reply(_("Showed %d/%d matches for \002%s\002."), matches.size(), found, search_string.c_str());
+ size_t count = 0;
+ for (const auto &match : matches)
+ source.Reply("#%zu: %s", ++count, match.c_str());
+ source.Reply(_("Showed %zu/%zu matches for \002%s\002."), matches.size(), found, search_string.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("This command searches the Services logfiles for messages\n"
+ source.Reply(_("This command searches the services logfiles for messages\n"
"that match the given pattern. The day and limit argument\n"
"may be used to specify how many days of logs to search\n"
"and the number of replies to limit to. By default this\n"
@@ -171,11 +162,12 @@ class CommandOSLogSearch : public Command
}
};
-class OSLogSearch : public Module
+class OSLogSearch final
+ : public Module
{
CommandOSLogSearch commandoslogsearch;
- public:
+public:
OSLogSearch(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandoslogsearch(this)
{
diff --git a/modules/commands/os_mode.cpp b/modules/operserv/os_mode.cpp
index 50bdea3b3..3a6b2159e 100644
--- a/modules/commands/os_mode.cpp
+++ b/modules/operserv/os_mode.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandOSMode : public Command
+class CommandOSMode final
+ : public Command
{
- public:
+public:
CommandOSMode(Module *creator) : Command(creator, "operserv/mode", 2, 3)
{
this->SetDesc(_("Change channel modes"));
@@ -21,7 +22,7 @@ class CommandOSMode : public Command
this->SetSyntax(_("\037channel\037 CLEAR [ALL]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &target = params[0];
const Anope::string &modes = params[1];
@@ -35,9 +36,8 @@ class CommandOSMode : public Command
{
bool all = params.size() > 2 && params[2].equals_ci("ALL");
- const Channel::ModeList chmodes = c->GetModes();
- for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end && c; ++it)
- c->RemoveMode(c->WhoSends(), it->first, it->second, false);
+ for (const auto &[mode, value] : c->GetModes())
+ c->RemoveMode(c->WhoSends(), mode, value, false);
if (!c)
{
@@ -47,10 +47,8 @@ class CommandOSMode : public Command
if (all)
{
- for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : c->users)
{
- ChanUserContainer *uc = it->second;
-
if (uc->user->HasMode("OPER"))
continue;
@@ -126,7 +124,7 @@ class CommandOSMode : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -138,16 +136,17 @@ class CommandOSMode : public Command
}
};
-class CommandOSUMode : public Command
+class CommandOSUMode final
+ : public Command
{
- public:
+public:
CommandOSUMode(Module *creator) : Command(creator, "operserv/umode", 2, 2)
{
this->SetDesc(_("Change user modes"));
this->SetSyntax(_("\037user\037 \037modes\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &target = params[0];
const Anope::string &modes = params[1];
@@ -157,7 +156,7 @@ class CommandOSUMode : public Command
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
else
{
- u2->SetModes(source.service, "%s", modes.c_str());
+ u2->SetModes(source.service, modes);
source.Reply(_("Changed usermodes of \002%s\002 to %s."), u2->nick.c_str(), modes.c_str());
u2->SendMessage(source.service, _("\002%s\002 changed your usermodes to %s."), source.GetNick().c_str(), modes.c_str());
@@ -166,7 +165,7 @@ class CommandOSUMode : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -176,12 +175,13 @@ class CommandOSUMode : public Command
}
};
-class OSMode : public Module
+class OSMode final
+ : public Module
{
CommandOSMode commandosmode;
CommandOSUMode commandosumode;
- public:
+public:
OSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosmode(this), commandosumode(this)
{
diff --git a/modules/commands/os_modinfo.cpp b/modules/operserv/os_modinfo.cpp
index 6e76eb5ab..58ab596f3 100644
--- a/modules/commands/os_modinfo.cpp
+++ b/modules/operserv/os_modinfo.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSModInfo : public Command
+class CommandOSModInfo final
+ : public Command
{
- public:
+public:
CommandOSModInfo(Module *creator) : Command(creator, "operserv/modinfo", 1, 1)
{
this->SetDesc(_("Info about a loaded module"));
this->SetSyntax(_("\037modname\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &file = params[0];
@@ -34,22 +35,18 @@ class CommandOSModInfo : public Command
source.Reply(_(" Loaded at: %p"), m->handle);
std::vector<Anope::string> servicekeys = Service::GetServiceKeys("Command");
- for (unsigned i = 0; i < servicekeys.size(); ++i)
+ for (const auto &servicekey : servicekeys)
{
- ServiceReference<Command> c("Command", servicekeys[i]);
+ ServiceReference<Command> c("Command", servicekey);
if (!c || c->owner != m)
continue;
source.Reply(_(" Providing service: \002%s\002"), c->name.c_str());
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ for (const auto &[_, bi] : *BotListByNick)
{
- const BotInfo *bi = it->second;
-
- for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit)
+ for (const auto &[c_name, info] : bi->commands)
{
- const Anope::string &c_name = cit->first;
- const CommandInfo &info = cit->second;
if (info.name != c->name)
continue;
source.Reply(_(" Command \002%s\002 on \002%s\002 is linked to \002%s\002"), c_name.c_str(), bi->nick.c_str(), c->name.c_str());
@@ -63,7 +60,7 @@ class CommandOSModInfo : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -72,16 +69,17 @@ class CommandOSModInfo : public Command
}
};
-class CommandOSModList : public Command
+class CommandOSModList final
+ : public Command
{
- public:
+public:
CommandOSModList(Module *creator) : Command(creator, "operserv/modlist", 0, 1)
{
this->SetDesc(_("List loaded modules"));
this->SetSyntax("[all|third|vendor|extra|database|encryption|pseudoclient|protocol]");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &param = !params.empty() ? params[0] : "";
@@ -116,10 +114,8 @@ class CommandOSModList : public Command
source.Reply(_("Current module list:"));
int count = 0;
- for (std::list<Module *>::iterator it = ModuleManager::Modules.begin(), it_end = ModuleManager::Modules.end(); it != it_end; ++it)
+ for (auto *m : ModuleManager::Modules)
{
- Module *m = *it;
-
bool show = false;
Anope::string mtype;
@@ -189,7 +185,7 @@ class CommandOSModList : public Command
source.Reply(_("%d modules loaded."), count);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -198,12 +194,13 @@ class CommandOSModList : public Command
}
};
-class OSModInfo : public Module
+class OSModInfo final
+ : public Module
{
CommandOSModInfo commandosmodinfo;
CommandOSModList commandosmodlist;
- public:
+public:
OSModInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosmodinfo(this), commandosmodlist(this)
{
diff --git a/modules/commands/os_module.cpp b/modules/operserv/os_module.cpp
index e5ad209ba..2a54d9a67 100644
--- a/modules/commands/os_module.cpp
+++ b/modules/operserv/os_module.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSModLoad : public Command
+class CommandOSModLoad final
+ : public Command
{
- public:
+public:
CommandOSModLoad(Module *creator) : Command(creator, "operserv/modload", 1, 1)
{
this->SetDesc(_("Load a module"));
this->SetSyntax(_("\037modname\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &mname = params[0];
@@ -38,7 +39,7 @@ class CommandOSModLoad : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -48,16 +49,17 @@ class CommandOSModLoad : public Command
}
};
-class CommandOSModReLoad : public Command
+class CommandOSModReLoad final
+ : public Command
{
- public:
+public:
CommandOSModReLoad(Module *creator) : Command(creator, "operserv/modreload", 1, 1)
{
this->SetDesc(_("Reload a module"));
this->SetSyntax(_("\037modname\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &mname = params[0];
@@ -111,7 +113,7 @@ class CommandOSModReLoad : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -120,16 +122,17 @@ class CommandOSModReLoad : public Command
}
};
-class CommandOSModUnLoad : public Command
+class CommandOSModUnLoad final
+ : public Command
{
- public:
+public:
CommandOSModUnLoad(Module *creator) : Command(creator, "operserv/modunload", 1, 1)
{
this->SetDesc(_("Un-Load a module"));
this->SetSyntax(_("\037modname\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &mname = params[0];
@@ -161,7 +164,7 @@ class CommandOSModUnLoad : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -170,13 +173,14 @@ class CommandOSModUnLoad : public Command
}
};
-class OSModule : public Module
+class OSModule final
+ : public Module
{
CommandOSModLoad commandosmodload;
CommandOSModReLoad commandosmodreload;
CommandOSModUnLoad commandosmodunload;
- public:
+public:
OSModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosmodload(this), commandosmodreload(this), commandosmodunload(this)
{
diff --git a/modules/commands/os_news.cpp b/modules/operserv/os_news.cpp
index 38df7a660..ba6fe37bf 100644
--- a/modules/commands/os_news.cpp
+++ b/modules/operserv/os_news.cpp
@@ -12,6 +12,11 @@
#include "module.h"
#include "modules/os_news.h"
+// TODO: msgarray breaks the format string checking
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wformat-security"
+#endif
+
/* List of messages for each news type. This simplifies message sending. */
enum
@@ -59,17 +64,18 @@ struct NewsMessages msgarray[] = {
}
};
-struct MyNewsItem : NewsItem
+struct MyNewsItem final
+ : NewsItem
{
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["type"] << this->type;
- data["text"] << this->text;
- data["who"] << this->who;
- data["time"] << this->time;
+ data.Store("type", this->type);
+ data.Store("text", this->text);
+ data.Store("who", this->who);
+ data.Store("time", this->time);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
if (!news_service)
return NULL;
@@ -93,30 +99,33 @@ struct MyNewsItem : NewsItem
}
};
-class MyNewsService : public NewsService
+class MyNewsService final
+ : public NewsService
{
std::vector<NewsItem *> newsItems[3];
- public:
+public:
MyNewsService(Module *m) : NewsService(m) { }
- ~MyNewsService()
+ ~MyNewsService() override
{
- for (unsigned i = 0; i < 3; ++i)
- for (unsigned j = 0; j < newsItems[i].size(); ++j)
- delete newsItems[i][j];
+ for (const auto &newstype : newsItems)
+ {
+ for (const auto *newsitem : newstype)
+ delete newsitem;
+ }
}
- NewsItem *CreateNewsItem() anope_override
+ NewsItem *CreateNewsItem() override
{
return new MyNewsItem();
}
- void AddNewsItem(NewsItem *n) anope_override
+ void AddNewsItem(NewsItem *n) override
{
this->newsItems[n->type].push_back(n);
}
- void DelNewsItem(NewsItem *n) anope_override
+ void DelNewsItem(NewsItem *n) override
{
std::vector<NewsItem *> &list = this->GetNewsList(n->type);
std::vector<NewsItem *>::iterator it = std::find(list.begin(), list.end(), n);
@@ -125,7 +134,7 @@ class MyNewsService : public NewsService
delete n;
}
- std::vector<NewsItem *> &GetNewsList(NewsType t) anope_override
+ std::vector<NewsItem *> &GetNewsList(NewsType t) override
{
return this->newsItems[t];
}
@@ -134,17 +143,18 @@ class MyNewsService : public NewsService
#define lenof(a) (sizeof(a) / sizeof(*(a)))
static const char **findmsgs(NewsType type)
{
- for (unsigned i = 0; i < lenof(msgarray); ++i)
- if (msgarray[i].type == type)
- return msgarray[i].msgs;
+ for (auto &msg : msgarray)
+ if (msg.type == type)
+ return msg.msgs;
return NULL;
}
-class NewsBase : public Command
+class NewsBase
+ : public Command
{
ServiceReference<NewsService> ns;
- protected:
+protected:
void DoList(CommandSource &source, NewsType ntype, const char **msgs)
{
std::vector<NewsItem *> &list = this->ns->GetNewsList(ntype);
@@ -158,7 +168,7 @@ class NewsBase : public Command
for (unsigned i = 0, end = list.size(); i < end; ++i)
{
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Creator"] = list[i]->who;
entry["Created"] = Anope::strftime(list[i]->time, NULL, true);
entry["Text"] = list[i]->text;
@@ -170,8 +180,8 @@ class NewsBase : public Command
std::vector<Anope::string> replies;
lflist.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
source.Reply(_("End of news list."));
}
@@ -222,18 +232,14 @@ class NewsBase : public Command
source.Reply(READ_ONLY_MODE);
if (!text.equals_ci("ALL"))
{
- try
+ unsigned num = Anope::Convert<unsigned>(text, 0);
+ if (num > 0 && num <= list.size())
{
- unsigned num = convertTo<unsigned>(text);
- if (num > 0 && num <= list.size())
- {
- this->ns->DelNewsItem(list[num - 1]);
- source.Reply(msgs[MSG_DELETED], num);
- Log(LOG_ADMIN, source, this) << "to delete a news item";
- return;
- }
+ this->ns->DelNewsItem(list[num - 1]);
+ source.Reply(msgs[MSG_DELETED], num);
+ Log(LOG_ADMIN, source, this) << "to delete a news item";
+ return;
}
- catch (const ConvertException &) { }
source.Reply(msgs[MSG_DEL_NOT_FOUND], text.c_str());
}
@@ -272,7 +278,7 @@ class NewsBase : public Command
return;
}
- public:
+public:
NewsBase(Module *creator, const Anope::string &newstype) : Command(creator, newstype, 1, 2), ns("NewsService", "news")
{
this->SetSyntax(_("ADD \037text\037"));
@@ -280,29 +286,30 @@ class NewsBase : public Command
this->SetSyntax("LIST");
}
- virtual ~NewsBase()
+ ~NewsBase() override
{
}
- virtual void Execute(CommandSource &source, const std::vector<Anope::string> &params) = 0;
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override = 0;
- virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0;
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override = 0;
};
-class CommandOSLogonNews : public NewsBase
+class CommandOSLogonNews final
+ : public NewsBase
{
- public:
+public:
CommandOSLogonNews(Module *creator) : NewsBase(creator, "operserv/logonnews")
{
this->SetDesc(_("Define messages to be shown to users at logon"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
return this->DoNews(source, params, NEWS_LOGON);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -316,20 +323,21 @@ class CommandOSLogonNews : public NewsBase
}
};
-class CommandOSOperNews : public NewsBase
+class CommandOSOperNews final
+ : public NewsBase
{
- public:
+public:
CommandOSOperNews(Module *creator) : NewsBase(creator, "operserv/opernews")
{
this->SetDesc(_("Define messages to be shown to users who oper"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
return this->DoNews(source, params, NEWS_OPER);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -343,20 +351,21 @@ class CommandOSOperNews : public NewsBase
}
};
-class CommandOSRandomNews : public NewsBase
+class CommandOSRandomNews final
+ : public NewsBase
{
- public:
+public:
CommandOSRandomNews(Module *creator) : NewsBase(creator, "operserv/randomnews")
{
this->SetDesc(_("Define messages to be randomly shown to users at logon"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
return this->DoNews(source, params, NEWS_RANDOM);
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -369,7 +378,8 @@ class CommandOSRandomNews : public NewsBase
static unsigned cur_rand_news = 0;
-class OSNews : public Module
+class OSNews final
+ : public Module
{
MyNewsService newsservice;
Serialize::Type newsitem_type;
@@ -431,27 +441,27 @@ class OSNews : public Module
cur_rand_news = 0;
}
- public:
+public:
OSNews(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
newsservice(this), newsitem_type("NewsItem", MyNewsItem::Unserialize),
commandoslogonnews(this), commandosopernews(this), commandosrandomnews(this)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
oper_announcer = conf->GetModule(this)->Get<const Anope::string>("oper_announcer", "OperServ");
announcer = conf->GetModule(this)->Get<const Anope::string>("announcer", "Global");
news_count = conf->GetModule(this)->Get<unsigned>("newscount", "3");
}
- void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override
+ void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override
{
if (mname == "OPER")
DisplayNews(u, NEWS_OPER);
}
- void OnUserConnect(User *user, bool &) anope_override
+ void OnUserConnect(User *user, bool &) override
{
if (user->Quitting() || !user->server->IsSynced())
return;
diff --git a/modules/commands/os_noop.cpp b/modules/operserv/os_noop.cpp
index ce8423deb..6e4b412fd 100644
--- a/modules/commands/os_noop.cpp
+++ b/modules/operserv/os_noop.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandOSNOOP : public Command
+class CommandOSNOOP final
+ : public Command
{
- public:
+public:
CommandOSNOOP(Module *creator) : Command(creator, "operserv/noop", 2, 2)
{
this->SetDesc(_("Remove all operators from a server remotely"));
@@ -21,7 +22,7 @@ class CommandOSNOOP : public Command
this->SetSyntax(_("REVOKE \037server\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
const Anope::string &server = params[1];
@@ -30,7 +31,7 @@ class CommandOSNOOP : public Command
if (s == NULL)
source.Reply(_("Server %s does not exist."), server.c_str());
else if (s == Me || s->IsJuped())
- source.Reply(_("You can not NOOP Services."));
+ source.Reply(_("You can not NOOP services."));
else if (cmd.equals_ci("SET"))
{
/* Remove the O:lines */
@@ -42,10 +43,8 @@ class CommandOSNOOP : public Command
Anope::string reason = "NOOP command used by " + source.GetNick();
/* Kill all the IRCops of the server */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u2] : UserListByNick)
{
- User *u2 = it->second;
-
if (u2->server == s && u2->HasMode("OPER"))
u2->Kill(*source.service, reason);
}
@@ -61,7 +60,7 @@ class CommandOSNOOP : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -73,19 +72,21 @@ class CommandOSNOOP : public Command
}
};
-class OSNOOP : public Module
+class OSNOOP final
+ : public Module
{
CommandOSNOOP commandosnoop;
PrimitiveExtensibleItem<Anope::string> noop;
- public:
+public:
OSNOOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosnoop(this), noop(this, "noop")
{
-
+ if (!IRCD || !IRCD->CanSVSNOOP)
+ throw ModuleException("Your IRCd does not support SVSNOOP.");
}
- void OnUserModeSet(const MessageSource &, User *u, const Anope::string &mname) anope_override
+ void OnUserModeSet(const MessageSource &, User *u, const Anope::string &mname) override
{
Anope::string *setter;
if (mname == "OPER" && (setter = noop.Get(u->server)))
diff --git a/modules/commands/os_oper.cpp b/modules/operserv/os_oper.cpp
index 300372eb1..674de100a 100644
--- a/modules/commands/os_oper.cpp
+++ b/modules/operserv/os_oper.cpp
@@ -10,60 +10,29 @@
*/
#include "module.h"
+#include "modules/os_oper.h"
-struct MyOper : Oper, Serializable
+class CommandOSOper final
+ : public Command
{
- MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
-
- void Serialize(Serialize::Data &data) const anope_override
- {
- data["name"] << this->name;
- data["type"] << this->ot->GetName();
- }
-
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
- {
- Anope::string stype, sname;
-
- data["type"] >> stype;
- data["name"] >> sname;
-
- OperType *ot = OperType::Find(stype);
- if (ot == NULL)
- return NULL;
- NickCore *nc = NickCore::Find(sname);
- if (nc == NULL)
- return NULL;
-
- MyOper *myo;
- if (obj)
- myo = anope_dynamic_static_cast<MyOper *>(obj);
- else
- myo = new MyOper(nc->display, ot);
- nc->o = myo;
- Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
- return myo;
- }
-};
-
-class CommandOSOper : public Command
-{
- bool HasPrivs(CommandSource &source, OperType *ot) const
+ static bool HasPrivs(CommandSource &source, OperType *ot)
{
- std::list<Anope::string> commands = ot->GetCommands(), privs = ot->GetPrivs();
-
- for (std::list<Anope::string>::iterator it = commands.begin(); it != commands.end(); ++it)
- if (!source.HasCommand(*it))
+ for (const auto &command : ot->GetCommands())
+ {
+ if (!source.HasCommand(command))
return false;
+ }
- for (std::list<Anope::string>::iterator it = privs.begin(); it != privs.end(); ++it)
- if (!source.HasPriv(*it))
+ for (const auto &priv : ot->GetPrivs())
+ {
+ if (!source.HasPriv(priv))
return false;
+ }
return true;
}
- public:
+public:
CommandOSOper(Module *creator) : Command(creator, "operserv/oper", 1, 3)
{
this->SetDesc(_("View and change Services Operators"));
@@ -73,7 +42,7 @@ class CommandOSOper : public Command
this->SetSyntax("LIST");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &subcommand = params[0];
@@ -151,20 +120,17 @@ class CommandOSOper : public Command
else if (subcommand.equals_ci("LIST"))
{
source.Reply(_("Name Type"));
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- const NickCore *nc = it->second;
-
if (!nc->o)
continue;
source.Reply(_("%-8s %s"), nc->o->name.c_str(), nc->o->ot->GetName().c_str());
if (std::find(Config->Opers.begin(), Config->Opers.end(), nc->o) != Config->Opers.end())
source.Reply(_(" This oper is configured in the configuration file."));
- for (std::list<User *>::const_iterator uit = nc->users.begin(); uit != nc->users.end(); ++uit)
+ for (auto *u : nc->users)
{
- User *u = *uit;
- source.Reply(_(" %s is online using this oper block."), u->nick.c_str());
+ source.Reply(_(" %s is online using this oper block."), u->nick.c_str());
}
}
}
@@ -173,9 +139,8 @@ class CommandOSOper : public Command
if (params.size() < 2)
{
source.Reply(_("Available opertypes:"));
- for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i)
+ for (auto *ot : Config->MyOperTypes)
{
- OperType *ot = Config->MyOperTypes[i];
source.Reply("%s", ot->GetName().c_str());
}
return;
@@ -196,9 +161,9 @@ class CommandOSOper : public Command
source.Reply(_("Available commands for \002%s\002:"), ot->GetName().c_str());
Anope::string buf;
std::list<Anope::string> cmds = ot->GetCommands();
- for (std::list<Anope::string>::const_iterator it = cmds.begin(), it_end = cmds.end(); it != it_end; ++it)
+ for (const auto &cmd : cmds)
{
- buf += *it + " ";
+ buf += cmd + " ";
if (buf.length() > 400)
{
source.Reply("%s", buf.c_str());
@@ -218,9 +183,9 @@ class CommandOSOper : public Command
source.Reply(_("Available privileges for \002%s\002:"), ot->GetName().c_str());
Anope::string buf;
std::list<Anope::string> privs = ot->GetPrivs();
- for (std::list<Anope::string>::const_iterator it = privs.begin(), it_end = privs.end(); it != it_end; ++it)
+ for (const auto &priv : privs)
{
- buf += *it + " ";
+ buf += priv + " ";
if (buf.length() > 400)
{
source.Reply("%s", buf.c_str());
@@ -243,7 +208,7 @@ class CommandOSOper : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -254,23 +219,22 @@ class CommandOSOper : public Command
}
};
-class OSOper : public Module
+class OSOper final
+ : public Module
{
Serialize::Type myoper_type;
CommandOSOper commandosoper;
- public:
+public:
OSOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
myoper_type("Oper", MyOper::Unserialize), commandosoper(this)
{
}
- ~OSOper()
+ ~OSOper() override
{
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- NickCore *nc = it->second;
-
if (nc->o && dynamic_cast<MyOper *>(nc->o))
{
delete nc->o;
@@ -279,7 +243,7 @@ class OSOper : public Module
}
}
- void OnDelCore(NickCore *nc) anope_override
+ void OnDelCore(NickCore *nc) override
{
if (nc->o && dynamic_cast<MyOper *>(nc->o))
{
diff --git a/modules/commands/os_reload.cpp b/modules/operserv/os_reload.cpp
index 3b43a4926..88bcead7c 100644
--- a/modules/commands/os_reload.cpp
+++ b/modules/operserv/os_reload.cpp
@@ -11,21 +11,22 @@
#include "module.h"
-class CommandOSReload : public Command
+class CommandOSReload final
+ : public Command
{
- public:
+public:
CommandOSReload(Module *creator) : Command(creator, "operserv/reload", 0, 0)
{
this->SetDesc(_("Reload services' configuration file"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
try
{
Log(LOG_ADMIN, source, this);
- Configuration::Conf *new_config = new Configuration::Conf();
+ auto *new_config = new Configuration::Conf();
Configuration::Conf *old = Config;
Config = new_config;
Config->Post(old);
@@ -40,23 +41,24 @@ class CommandOSReload : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Causes Services to reload the configuration file. Note that\n"
- "some directives still need the restart of the Services to\n"
- "take effect (such as Services' nicknames, activation of the\n"
+ source.Reply(_("Causes services to reload the configuration file. Note that\n"
+ "some directives still need the restart of the services to\n"
+ "take effect (such as services' nicknames, activation of the\n"
"session limitation, etc.)."));
return true;
}
};
-class OSReload : public Module
+class OSReload final
+ : public Module
{
CommandOSReload commandosreload;
- public:
+public:
OSReload(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosreload(this)
{
diff --git a/modules/commands/os_session.cpp b/modules/operserv/os_session.cpp
index 9167bc3ea..5e2399d53 100644
--- a/modules/commands/os_session.cpp
+++ b/modules/operserv/os_session.cpp
@@ -35,35 +35,35 @@ namespace
unsigned ipv6_cidr;
}
-class MySessionService : public SessionService
+class MySessionService final
+ : public SessionService
{
SessionMap Sessions;
Serialize::Checker<ExceptionVector> Exceptions;
- public:
+public:
MySessionService(Module *m) : SessionService(m), Exceptions("Exception") { }
- Exception *CreateException() anope_override
+ Exception *CreateException() override
{
return new Exception();
}
- void AddException(Exception *e) anope_override
+ void AddException(Exception *e) override
{
this->Exceptions->push_back(e);
}
- void DelException(Exception *e) anope_override
+ void DelException(Exception *e) override
{
ExceptionVector::iterator it = std::find(this->Exceptions->begin(), this->Exceptions->end(), e);
if (it != this->Exceptions->end())
this->Exceptions->erase(it);
}
- Exception *FindException(User *u) anope_override
+ Exception *FindException(User *u) override
{
- for (std::vector<Exception *>::const_iterator it = this->Exceptions->begin(), it_end = this->Exceptions->end(); it != it_end; ++it)
+ for (auto *e : *this->Exceptions)
{
- Exception *e = *it;
if (Anope::Match(u->host, e->mask) || Anope::Match(u->ip.addr(), e->mask))
return e;
@@ -73,11 +73,10 @@ class MySessionService : public SessionService
return NULL;
}
- Exception *FindException(const Anope::string &host) anope_override
+ Exception *FindException(const Anope::string &host) override
{
- for (std::vector<Exception *>::const_iterator it = this->Exceptions->begin(), it_end = this->Exceptions->end(); it != it_end; ++it)
+ for (auto *e : *this->Exceptions)
{
- Exception *e = *it;
if (Anope::Match(host, e->mask))
return e;
@@ -88,7 +87,7 @@ class MySessionService : public SessionService
return NULL;
}
- ExceptionVector &GetExceptions() anope_override
+ ExceptionVector &GetExceptions() override
{
return this->Exceptions;
}
@@ -98,7 +97,7 @@ class MySessionService : public SessionService
this->Sessions.erase(s->addr);
}
- Session *FindSession(const Anope::string &ip) anope_override
+ Session *FindSession(const Anope::string &ip) override
{
cidr c(ip, ip.find(':') != Anope::string::npos ? ipv6_cidr : ipv4_cidr);
if (!c.valid())
@@ -117,29 +116,30 @@ class MySessionService : public SessionService
return this->Sessions.find(c);
}
- Session* &FindOrCreateSession(const cidr &ip)
+ Session *&FindOrCreateSession(const cidr &ip)
{
return this->Sessions[ip];
}
- SessionMap &GetSessions() anope_override
+ SessionMap &GetSessions() override
{
return this->Sessions;
}
};
-class ExceptionDelCallback : public NumberList
+class ExceptionDelCallback final
+ : public NumberList
{
- protected:
+protected:
CommandSource &source;
- unsigned deleted;
+ unsigned deleted = 0;
Command *cmd;
- public:
- ExceptionDelCallback(CommandSource &_source, const Anope::string &numlist, Command *c) : NumberList(numlist, true), source(_source), deleted(0), cmd(c)
+public:
+ ExceptionDelCallback(CommandSource &_source, const Anope::string &numlist, Command *c) : NumberList(numlist, true), source(_source), cmd(c)
{
}
- ~ExceptionDelCallback()
+ ~ExceptionDelCallback() override
{
if (!deleted)
source.Reply(_("No matching entries on session-limit exception list."));
@@ -149,7 +149,7 @@ class ExceptionDelCallback : public NumberList
source.Reply(_("Deleted %d entries from session-limit exception list."), deleted);
}
- virtual void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number || number > session_service->GetExceptions().size())
return;
@@ -170,20 +170,15 @@ class ExceptionDelCallback : public NumberList
}
};
-class CommandOSSession : public Command
+class CommandOSSession final
+ : public Command
{
- private:
- void DoList(CommandSource &source, const std::vector<Anope::string> &params)
+private:
+ static void DoList(CommandSource &source, const std::vector<Anope::string> &params)
{
Anope::string param = params[1];
- unsigned mincount = 0;
- try
- {
- mincount = convertTo<unsigned>(param);
- }
- catch (const ConvertException &) { }
-
+ auto mincount = Anope::Convert<unsigned>(param, 0);
if (mincount <= 1)
source.Reply(_("Invalid threshold value. It must be a valid integer greater than 1."));
else
@@ -191,14 +186,12 @@ class CommandOSSession : public Command
ListFormatter list(source.GetAccount());
list.AddColumn(_("Session")).AddColumn(_("Host"));
- for (SessionService::SessionMap::iterator it = session_service->GetSessions().begin(), it_end = session_service->GetSessions().end(); it != it_end; ++it)
+ for (const auto &[_, session] : session_service->GetSessions())
{
- Session *session = it->second;
-
if (session->count >= mincount)
{
ListFormatter::ListEntry entry;
- entry["Session"] = stringify(session->count);
+ entry["Session"] = Anope::ToString(session->count);
entry["Host"] = session->addr.mask();
list.AddEntry(entry);
}
@@ -210,14 +203,14 @@ class CommandOSSession : public Command
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
return;
}
- void DoView(CommandSource &source, const std::vector<Anope::string> &params)
+ static void DoView(CommandSource &source, const std::vector<Anope::string> &params)
{
Anope::string param = params[1];
Session *session = session_service->FindSession(param);
@@ -239,7 +232,7 @@ class CommandOSSession : public Command
else
source.Reply(_("The host \002%s\002 currently has \002%d\002 sessions with a limit of \002%d\002 because it matches entry: \002%s\002."), session->addr.mask().c_str(), session->count, limit, entry.c_str());
}
- public:
+public:
CommandOSSession(Module *creator) : Command(creator, "operserv/session", 2, 2)
{
this->SetDesc(_("View the list of host sessions"));
@@ -247,7 +240,7 @@ class CommandOSSession : public Command
this->SetSyntax(_("VIEW \037host\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
@@ -263,7 +256,7 @@ class CommandOSSession : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -285,9 +278,10 @@ class CommandOSSession : public Command
}
};
-class CommandOSException : public Command
+class CommandOSException final
+ : public Command
{
- private:
+private:
void DoAdd(CommandSource &source, const std::vector<Anope::string> &params)
{
Anope::string mask, expiry, limitstr;
@@ -327,13 +321,7 @@ class CommandOSException : public Command
else if (expires > 0)
expires += Anope::CurTime;
- unsigned limit = -1;
- try
- {
- limit = convertTo<unsigned>(limitstr);
- }
- catch (const ConvertException &) { }
-
+ auto limit = Anope::Convert<unsigned>(limitstr, -1);
if (limit > max_exception_limit)
{
source.Reply(_("Invalid session limit. It must be a valid integer greater than or equal to zero and less than \002%d\002."), max_exception_limit);
@@ -347,9 +335,8 @@ class CommandOSException : public Command
return;
}
- for (std::vector<Exception *>::iterator it = session_service->GetExceptions().begin(), it_end = session_service->GetExceptions().end(); it != it_end; ++it)
+ for (auto *e : session_service->GetExceptions())
{
- Exception *e = *it;
if (e->mask.equals_ci(mask))
{
if (e->limit != limit)
@@ -363,7 +350,7 @@ class CommandOSException : public Command
}
}
- Exception *exception = new Exception();
+ auto *exception = new Exception();
exception->mask = mask;
exception->limit = limit;
exception->reason = reason;
@@ -436,16 +423,17 @@ class CommandOSException : public Command
if (!mask.empty() && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class ExceptionListCallback : public NumberList
+ class ExceptionListCallback final
+ : public NumberList
{
CommandSource &source;
ListFormatter &list;
- public:
+ public:
ExceptionListCallback(CommandSource &_source, ListFormatter &_list, const Anope::string &numlist) : NumberList(numlist, false), source(_source), list(_list)
{
}
- void HandleNumber(unsigned Number) anope_override
+ void HandleNumber(unsigned Number) override
{
if (!Number || Number > session_service->GetExceptions().size())
return;
@@ -453,12 +441,12 @@ class CommandOSException : public Command
Exception *e = session_service->GetExceptions()[Number - 1];
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(Number);
+ entry["Number"] = Anope::ToString(Number);
entry["Mask"] = e->mask;
entry["By"] = e->who;
entry["Created"] = Anope::strftime(e->time, NULL, true);
entry["Expires"] = Anope::Expires(e->expires, source.GetAccount());
- entry["Limit"] = stringify(e->limit);
+ entry["Limit"] = Anope::ToString(e->limit);
entry["Reason"] = e->reason;
this->list.AddEntry(entry);
}
@@ -474,12 +462,12 @@ class CommandOSException : public Command
if (mask.empty() || Anope::Match(e->mask, mask))
{
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Mask"] = e->mask;
entry["By"] = e->who;
entry["Created"] = Anope::strftime(e->time, NULL, true);
entry["Expires"] = Anope::Expires(e->expires, source.GetAccount());
- entry["Limit"] = stringify(e->limit);
+ entry["Limit"] = Anope::ToString(e->limit);
entry["Reason"] = e->reason;
list.AddEntry(entry);
}
@@ -495,8 +483,8 @@ class CommandOSException : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
@@ -516,7 +504,7 @@ class CommandOSException : public Command
this->ProcessList(source, params, list);
}
- public:
+public:
CommandOSException(Module *creator) : Command(creator, "operserv/exception", 1, 5)
{
this->SetDesc(_("Modify the session-limit exception list"));
@@ -526,7 +514,7 @@ class CommandOSException : public Command
this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
@@ -544,7 +532,7 @@ class CommandOSException : public Command
this->OnSyntaxError(source, "");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -582,7 +570,8 @@ class CommandOSException : public Command
}
};
-class OSSession : public Module
+class OSSession final
+ : public Module
{
Serialize::Type exception_type;
MySessionService ss;
@@ -590,19 +579,19 @@ class OSSession : public Module
CommandOSException commandosexception;
ServiceReference<XLineManager> akills;
- public:
+public:
OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
exception_type("Exception", Exception::Unserialize), ss(this), commandossession(this), commandosexception(this), akills("XLineManager", "xlinemanager/sgline")
{
this->SetPermanent(true);
}
- void Prioritize() anope_override
+ void Prioritize() override
{
ModuleManager::SetPriority(this, PRIORITY_FIRST);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = Config->GetModule(this);
@@ -622,7 +611,7 @@ class OSSession : public Module
throw ConfigException(this->name + ": session CIDR value out of range");
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (u->Quitting() || !session_limit || exempt || !u->server || u->server->IsULined())
return;
@@ -631,7 +620,7 @@ class OSSession : public Module
if (!u_ip.valid())
return;
- Session* &session = this->ss.FindOrCreateSession(u_ip);
+ Session *&session = this->ss.FindOrCreateSession(u_ip);
if (session)
{
@@ -676,7 +665,7 @@ class OSSession : public Module
const Anope::string &akillmask = "*@" + session->addr.mask();
if (max_session_kill && session->hits >= max_session_kill && akills && !akills->HasEntry(akillmask))
{
- XLine *x = new XLine(akillmask, OperServ ? OperServ->nick : "", Anope::CurTime + session_autokill_expiry, "Session limit exceeded", XLineManager::GenerateUID());
+ auto *x = new XLine(akillmask, OperServ ? OperServ->nick : "", Anope::CurTime + session_autokill_expiry, "Session limit exceeded", XLineManager::GenerateUID());
akills->AddXLine(x);
akills->Send(NULL, x);
Log(OperServ, "akill/session") << "Added a temporary AKILL for \002" << akillmask << "\002 due to excessive connections";
@@ -693,7 +682,7 @@ class OSSession : public Module
}
}
- void OnUserQuit(User *u, const Anope::string &msg) anope_override
+ void OnUserQuit(User *u, const Anope::string &msg) override
{
if (!session_limit || !u->server || u->server->IsULined())
return;
@@ -716,7 +705,7 @@ class OSSession : public Module
sessions.erase(sit);
}
- void OnExpireTick() anope_override
+ void OnExpireTick() override
{
if (Anope::NoExpire)
return;
diff --git a/modules/commands/os_set.cpp b/modules/operserv/os_set.cpp
index 2f66f2136..d7f3fc711 100644
--- a/modules/commands/os_set.cpp
+++ b/modules/operserv/os_set.cpp
@@ -11,9 +11,10 @@
#include "module.h"
-class CommandOSSet : public Command
+class CommandOSSet final
+ : public Command
{
- private:
+private:
void DoList(CommandSource &source)
{
Log(LOG_ADMIN, source, this) << "LIST";
@@ -121,14 +122,14 @@ class CommandOSSet : public Command
}
else
{
- try
+ auto debug = Anope::TryConvert<int>(setting);
+ if (debug.has_value())
{
- Anope::Debug = convertTo<int>(setting);
+ Anope::Debug = debug.value();
Log(LOG_ADMIN, source, this) << "DEBUG " << Anope::Debug;
source.Reply(_("Services are now in \002debug\002 mode (level %d)."), Anope::Debug);
return;
}
- catch (const ConvertException &) { }
source.Reply(_("Setting for DEBUG must be \002ON\002, \002OFF\002, or a positive number."));
}
@@ -163,14 +164,14 @@ class CommandOSSet : public Command
return;
}
- public:
+public:
CommandOSSet(Module *creator) : Command(creator, "operserv/set", 1, 2)
{
- this->SetDesc(_("Set various global Services options"));
+ this->SetDesc(_("Set various global services options"));
this->SetSyntax(_("\037option\037 \037setting\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &option = params[0];
@@ -190,13 +191,13 @@ class CommandOSSet : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
if (subcommand.empty())
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Sets various global Services options. Option names\n"
+ source.Reply(_("Sets various global services options. Option names\n"
"currently defined are:\n"
" READONLY Set read-only or read-write mode\n"
" DEBUG Activate or deactivate debug mode\n"
@@ -212,13 +213,13 @@ class CommandOSSet : public Command
source.Reply(_("Syntax: \002READONLY {ON | OFF}\002\n"
" \n"
"Sets read-only mode on or off. In read-only mode, normal\n"
- "users will not be allowed to modify any Services data,\n"
- "including channel and nickname access lists, etc. IRCops\n"
- "with sufficient Services privileges will be able to modify\n"
+ "users will not be allowed to modify any services data,\n"
+ "including channel access lists, etc. Server operators\n"
+ "with sufficient services privileges will be able to modify\n"
"Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n"
"suspend or forbid nicknames and channels, and manage news,\n"
"oper info and DNS, but any such changes will not be saved\n"
- "unless read-only mode is deactivated before Services are\n"
+ "unless read-only mode is deactivated before services are\n"
"terminated or restarted.\n"
" \n"
"This option is equivalent to the command-line option\n"
@@ -253,11 +254,12 @@ class CommandOSSet : public Command
}
};
-class OSSet : public Module
+class OSSet final
+ : public Module
{
CommandOSSet commandosset;
- public:
+public:
OSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosset(this)
{
diff --git a/modules/commands/os_shutdown.cpp b/modules/operserv/os_shutdown.cpp
index 6667d1373..5ebdb2200 100644
--- a/modules/commands/os_shutdown.cpp
+++ b/modules/operserv/os_shutdown.cpp
@@ -11,27 +11,38 @@
#include "module.h"
-class CommandOSQuit : public Command
+class CommandOSQuit final
+ : public Command
{
- public:
- CommandOSQuit(Module *creator) : Command(creator, "operserv/quit", 0, 0)
+public:
+ CommandOSQuit(Module *creator) : Command(creator, "operserv/quit", 0, 1)
{
- this->SetDesc(_("Terminate Services WITHOUT saving"));
+ this->SetDesc(_("Terminate services WITHOUT saving"));
+ if (Config->GetModule(this->owner)->Get<bool>("requirename"))
+ this->SetSyntax(_("\037network-name\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
+ const auto requirename = Config->GetModule(this->owner)->Get<bool>("requirename");
+ const auto networkname = Config->GetBlock("networkinfo")->Get<Anope::string>("networkname");
+ if (requirename && (params.empty() || !params[0].equals_cs(networkname)))
+ {
+ OnSyntaxError(source, source.command);
+ return;
+ }
+
Log(LOG_ADMIN, source, this);
Anope::QuitReason = source.command + " command received from " + source.GetNick();
Anope::Quitting = true;
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Causes Services to do an immediate shutdown; databases are\n"
+ source.Reply(_("Causes services to do an immediate shutdown; databases are\n"
"\002not\002 saved. This command should not be used unless\n"
"damage to the in-memory copies of the databases is feared\n"
"and they should not be saved."));
@@ -39,16 +50,27 @@ class CommandOSQuit : public Command
}
};
-class CommandOSRestart : public Command
+class CommandOSRestart final
+ : public Command
{
- public:
- CommandOSRestart(Module *creator) : Command(creator, "operserv/restart", 0, 0)
+public:
+ CommandOSRestart(Module *creator) : Command(creator, "operserv/restart", 0, 1)
{
- this->SetDesc(_("Save databases and restart Services"));
+ this->SetDesc(_("Save databases and restart services"));
+ if (Config->GetModule(this->owner)->Get<bool>("requirename"))
+ this->SetSyntax(_("\037network-name\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
+ const auto requirename = Config->GetModule(this->owner)->Get<bool>("requirename");
+ const auto networkname = Config->GetBlock("networkinfo")->Get<Anope::string>("networkname");
+ if (requirename && (params.empty() || !params[0].equals_cs(networkname)))
+ {
+ OnSyntaxError(source, source.command);
+ return;
+ }
+
Log(LOG_ADMIN, source, this);
Anope::QuitReason = source.command + " command received from " + source.GetNick();
Anope::Quitting = Anope::Restarting = true;
@@ -56,25 +78,36 @@ class CommandOSRestart : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
- source.Reply(_("Causes Services to save all databases and then restart\n"
+ source.Reply(_("Causes services to save all databases and then restart\n"
"(i.e. exit and immediately re-run the executable)."));
return true;
}
};
-class CommandOSShutdown : public Command
+class CommandOSShutdown final
+ : public Command
{
- public:
- CommandOSShutdown(Module *creator) : Command(creator, "operserv/shutdown", 0, 0)
+public:
+ CommandOSShutdown(Module *creator) : Command(creator, "operserv/shutdown", 0, 1)
{
this->SetDesc(_("Terminate services with save"));
+ if (Config->GetModule(this->owner)->Get<bool>("requirename"))
+ this->SetSyntax(_("\037network-name\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
+ const auto requirename = Config->GetModule(this->owner)->Get<bool>("requirename");
+ const auto networkname = Config->GetBlock("networkinfo")->Get<Anope::string>("networkname");
+ if (requirename && (params.empty() || !params[0].equals_cs(networkname)))
+ {
+ OnSyntaxError(source, source.command);
+ return;
+ }
+
Log(LOG_ADMIN, source, this);
Anope::QuitReason = source.command + " command received from " + source.GetNick();
Anope::Quitting = true;
@@ -82,22 +115,23 @@ class CommandOSShutdown : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Causes Services to save all databases and then shut down."));
+ source.Reply(_("Causes services to save all databases and then shut down."));
return true;
}
};
-class OSShutdown : public Module
+class OSShutdown final
+ : public Module
{
CommandOSQuit commandosquit;
CommandOSRestart commandosrestart;
CommandOSShutdown commandosshutdown;
- public:
+public:
OSShutdown(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosquit(this), commandosrestart(this), commandosshutdown(this)
{
diff --git a/modules/commands/os_stats.cpp b/modules/operserv/os_stats.cpp
index 9cbe57503..1190ac1fc 100644
--- a/modules/commands/os_stats.cpp
+++ b/modules/operserv/os_stats.cpp
@@ -12,7 +12,8 @@
#include "module.h"
#include "modules/os_session.h"
-struct Stats : Serializable
+struct Stats final
+ : Serializable
{
static Stats *me;
@@ -21,13 +22,13 @@ struct Stats : Serializable
me = this;
}
- void Serialize(Serialize::Data &data) const anope_override
+ void Serialize(Serialize::Data &data) const override
{
- data["maxusercnt"] << MaxUserCount;
- data["maxusertime"] << MaxUserTime;
+ data.Store("maxusercnt", MaxUserCount);
+ data.Store("maxusertime", MaxUserTime);
}
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
data["maxusercnt"] >> MaxUserCount;
data["maxusertime"] >> MaxUserTime;
@@ -50,23 +51,26 @@ static int stats_count_servers(Server *s)
int count = 1;
if (!s->GetLinks().empty())
- for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i)
- count += stats_count_servers(s->GetLinks()[i]);
+ {
+ for (auto *link : s->GetLinks())
+ count += stats_count_servers(link);
+ }
return count;
}
-class CommandOSStats : public Command
+class CommandOSStats final
+ : public Command
{
ServiceReference<XLineManager> akills, snlines, sqlines;
- private:
+private:
void DoStatsAkill(CommandSource &source)
{
int timeout;
if (akills)
{
/* AKILLs */
- source.Reply(_("Current number of AKILLs: \002%d\002"), akills->GetCount());
+ source.Reply(_("Current number of AKILLs: \002%zu\002"), akills->GetCount());
timeout = Config->GetModule("operserv")->Get<time_t>("autokillexpiry", "30d") + 59;
if (timeout >= 172800)
source.Reply(_("Default AKILL expiry time: \002%d days\002"), timeout / 86400);
@@ -86,7 +90,7 @@ class CommandOSStats : public Command
if (snlines)
{
/* SNLINEs */
- source.Reply(_("Current number of SNLINEs: \002%d\002"), snlines->GetCount());
+ source.Reply(_("Current number of SNLINEs: \002%zu\002"), snlines->GetCount());
timeout = Config->GetModule("operserv")->Get<time_t>("snlineexpiry", "30d") + 59;
if (timeout >= 172800)
source.Reply(_("Default SNLINE expiry time: \002%d days\002"), timeout / 86400);
@@ -106,7 +110,7 @@ class CommandOSStats : public Command
if (sqlines)
{
/* SQLINEs */
- source.Reply(_("Current number of SQLINEs: \002%d\002"), sqlines->GetCount());
+ source.Reply(_("Current number of SQLINEs: \002%zu\002"), sqlines->GetCount());
timeout = Config->GetModule("operserv")->Get<time_t>("sglineexpiry", "30d") + 59;
if (timeout >= 172800)
source.Reply(_("Default SQLINE expiry time: \002%d days\002"), timeout / 86400);
@@ -125,7 +129,7 @@ class CommandOSStats : public Command
}
}
- void DoStatsReset(CommandSource &source)
+ static void DoStatsReset(CommandSource &source)
{
MaxUserCount = UserListByNick.size();
MaxUserTime = Anope::CurTime;
@@ -134,21 +138,21 @@ class CommandOSStats : public Command
return;
}
- void DoStatsUptime(CommandSource &source)
+ static void DoStatsUptime(CommandSource &source)
{
time_t uptime = Anope::CurTime - Anope::StartTime;
- source.Reply(_("Current users: \002%d\002 (\002%d\002 ops)"), UserListByNick.size(), OperCount);
+ source.Reply(_("Current users: \002%zu\002 (\002%d\002 ops)"), UserListByNick.size(), OperCount);
source.Reply(_("Maximum users: \002%d\002 (%s)"), MaxUserCount, Anope::strftime(MaxUserTime, source.GetAccount()).c_str());
source.Reply(_("Services up %s."), Anope::Duration(uptime, source.GetAccount()).c_str());
return;
}
- void DoStatsUplink(CommandSource &source)
+ static void DoStatsUplink(CommandSource &source)
{
Anope::string buf;
- for (std::set<Anope::string>::iterator it = Servers::Capab.begin(); it != Servers::Capab.end(); ++it)
- buf += " " + *it;
+ for (const auto &capab : Servers::Capab)
+ buf += " " + capab;
if (!buf.empty())
buf.erase(buf.begin());
@@ -158,7 +162,7 @@ class CommandOSStats : public Command
return;
}
- template<typename T> void GetHashStats(const T& map, size_t& entries, size_t& buckets, size_t& max_chain)
+ template<typename T> void GetHashStats(const T &map, size_t &entries, size_t &buckets, size_t &max_chain)
{
entries = map.size(), buckets = map.bucket_count(), max_chain = 0;
for (size_t i = 0; i < buckets; ++i)
@@ -171,42 +175,73 @@ class CommandOSStats : public Command
size_t entries, buckets, max_chain;
GetHashStats(UserListByNick, entries, buckets, max_chain);
- source.Reply(_("Users (nick): %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Users (nick): %lu entries, %lu buckets, longest chain is %zu"), entries, buckets, max_chain);
if (!UserListByUID.empty())
{
GetHashStats(UserListByUID, entries, buckets, max_chain);
- source.Reply(_("Users (uid): %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Users (uid): %lu entries, %lu buckets, longest chain is %zu"), entries, buckets, max_chain);
}
GetHashStats(ChannelList, entries, buckets, max_chain);
- source.Reply(_("Channels: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Channels: %zu entries, %zu buckets, longest chain is %zu"), entries, buckets, max_chain);
GetHashStats(*RegisteredChannelList, entries, buckets, max_chain);
- source.Reply(_("Registered channels: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Registered channels: %zu entries, %zu buckets, longest chain is %zu"), entries, buckets, max_chain);
GetHashStats(*NickAliasList, entries, buckets, max_chain);
- source.Reply(_("Registered nicknames: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Registered nicknames: %zu entries, %zu buckets, longest chain is %zu"), entries, buckets, max_chain);
GetHashStats(*NickCoreList, entries, buckets, max_chain);
- source.Reply(_("Registered nick groups: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Registered nick groups: %zu entries, %zu buckets, longest chain is %zu"), entries, buckets, max_chain);
if (session_service)
{
GetHashStats(session_service->GetSessions(), entries, buckets, max_chain);
- source.Reply(_("Sessions: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain);
+ source.Reply(_("Sessions: %zu entries, %zu buckets, longest chain is %zu"), entries, buckets, max_chain);
+ }
+ }
+
+ void DoStatsPassword(CommandSource &source)
+ {
+ Anope::map<size_t> counts;
+ size_t missing = 0;
+ size_t unknown = 0;
+ for (const auto &[_, nc] : *NickCoreList)
+ {
+ if (nc->pass.empty())
+ {
+ missing++;
+ continue;
+ }
+
+ auto sep = nc->pass.find(':');
+ if (sep == Anope::string::npos)
+ {
+ unknown++;
+ continue;
+ }
+
+ counts[nc->pass.substr(0, sep)]++;
}
+
+ for (const auto &[algo, count] : counts)
+ source.Reply(_("Passwords encrypted with %s: %zu"), algo.c_str(), count);
+ if (missing)
+ source.Reply(_("Missing passwords: %zu"), missing);
+ if (unknown)
+ source.Reply(_("Unknown passwords: %zu"), unknown);
}
- public:
+public:
CommandOSStats(Module *creator) : Command(creator, "operserv/stats", 0, 1),
akills("XLineManager", "xlinemanager/sgline"), snlines("XLineManager", "xlinemanager/snline"), sqlines("XLineManager", "xlinemanager/sqline")
{
- this->SetDesc(_("Show status of Services and network"));
- this->SetSyntax("[AKILL | HASH | UPLINK | UPTIME | ALL | RESET]");
+ this->SetDesc(_("Show status of services and network"));
+ this->SetSyntax("[AKILL | HASH | PASSWORD | UPLINK | UPTIME | ALL | RESET]");
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Anope::string extra = !params.empty() ? params[0] : "";
@@ -215,29 +250,48 @@ class CommandOSStats : public Command
if (extra.equals_ci("RESET"))
return this->DoStatsReset(source);
+ bool handled = false;
if (extra.equals_ci("ALL") || extra.equals_ci("AKILL"))
+ {
this->DoStatsAkill(source);
+ handled = true;
+ }
if (extra.equals_ci("ALL") || extra.equals_ci("HASH"))
+ {
this->DoStatsHash(source);
+ handled = true;
+ }
+
+ if (extra.equals_ci("ALL") || extra.equals_ci("PASSWORD"))
+ {
+ this->DoStatsPassword(source);
+ handled = true;
+ }
if (extra.equals_ci("ALL") || extra.equals_ci("UPLINK"))
+ {
this->DoStatsUplink(source);
+ handled = true;
+ }
if (extra.empty() || extra.equals_ci("ALL") || extra.equals_ci("UPTIME"))
+ {
this->DoStatsUptime(source);
+ handled = true;
+ }
- if (!extra.empty() && !extra.equals_ci("ALL") && !extra.equals_ci("AKILL") && !extra.equals_ci("HASH") && !extra.equals_ci("UPLINK") && !extra.equals_ci("UPTIME"))
+ if (!handled)
source.Reply(_("Unknown STATS option: \002%s\002"), extra.c_str());
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Without any option, shows the current number of users online,\n"
- "and the highest number of users online since Services was\n"
- "started, and the length of time Services has been running.\n"
+ "and the highest number of users online since services was\n"
+ "started, and the length of time services has been running.\n"
" \n"
"With the \002AKILL\002 option, displays the current size of the\n"
"AKILL list and the current default expiry time.\n"
@@ -245,6 +299,9 @@ class CommandOSStats : public Command
"The \002RESET\002 option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
+ "The \002PASSWORD\002 option displays the encryption algorithms used\n"
+ "for user passwords.\n"
+ " \n"
"The \002UPLINK\002 option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
" \n"
@@ -255,20 +312,21 @@ class CommandOSStats : public Command
}
};
-class OSStats : public Module
+class OSStats final
+ : public Module
{
CommandOSStats commandosstats;
Serialize::Type stats_type;
Stats stats_saver;
- public:
+public:
OSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosstats(this), stats_type("Stats", Stats::Unserialize)
{
}
- void OnUserConnect(User *u, bool &exempt) anope_override
+ void OnUserConnect(User *u, bool &exempt) override
{
if (UserListByNick.size() == MaxUserCount && Anope::CurTime == MaxUserTime)
stats_saver.QueueUpdate();
diff --git a/modules/commands/os_svs.cpp b/modules/operserv/os_svs.cpp
index 6875fa6e8..1d6077aca 100644
--- a/modules/commands/os_svs.cpp
+++ b/modules/operserv/os_svs.cpp
@@ -11,16 +11,17 @@
#include "module.h"
-class CommandOSSVSNick : public Command
+class CommandOSSVSNick final
+ : public Command
{
- public:
+public:
CommandOSSVSNick(Module *creator) : Command(creator, "operserv/svsnick", 2, 2)
{
this->SetDesc(_("Forcefully change a user's nickname"));
this->SetSyntax(_("\037nick\037 \037newnick\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &nick = params[0];
Anope::string newnick = params[1];
@@ -33,10 +34,10 @@ class CommandOSSVSNick : public Command
}
/* Truncate long nicknames to nicklen characters */
- unsigned nicklen = Config->GetBlock("networkinfo")->Get<unsigned>("nicklen");
+ size_t nicklen = IRCD->MaxNick;
if (newnick.length() > nicklen)
{
- source.Reply(_("Nick \002%s\002 was truncated to %d characters."), newnick.c_str(), nicklen, newnick.c_str());
+ source.Reply(_("Nick \002%s\002 was truncated to %zu characters."), newnick.c_str(), nicklen);
newnick = params[1].substr(0, nicklen);
}
@@ -61,7 +62,7 @@ class CommandOSSVSNick : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -70,16 +71,17 @@ class CommandOSSVSNick : public Command
}
};
-class CommandOSSVSJoin : public Command
+class CommandOSSVSJoin final
+ : public Command
{
- public:
+public:
CommandOSSVSJoin(Module *creator) : Command(creator, "operserv/svsjoin", 2, 2)
{
this->SetDesc(_("Forcefully join a user to a channel"));
this->SetSyntax(_("\037nick\037 \037channel\037"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!IRCD->CanSVSJoin)
{
@@ -105,7 +107,7 @@ class CommandOSSVSJoin : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -114,16 +116,17 @@ class CommandOSSVSJoin : public Command
}
};
-class CommandOSSVSPart : public Command
+class CommandOSSVSPart final
+ : public Command
{
- public:
+public:
CommandOSSVSPart(Module *creator) : Command(creator, "operserv/svspart", 2, 3)
{
this->SetDesc(_("Forcefully part a user from a channel"));
this->SetSyntax(_("\037nick\037 \037channel\037 [\037reason\037]"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!IRCD->CanSVSJoin)
{
@@ -153,7 +156,7 @@ class CommandOSSVSPart : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
@@ -162,13 +165,14 @@ class CommandOSSVSPart : public Command
}
};
-class OSSVS : public Module
+class OSSVS final
+ : public Module
{
CommandOSSVSNick commandossvsnick;
CommandOSSVSJoin commandossvsjoin;
CommandOSSVSPart commandossvspart;
- public:
+public:
OSSVS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandossvsnick(this), commandossvsjoin(this), commandossvspart(this)
{
diff --git a/modules/commands/os_sxline.cpp b/modules/operserv/os_sxline.cpp
index 0e18f933a..270ece378 100644
--- a/modules/commands/os_sxline.cpp
+++ b/modules/operserv/os_sxline.cpp
@@ -11,18 +11,19 @@
#include "module.h"
-class SXLineDelCallback : public NumberList
+class SXLineDelCallback final
+ : public NumberList
{
XLineManager *xlm;
Command *command;
CommandSource &source;
- unsigned deleted;
- public:
- SXLineDelCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), xlm(x), command(c), source(_source), deleted(0)
+ unsigned deleted = 0;
+public:
+ SXLineDelCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), xlm(x), command(c), source(_source)
{
}
- ~SXLineDelCallback()
+ ~SXLineDelCallback() override
{
if (!deleted)
source.Reply(_("No matching entries on the %s list."), source.command.c_str());
@@ -32,7 +33,7 @@ class SXLineDelCallback : public NumberList
source.Reply(_("Deleted %d entries from the %s list."), deleted, source.command.c_str());
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number)
return;
@@ -54,10 +55,11 @@ class SXLineDelCallback : public NumberList
}
};
-class CommandOSSXLineBase : public Command
+class CommandOSSXLineBase
+ : public Command
{
- private:
- virtual XLineManager* xlm() = 0;
+private:
+ virtual XLineManager *xlm() = 0;
virtual void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) = 0;
@@ -118,17 +120,18 @@ class CommandOSSXLineBase : public Command
if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos)
{
- class SXLineListCallback : public NumberList
+ class SXLineListCallback final
+ : public NumberList
{
XLineManager *xlm;
CommandSource &source;
ListFormatter &list;
- public:
+ public:
SXLineListCallback(XLineManager *x, CommandSource &_source, ListFormatter &_list, const Anope::string &numlist) : NumberList(numlist, false), xlm(x), source(_source), list(_list)
{
}
- void HandleNumber(unsigned number) anope_override
+ void HandleNumber(unsigned number) override
{
if (!number)
return;
@@ -139,7 +142,7 @@ class CommandOSSXLineBase : public Command
return;
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(number);
+ entry["Number"] = Anope::ToString(number);
entry["Mask"] = x->mask;
entry["By"] = x->by;
entry["Created"] = Anope::strftime(x->created, NULL, true);
@@ -161,7 +164,7 @@ class CommandOSSXLineBase : public Command
if (mask.empty() || mask.equals_ci(x->mask) || mask == x->id || Anope::Match(x->mask, mask, false, true))
{
ListFormatter::ListEntry entry;
- entry["Number"] = stringify(i + 1);
+ entry["Number"] = Anope::ToString(i + 1);
entry["Mask"] = x->mask;
entry["By"] = x->by;
entry["Created"] = Anope::strftime(x->created, NULL, true);
@@ -182,8 +185,8 @@ class CommandOSSXLineBase : public Command
std::vector<Anope::string> replies;
list.Process(replies);
- for (unsigned i = 0; i < replies.size(); ++i)
- source.Reply(replies[i]);
+ for (const auto &reply : replies)
+ source.Reply(reply);
}
}
@@ -223,17 +226,17 @@ class CommandOSSXLineBase : public Command
return;
}
- public:
+public:
CommandOSSXLineBase(Module *creator, const Anope::string &cmd) : Command(creator, cmd, 1, 4)
{
}
- const Anope::string GetDesc(CommandSource &source) const anope_override
+ const Anope::string GetDesc(CommandSource &source) const override
{
return Anope::printf(Language::Translate(source.GetAccount(), _("Manipulate the %s list")), source.command.upper().c_str());
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
const Anope::string &cmd = params[0];
@@ -253,17 +256,18 @@ class CommandOSSXLineBase : public Command
return;
}
- virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override = 0;
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override = 0;
};
-class CommandOSSNLine : public CommandOSSXLineBase
+class CommandOSSNLine final
+ : public CommandOSSXLineBase
{
- XLineManager *xlm() anope_override
+ XLineManager *xlm() override
{
return this->snlines;
}
- void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!this->xlm())
return;
@@ -366,13 +370,13 @@ class CommandOSSNLine : public CommandOSSXLineBase
return;
}
- XLine *x = new XLine(mask, source.GetNick(), expires, reason);
+ auto *x = new XLine(mask, source.GetNick(), expires, reason);
if (Config->GetModule("operserv")->Get<bool>("akillids"))
x->id = XLineManager::GenerateUID();
unsigned int affected = 0;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (this->xlm()->Check(it->second, x))
+ for (const auto &[_, user] : UserListByNick)
+ if (this->xlm()->Check(user, x))
++affected;
float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0;
@@ -385,7 +389,10 @@ class CommandOSSNLine : public CommandOSSXLineBase
}
if (!this->xlm()->CanAdd(source, mask, expires, reason))
+ {
+ delete x;
return;
+ }
EventReturn MOD_RESULT;
FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, this->xlm()));
@@ -401,10 +408,8 @@ class CommandOSSNLine : public CommandOSSXLineBase
{
Anope::string rreason = "G-Lined: " + reason;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, user] : UserListByNick)
{
- User *user = it->second;
-
if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
user->Kill(Me, rreason);
}
@@ -419,7 +424,7 @@ class CommandOSSNLine : public CommandOSSXLineBase
}
ServiceReference<XLineManager> snlines;
- public:
+public:
CommandOSSNLine(Module *creator) : CommandOSSXLineBase(creator, "operserv/snline"), snlines("XLineManager", "xlinemanager/snline")
{
this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037:\037reason\037"));
@@ -429,13 +434,13 @@ class CommandOSSNLine : public CommandOSSXLineBase
this->SetSyntax("CLEAR");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows Services Operators to manipulate the SNLINE list. If\n"
"a user with a realname matching an SNLINE mask attempts to\n"
- "connect, Services will not allow them to pursue their IRC\n"
+ "connect, services will not allow them to pursue their IRC\n"
"session."));
source.Reply(_(" \n"
"\002SNLINE ADD\002 adds the given realname mask to the SNLINE\n"
@@ -482,14 +487,15 @@ class CommandOSSNLine : public CommandOSSXLineBase
}
};
-class CommandOSSQLine : public CommandOSSXLineBase
+class CommandOSSQLine final
+ : public CommandOSSXLineBase
{
- XLineManager *xlm() anope_override
+ XLineManager *xlm() override
{
return this->sqlines;
}
- void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void OnAdd(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!this->xlm())
return;
@@ -574,13 +580,13 @@ class CommandOSSQLine : public CommandOSSXLineBase
return;
}
- XLine *x = new XLine(mask, source.GetNick(), expires, reason);
+ auto *x = new XLine(mask, source.GetNick(), expires, reason);
if (Config->GetModule("operserv")->Get<bool>("akillids"))
x->id = XLineManager::GenerateUID();
unsigned int affected = 0;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (this->xlm()->Check(it->second, x))
+ for (const auto &[_, user] : UserListByNick)
+ if (this->xlm()->Check(user, x))
++affected;
float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0;
@@ -611,33 +617,28 @@ class CommandOSSQLine : public CommandOSSXLineBase
if (mask[0] == '#')
{
- for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit)
+ for (const auto &[_, c] : ChannelList)
{
- Channel *c = cit->second;
-
if (!Anope::Match(c->name, mask, false, true))
continue;
std::vector<User *> users;
- for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : c->users)
{
- ChanUserContainer *uc = it->second;
User *user = uc->user;
if (!user->HasMode("OPER") && user->server != Me)
users.push_back(user);
}
- for (unsigned i = 0; i < users.size(); ++i)
- c->Kick(NULL, users[i], "%s", reason.c_str());
+ for (auto *user : users)
+ c->Kick(NULL, user, reason);
}
}
else
{
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, user] : UserListByNick)
{
- User *user = it->second;
-
if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
user->Kill(Me, rreason);
}
@@ -653,7 +654,7 @@ class CommandOSSQLine : public CommandOSSXLineBase
}
ServiceReference<XLineManager> sqlines;
- public:
+public:
CommandOSSQLine(Module *creator) : CommandOSSXLineBase(creator, "operserv/sqline"), sqlines("XLineManager", "xlinemanager/sqline")
{
this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037 \037reason\037"));
@@ -663,13 +664,13 @@ class CommandOSSQLine : public CommandOSSXLineBase
this->SetSyntax("CLEAR");
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Allows Services Operators to manipulate the SQLINE list. If\n"
"a user with a nick matching an SQLINE mask attempts to\n"
- "connect, Services will not allow them to pursue their IRC\n"
+ "connect, services will not allow them to pursue their IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
"prevent the use of matching channels. If the mask is a\n"
@@ -717,12 +718,13 @@ class CommandOSSQLine : public CommandOSSXLineBase
}
};
-class OSSXLine : public Module
+class OSSXLine final
+ : public Module
{
CommandOSSNLine commandossnline;
CommandOSSQLine commandossqline;
- public:
+public:
OSSXLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandossnline(this), commandossqline(this)
{
diff --git a/modules/commands/os_update.cpp b/modules/operserv/os_update.cpp
index 67222785e..e1c25a1be 100644
--- a/modules/commands/os_update.cpp
+++ b/modules/operserv/os_update.cpp
@@ -11,15 +11,16 @@
#include "module.h"
-class CommandOSUpdate : public Command
+class CommandOSUpdate final
+ : public Command
{
- public:
+public:
CommandOSUpdate(Module *creator) : Command(creator, "operserv/update", 0, 0)
{
- this->SetDesc(_("Force the Services databases to be updated immediately"));
+ this->SetDesc(_("Force the services databases to be updated immediately"));
}
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
Log(LOG_ADMIN, source, this);
source.Reply(_("Updating databases."));
@@ -27,21 +28,22 @@ class CommandOSUpdate : public Command
return;
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
- source.Reply(_("Causes Services to update all database files as soon as you\n"
+ source.Reply(_("Causes services to update all database files as soon as you\n"
"send the command."));
return true;
}
};
-class OSUpdate : public Module
+class OSUpdate final
+ : public Module
{
CommandOSUpdate commandosupdate;
- public:
+public:
OSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandosupdate(this)
{
diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp
index f612950d3..cd1a582b9 100644
--- a/modules/protocol/bahamut.cpp
+++ b/modules/protocol/bahamut.cpp
@@ -11,32 +11,35 @@
#include "module.h"
-class ChannelModeFlood : public ChannelModeParam
+class ChannelModeFlood final
+ : public ChannelModeParam
{
- public:
+public:
ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
- bool IsValid(Anope::string &value) const anope_override
+ bool IsValid(Anope::string &value) const override
{
- try
- {
- Anope::string rest;
- if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty())
- return true;
- }
- catch (const ConvertException &) { }
+ if (value.empty() || value[0] == ':')
+ return false;
- return false;
+ Anope::string rest;
+ auto num1 = Anope::Convert<int>(value[0] == '*' ? value.substr(1) : value, 0, &rest);
+ if (num1 <= 0 || rest[0] != ':' || rest.length() <= 1)
+ return false;
+
+ return Anope::Convert<int>(rest.substr(1), 0, &rest) > 0 && rest.empty();
}
};
-class BahamutIRCdProto : public IRCDProto
+class BahamutIRCdProto final
+ : public IRCDProto
{
- public:
- BahamutIRCdProto(Module *creator) : IRCDProto(creator, "Bahamut 1.8.x")
+public:
+ BahamutIRCdProto(Module *creator) : IRCDProto(creator, "Bahamut 2+")
{
DefaultPseudoclientModes = "+";
CanSVSNick = true;
+ CanSVSNOOP = true;
CanSNLine = true;
CanSQLine = true;
CanSQLineChannel = true;
@@ -45,91 +48,82 @@ class BahamutIRCdProto : public IRCDProto
MaxModes = 60;
}
- void SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) anope_override
+ void SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values) override
{
- if (Servers::Capab.count("TSMODE") > 0)
- {
- UplinkSocket::Message(source) << "MODE " << dest->name << " " << dest->creation_time << " " << buf;
- }
- else
- IRCDProto::SendModeInternal(source, dest, buf);
+ auto params = values;
+ params.insert(params.begin(), { chan->name, Anope::ToString(chan->creation_time), modes });
+ Uplink::SendInternal({}, source, "MODE", params);
}
- void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override
+ void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values) override
{
- UplinkSocket::Message(source) << "SVSMODE " << u->nick << " " << u->timestamp << " " << buf;
+ auto params = values;
+ params.insert(params.begin(), { u->nick, Anope::ToString(u->timestamp), modes });
+ Uplink::SendInternal({}, source, "SVSMODE", params);
}
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "NOTICE", "$" + dest->GetName(), msg);
}
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg);
}
/* SVSHOLD - set */
- void SendSVSHold(const Anope::string &nick, time_t time) anope_override
+ void SendSVSHold(const Anope::string &nick, time_t time) override
{
- UplinkSocket::Message(Me) << "SVSHOLD " << nick << " " << time << " :Being held for registered user";
+ Uplink::Send("SVSHOLD", nick, time, "Being held for a registered user");
}
/* SVSHOLD - release */
- void SendSVSHoldDel(const Anope::string &nick) anope_override
+ void SendSVSHoldDel(const Anope::string &nick) override
{
- UplinkSocket::Message(Me) << "SVSHOLD " << nick << " 0";
+ Uplink::Send("SVSHOLD", nick, 0);
}
/* SQLINE */
- void SendSQLine(User *, const XLine *x) anope_override
+ void SendSQLine(User *, const XLine *x) override
{
- UplinkSocket::Message() << "SQLINE " << x->mask << " :" << x->GetReason();
+ Uplink::Send("SQLINE", x->mask, x->reason);
}
/* UNSLINE */
- void SendSGLineDel(const XLine *x) anope_override
+ void SendSGLineDel(const XLine *x) override
{
- UplinkSocket::Message() << "UNSGLINE 0 :" << x->mask;
+ Uplink::Send("UNSGLINE", 0, x->mask);
}
/* UNSZLINE */
- void SendSZLineDel(const XLine *x) anope_override
+ void SendSZLineDel(const XLine *x) override
{
- /* this will likely fail so its only here for legacy */
- UplinkSocket::Message() << "UNSZLINE 0 " << x->GetHost();
- /* this is how we are supposed to deal with it */
- UplinkSocket::Message() << "RAKILL " << x->GetHost() << " *";
+ Uplink::Send("RAKILL", x->GetHost(), '*');
}
/* SZLINE */
- void SendSZLine(User *, const XLine *x) anope_override
+ void SendSZLine(User *, const XLine *x) override
{
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- /* this will likely fail so its only here for legacy */
- UplinkSocket::Message() << "SZLINE " << x->GetHost() << " :" << x->GetReason();
- /* this is how we are supposed to deal with it */
- UplinkSocket::Message() << "AKILL " << x->GetHost() << " * " << timeleft << " " << x->by << " " << Anope::CurTime << " :" << x->GetReason();
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+ Uplink::Send("AKILL", x->GetHost(), '*', timeleft, x->by, Anope::CurTime, x->GetReason());
}
/* SVSNOOP */
- void SendSVSNOOP(const Server *server, bool set) anope_override
+ void SendSVSNOOP(const Server *server, bool set) override
{
- UplinkSocket::Message() << "SVSNOOP " << server->GetName() << " " << (set ? "+" : "-");
+ Uplink::Send("SVSNOOP", server->GetName(), set ? '+' : '-');
}
/* SGLINE */
- void SendSGLine(User *, const XLine *x) anope_override
+ void SendSGLine(User *, const XLine *x) override
{
- UplinkSocket::Message() << "SGLINE " << x->mask.length() << " :" << x->mask << ":" << x->GetReason();
+ Uplink::Send("SGLINE", x->mask.length(), x->mask, x->GetReason());
}
/* RAKILL */
- void SendAkillDel(const XLine *x) anope_override
+ void SendAkillDel(const XLine *x) override
{
if (x->IsRegex() || x->HasNickOrReal())
return;
@@ -145,25 +139,25 @@ class BahamutIRCdProto : public IRCDProto
}
}
- UplinkSocket::Message() << "RAKILL " << x->GetHost() << " " << x->GetUser();
+ Uplink::Send("RAKILL", x->GetHost(), x->GetUser());
}
/* TOPIC */
- void SendTopic(const MessageSource &source, Channel *c) anope_override
+ void SendTopic(const MessageSource &source, Channel *c) override
{
- UplinkSocket::Message(source) << "TOPIC " << c->name << " " << c->topic_setter << " " << c->topic_ts << " :" << c->topic;
+ Uplink::Send(source, "TOPIC", c->name, c->topic_setter, c->topic_ts, c->topic);
}
/* UNSQLINE */
- void SendSQLineDel(const XLine *x) anope_override
+ void SendSQLineDel(const XLine *x) override
{
- UplinkSocket::Message() << "UNSQLINE " << x->mask;
+ Uplink::Send("UNSQLINE", x->mask);
}
/* JOIN - SJOIN */
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override
{
- UplinkSocket::Message(user) << "SJOIN " << c->creation_time << " " << c->name;
+ Uplink::Send(user, "SJOIN", c->creation_time, c->name);
if (status)
{
/* First save the channel status incase uc->Status == status */
@@ -176,24 +170,24 @@ class BahamutIRCdProto : public IRCDProto
uc->status.Clear();
BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
+ for (auto mode : cs.Modes())
+ c->SetMode(setter, ModeManager::FindChannelModeByChar(mode), user->GetUID(), false);
if (uc != NULL)
uc->status = cs;
}
}
- void SendAkill(User *u, XLine *x) anope_override
+ void SendAkill(User *u, XLine *x) override
{
if (x->IsRegex() || x->HasNickOrReal())
{
if (!u)
{
/* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (x->manager->Check(it->second, x))
- this->SendAkill(it->second, x);
+ for (const auto &[_, user] : UserListByNick)
+ if (x->manager->Check(user, x))
+ this->SendAkill(user, x);
return;
}
@@ -220,47 +214,44 @@ class BahamutIRCdProto : public IRCDProto
}
}
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800)
- timeleft = 172800;
- UplinkSocket::Message() << "AKILL " << x->GetHost() << " " << x->GetUser() << " " << timeleft << " " << x->by << " " << Anope::CurTime << " :" << x->GetReason();
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+ Uplink::Send("AKILL", x->GetHost(), x->GetUser(), timeleft, x->by, Anope::CurTime, x->reason);
}
/*
Note: if the stamp is null 0, the below usage is correct of Bahamut
*/
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override
+ void SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) override
{
- UplinkSocket::Message(source) << "SVSKILL " << user->nick << " :" << buf;
+ Uplink::Send(source, "SVSKILL", user->nick, buf);
}
- void SendBOB() anope_override
+ void SendBOB() override
{
- UplinkSocket::Message() << "BURST";
+ Uplink::Send("BURST");
}
- void SendEOB() anope_override
+ void SendEOB() override
{
- UplinkSocket::Message() << "BURST 0";
+ Uplink::Send("BURST", 0);
}
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message() << "NICK " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " " << u->server->GetName() << " 0 0 :" << u->realname;
+ Uplink::Send("NICK", u->nick, 1, u->timestamp, "+" + u->GetModes(), u->GetIdent(), u->host, u->server->GetName(), 0, "0.0.0.0", u->realname);
}
/* SERVER */
- void SendServer(const Server *server) anope_override
+ void SendServer(const Server *server) override
{
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription();
+ Uplink::Send("SERVER", server->GetName(), server->GetHops(), server->GetDescription());
}
- void SendConnect() anope_override
+ void SendConnect() override
{
- UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " :TS";
- UplinkSocket::Message() << "CAPAB SSJOIN NOQUIT BURST UNCONNECT NICKIP TSMODE TS3";
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS");
+ Uplink::Send("CAPAB", "BURST", "NICKIPSTR", "SSJOIN", "UNCONNECT");
SendServer(Me);
/*
* SVINFO
@@ -270,34 +261,32 @@ class BahamutIRCdProto : public IRCDProto
* parv[3] = server is standalone or connected to non-TS only
* parv[4] = server's idea of UTC time
*/
- UplinkSocket::Message() << "SVINFO 3 1 0 :" << Anope::CurTime;
+ Uplink::Send("SVINFO", 5, 5, 0, Anope::CurTime);
this->SendBOB();
}
- void SendChannel(Channel *c) anope_override
+ void SendChannel(Channel *c) override
{
- Anope::string modes = c->GetModes(true, true);
- if (modes.empty())
- modes = "+";
- UplinkSocket::Message() << "SJOIN " << c->creation_time << " " << c->name << " " << modes << " :";
+ Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), "");
}
- void SendLogin(User *u, NickAlias *) anope_override
+ void SendLogin(User *u, NickAlias *) override
{
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %d", u->signon);
+ IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", u->signon);
}
- void SendLogout(User *u) anope_override
+ void SendLogout(User *u) override
{
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d 1");
+ IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", 1);
}
};
-struct IRCDMessageBurst : IRCDMessage
+struct IRCDMessageBurst final
+ : IRCDMessage
{
- IRCDMessageBurst(Module *creator) : IRCDMessage(creator, "BURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageBurst(Module *creator) : IRCDMessage(creator, "BURST", 0) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/* If we found a server with the given source, that one just
* finished bursting. If there was no source, then our uplink
@@ -311,35 +300,26 @@ struct IRCDMessageBurst : IRCDMessage
}
};
-struct IRCDMessageMode : IRCDMessage
+struct IRCDMessageMode final
+ : IRCDMessage
{
- IRCDMessageMode(Module *creator, const Anope::string &sname) : IRCDMessage(creator, sname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageMode(Module *creator, const Anope::string &sname) : IRCDMessage(creator, sname, 2) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() > 2 && IRCD->IsChannelValid(params[0]))
{
Channel *c = Channel::Find(params[0]);
- time_t ts = 0;
-
- try
- {
- ts = convertTo<time_t>(params[1]);
- }
- catch (const ConvertException &) { }
-
- Anope::string modes = params[2];
- for (unsigned int i = 3; i < params.size(); ++i)
- modes += " " + params[i];
+ auto ts = IRCD->ExtractTimestamp(params[1]);
if (c)
- c->SetModesInternal(source, modes, ts);
+ c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
}
else
{
User *u = User::Find(params[0]);
if (u)
- u->SetModesInternal(source, "%s", params[1].c_str());
+ u->SetModesInternal(source, params[1]);
}
}
};
@@ -362,11 +342,12 @@ struct IRCDMessageMode : IRCDMessage
** parv[0] = new nickname
** parv[1] = hopcount
*/
-struct IRCDMessageNick : IRCDMessage
+struct IRCDMessageNick final
+ : IRCDMessage
{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() == 10)
{
@@ -378,8 +359,8 @@ struct IRCDMessageNick : IRCDMessage
}
NickAlias *na = NULL;
- time_t signon = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0,
- stamp = params[7].is_pos_number_only() ? convertTo<time_t>(params[7]) : 0;
+ auto signon = IRCD->ExtractTimestamp(params[2]);
+ auto stamp = IRCD->ExtractTimestamp(params[7]);
if (signon && signon == stamp)
na = NickAlias::Find(params[0]);
@@ -395,29 +376,32 @@ struct IRCDMessageNick : IRCDMessage
}
};
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
+ auto hops = Anope::Convert<unsigned>(params[1], 0);
new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]);
}
};
-struct IRCDMessageSJoin : IRCDMessage
+struct IRCDMessageSJoin final
+ : IRCDMessage
{
- IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 2) { SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes;
+ std::vector<Anope::string> modeparams;
if (params.size() >= 4)
- for (unsigned i = 2; i < params.size(); ++i)
- modes += " " + params[i];
- if (!modes.empty())
- modes.erase(modes.begin());
+ {
+ modes = params[2];
+ modeparams = { params.begin() + 3, params.end() };
+ }
std::list<Message::Join::SJoinUser> users;
@@ -457,24 +441,26 @@ struct IRCDMessageSJoin : IRCDMessage
}
}
- time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime;
- Message::Join::SJoin(source, params[1], ts, modes, users);
+ auto ts = IRCD->ExtractTimestamp(params[0]);
+ Message::Join::SJoin(source, params[1], ts, modes, modeparams, users);
}
};
-struct IRCDMessageTopic : IRCDMessage
+struct IRCDMessageTopic final
+ : IRCDMessage
{
IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 4) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Channel *c = Channel::Find(params[0]);
if (c)
- c->ChangeTopicInternal(source.GetUser(), params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime);
+ c->ChangeTopicInternal(source.GetUser(), params[1], params[3], IRCD->ExtractTimestamp(params[2]));
}
};
-class ProtoBahamut : public Module
+class ProtoBahamut final
+ : public Module
{
BahamutIRCdProto ircd_proto;
@@ -506,7 +492,7 @@ class ProtoBahamut : public Module
IRCDMessageSJoin message_sjoin;
IRCDMessageTopic message_topic;
- void AddModes()
+ static void AddModes()
{
/* Add user modes */
ModeManager::AddUserMode(new UserModeOperOnly("SERV_ADMIN", 'A'));
@@ -544,7 +530,7 @@ class ProtoBahamut : public Module
ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
}
- public:
+public:
ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_away(this), message_capab(this), message_error(this), message_invite(this),
@@ -555,12 +541,10 @@ class ProtoBahamut : public Module
message_burst(this), message_mode(this, "MODE"), message_svsmode(this, "SVSMODE"),
message_nick(this), message_server(this), message_sjoin(this), message_topic(this)
{
-
this->AddModes();
-
}
- void OnUserNickChange(User *u, const Anope::string &) anope_override
+ void OnUserNickChange(User *u, const Anope::string &) override
{
u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
IRCD->SendLogout(u);
diff --git a/modules/protocol/hybrid.cpp b/modules/protocol/hybrid.cpp
index a10423712..59f535e8a 100644
--- a/modules/protocol/hybrid.cpp
+++ b/modules/protocol/hybrid.cpp
@@ -15,15 +15,16 @@
static Anope::string UplinkSID;
static bool UseSVSAccount = false; // Temporary backwards compatibility hack until old proto is deprecated
-class HybridProto : public IRCDProto
+class HybridProto final
+ : public IRCDProto
{
- void SendSVSKillInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override
+ void SendSVSKill(const MessageSource &source, User *u, const Anope::string &buf) override
{
- IRCDProto::SendSVSKillInternal(source, u, buf);
+ IRCDProto::SendSVSKill(source, u, buf);
u->KillInternal(source, buf);
}
- public:
+public:
HybridProto(Module *creator) : IRCDProto(creator, "ircd-hybrid 8.2.23+")
{
DefaultPseudoclientModes = "+oi";
@@ -40,68 +41,64 @@ class HybridProto : public IRCDProto
MaxModes = 6;
}
- void SendInvite(const MessageSource &source, const Channel *c, User *u) anope_override
+ void SendInvite(const MessageSource &source, const Channel *c, User *u) override
{
- UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name << " " << c->creation_time;
+ Uplink::Send(source, "INVITE", u->GetUID(), c->name, c->creation_time);
}
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "NOTICE $$" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "NOTICE", "$$" + dest->GetName(), msg);
}
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "PRIVMSG $$" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "PRIVMSG", "$$" + dest->GetName(), msg);
}
- void SendSQLine(User *, const XLine *x) anope_override
+ void SendSQLine(User *, const XLine *x) override
{
- UplinkSocket::Message(Me) << "RESV * " << (x->expires ? x->expires - Anope::CurTime : 0) << " " << x->mask << " :" << x->reason;
+ Uplink::Send("RESV", '*', x->expires ? x->expires - Anope::CurTime : 0, x->mask, x->reason);
}
- void SendSGLineDel(const XLine *x) anope_override
+ void SendSGLineDel(const XLine *x) override
{
- UplinkSocket::Message(Me) << "UNXLINE * " << x->mask;
+ Uplink::Send("UNXLINE", '*', x->mask);
}
- void SendSGLine(User *, const XLine *x) anope_override
+ void SendSGLine(User *, const XLine *x) override
{
- UplinkSocket::Message(Me) << "XLINE * " << x->mask << " " << (x->expires ? x->expires - Anope::CurTime : 0) << " :" << x->GetReason();
+ Uplink::Send("XLINE", '*', x->mask, x->expires ? x->expires - Anope::CurTime : 0, x->GetReason());
}
- void SendSZLineDel(const XLine *x) anope_override
+ void SendSZLineDel(const XLine *x) override
{
- UplinkSocket::Message(Me) << "UNDLINE * " << x->GetHost();
+ Uplink::Send("UNDLINE", '*', x->GetHost());
}
- void SendSZLine(User *, const XLine *x) anope_override
+ void SendSZLine(User *, const XLine *x) override
{
- /* Calculate the time left before this would expire, capping it at 2 days */
- time_t timeleft = x->expires - Anope::CurTime;
-
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
-
- UplinkSocket::Message(Me) << "DLINE * " << timeleft << " " << x->GetHost() << " :" << x->GetReason();
+ /* Calculate the time left before this would expire */
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+ Uplink::Send("DLINE", '*', timeleft, x->GetHost(), x->GetReason());
}
- void SendAkillDel(const XLine *x) anope_override
+ void SendAkillDel(const XLine *x) override
{
if (x->IsRegex() || x->HasNickOrReal())
return;
- UplinkSocket::Message(Me) << "UNKLINE * " << x->GetUser() << " " << x->GetHost();
+ Uplink::Send("UNKLINE", '*', x->GetUser(), x->GetHost());
}
- void SendSQLineDel(const XLine *x) anope_override
+ void SendSQLineDel(const XLine *x) override
{
- UplinkSocket::Message(Me) << "UNRESV * " << x->mask;
+ Uplink::Send("UNRESV", '*', x->mask);
}
- void SendJoin(User *u, Channel *c, const ChannelStatus *status) anope_override
+ void SendJoin(User *u, Channel *c, const ChannelStatus *status) override
{
- UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :" << u->GetUID();
+ Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), u->GetUID());
/*
* Note that we can send this with the SJOIN but choose not to
@@ -122,15 +119,15 @@ class HybridProto : public IRCDProto
uc->status.Clear();
BotInfo *setter = BotInfo::Find(u->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), u->GetUID(), false);
+ for (auto mode : cs.Modes())
+ c->SetMode(setter, ModeManager::FindChannelModeByChar(mode), u->GetUID(), false);
if (uc)
uc->status = cs;
}
}
- void SendAkill(User *u, XLine *x) anope_override
+ void SendAkill(User *u, XLine *x) override
{
if (x->IsRegex() || x->HasNickOrReal())
{
@@ -140,9 +137,9 @@ class HybridProto : public IRCDProto
* No user (this akill was just added), and contains nick and/or realname.
* Find users that match and ban them.
*/
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (x->manager->Check(it->second, x))
- this->SendAkill(it->second, x);
+ for (const auto &[_, user] : UserListByNick)
+ if (x->manager->Check(user, x))
+ this->SendAkill(user, x);
return;
}
@@ -153,7 +150,7 @@ class HybridProto : public IRCDProto
return;
/* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
- XLine *xline = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
+ auto *xline = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
old->manager->AddXLine(xline);
x = xline;
@@ -162,26 +159,22 @@ class HybridProto : public IRCDProto
<< u->realname << " matches " << old->mask;
}
- /* Calculate the time left before this would expire, capping it at 2 days */
- time_t timeleft = x->expires - Anope::CurTime;
-
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
-
- UplinkSocket::Message(Me) << "KLINE * " << timeleft << " " << x->GetUser() << " " << x->GetHost() << " :" << x->GetReason();
+ /* Calculate the time left before this would expire */
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+ Uplink::Send("KLINE", '*', timeleft, x->GetUser(), x->GetHost(), x->GetReason());
}
- void SendServer(const Server *server) anope_override
+ void SendServer(const Server *server) override
{
if (server == Me)
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() + 1 << " " << server->GetSID() << " +" << " :" << server->GetDescription();
+ Uplink::Send("SERVER", server->GetName(), server->GetHops() + 1, server->GetSID(), '+', server->GetDescription());
else
- UplinkSocket::Message(Me) << "SID " << server->GetName() << " " << server->GetHops() + 1 << " " << server->GetSID() << " +" << " :" << server->GetDescription();
+ Uplink::Send("SID", server->GetName(), server->GetHops() + 1, server->GetSID(), '+', server->GetDescription());
}
- void SendConnect() anope_override
+ void SendConnect() override
{
- UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password;
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password);
/*
* TBURST - Supports topic burst
@@ -190,106 +183,104 @@ class HybridProto : public IRCDProto
* RHOST - Supports UID message with realhost information
* MLOCK - Supports MLOCK
*/
- UplinkSocket::Message() << "CAPAB :ENCAP TBURST EOB RHOST MLOCK";
+ Uplink::Send("CAPAB", "ENCAP", "TBURST", "EOB", "RHOST", "MLOCK");
SendServer(Me);
- UplinkSocket::Message(Me) << "SVINFO 6 6 0 :" << Anope::CurTime;
+ Uplink::Send("SVINFO", 6, 6, 0, Anope::CurTime);
}
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
-
- UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " "
- << u->host << " " << u->host << " 0.0.0.0 " << u->GetUID() << " * :" << u->realname;
+ Uplink::Send("UID", u->nick, 1, u->timestamp, "+" + u->GetModes(), u->GetIdent(), u->host, u->host, "0.0.0.0", u->GetUID(), '*', u->realname);
}
- void SendEOB() anope_override
+ void SendEOB() override
{
- UplinkSocket::Message(Me) << "EOB";
+ Uplink::Send("EOB");
}
- void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override
+ void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values) override
{
- UplinkSocket::Message(source) << "SVSMODE " << u->GetUID() << " " << u->timestamp << " " << buf;
+ auto params = values;
+ params.insert(params.begin(), { u->GetUID(), Anope::ToString(u->timestamp), modes });
+ Uplink::SendInternal({}, source, "SVSMODE", params);
}
- void SendLogin(User *u, NickAlias *na) anope_override
+ void SendLogin(User *u, NickAlias *na) override
{
- if (UseSVSAccount == false)
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %s", na->nc->display.c_str());
+ if (!UseSVSAccount)
+ IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", na->nc->display);
else
- UplinkSocket::Message(Me) << "SVSACCOUNT " << u->GetUID() << " " << u->timestamp << " " << na->nc->display;
+ Uplink::Send("SVSACCOUNT", u->GetUID(), u->timestamp, na->nc->display);
}
- void SendLogout(User *u) anope_override
+ void SendLogout(User *u) override
{
- if (UseSVSAccount == false)
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d *");
+ if (!UseSVSAccount)
+ IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", '*');
else
- UplinkSocket::Message(Me) << "SVSACCOUNT " << u->GetUID() << " " << u->timestamp << " *";
+ Uplink::Send("SVSACCOUNT", u->GetUID(), u->timestamp, '*');
}
- void SendChannel(Channel *c) anope_override
+ void SendChannel(Channel *c) override
{
- Anope::string modes = "+" + c->GetModes(true, true);
- UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " " << modes << " :";
+ Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), "");
}
- void SendTopic(const MessageSource &source, Channel *c) anope_override
+ void SendTopic(const MessageSource &source, Channel *c) override
{
- UplinkSocket::Message(source) << "TBURST " << c->creation_time << " " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic;
+ Uplink::Send(source, "TBURST", c->creation_time, c->name, c->topic_ts, c->topic_setter, c->topic);
}
- void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override
+ void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) override
{
- UplinkSocket::Message(Me) << "SVSNICK " << u->GetUID() << " " << u->timestamp << " " << newnick << " " << when;
+ Uplink::Send("SVSNICK", u->GetUID(), u->timestamp, newnick, when);
}
- void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) anope_override
+ void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &key) override
{
- UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
+ Uplink::Send(source, "SVSJOIN", u->GetUID(), chan);
}
- void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) anope_override
+ void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) override
{
if (!param.empty())
- UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
+ Uplink::Send(source, "SVSPART", u->GetUID(), chan, param);
else
- UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
+ Uplink::Send(source, "SVSPART", u->GetUID(), chan);
}
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override
+ void SendSVSHold(const Anope::string &nick, time_t t) override
{
- XLine x(nick, Me->GetName(), Anope::CurTime + t, "Being held for registered user");
+ XLine x(nick, Me->GetName(), Anope::CurTime + t, "Being held for a registered user");
this->SendSQLine(NULL, &x);
}
- void SendSVSHoldDel(const Anope::string &nick) anope_override
+ void SendSVSHoldDel(const Anope::string &nick) override
{
XLine x(nick);
this->SendSQLineDel(&x);
}
- void SendVhost(User *u, const Anope::string &ident, const Anope::string &host) anope_override
+ void SendVHost(User *u, const Anope::string &ident, const Anope::string &host) override
{
- UplinkSocket::Message(Me) << "SVSHOST " << u->GetUID() << " " << u->timestamp << " " << host;
+ Uplink::Send("SVSHOST", u->GetUID(), u->timestamp, host);
}
- void SendVhostDel(User *u) anope_override
+ void SendVHostDel(User *u) override
{
- UplinkSocket::Message(Me) << "SVSHOST " << u->GetUID() << " " << u->timestamp << " " << u->host;
+ Uplink::Send("SVSHOST", u->GetUID(), u->timestamp, u->host);
}
- bool IsExtbanValid(const Anope::string &mask) anope_override
+ bool IsExtbanValid(const Anope::string &mask) override
{
return mask.length() >= 4 && mask[0] == '$' && mask[2] == ':';
}
- bool IsIdentValid(const Anope::string &ident) anope_override
+ bool IsIdentValid(const Anope::string &ident) override
{
- if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
+ if (ident.empty() || ident.length() > IRCD->MaxUser)
return false;
/*
@@ -305,10 +296,8 @@ class HybridProto : public IRCDProto
if (a == '-' || a == '_' || a == '.')
return false;
- for (i = 0; i < ident.length(); ++i)
+ for (const auto c : ident)
{
- const char &c = ident[i];
-
/* A tilde can only be used as the first character of a user name. */
if (c == '~' && i == 0)
continue;
@@ -325,13 +314,14 @@ class HybridProto : public IRCDProto
}
};
-struct IRCDMessageBMask : IRCDMessage
+struct IRCDMessageBMask final
+ : IRCDMessage
{
- IRCDMessageBMask(Module *creator) : IRCDMessage(creator, "BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageBMask(Module *creator) : IRCDMessage(creator, "BMASK", 4) { SetFlag(FLAG_REQUIRE_SERVER); }
/* 0 1 2 3 */
/* :0MC BMASK 1350157102 #channel b :*!*@*.test.com */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Channel *c = Channel::Find(params[1]);
ChannelMode *mode = ModeManager::FindChannelModeByChar(params[2][0]);
@@ -347,13 +337,14 @@ struct IRCDMessageBMask : IRCDMessage
}
};
-struct IRCDMessageCapab : Message::Capab
+struct IRCDMessageCapab final
+ : Message::Capab
{
- IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(FLAG_SOFT_LIMIT); }
/* 0 */
/* CAPAB :TBURST EOB MLOCK */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
spacesepstream sep(params[0]);
Anope::string capab;
@@ -368,17 +359,17 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', 4));
}
- Message::Capab::Run(source, params);
+ Message::Capab::Run(source, params, tags);
}
};
struct IRCDMessageCertFP: IRCDMessage
{
- IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(FLAG_REQUIRE_USER); }
/* 0 */
/* :0MCAAAAAB CERTFP 4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = source.GetUser();
@@ -387,21 +378,23 @@ struct IRCDMessageCertFP: IRCDMessage
}
};
-struct IRCDMessageEOB : IRCDMessage
+struct IRCDMessageEOB final
+ : IRCDMessage
{
- IRCDMessageEOB(Module *creator) : IRCDMessage(creator, "EOB", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageEOB(Module *creator) : IRCDMessage(creator, "EOB", 0) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
source.GetServer()->Sync(true);
}
};
-struct IRCDMessageJoin : Message::Join
+struct IRCDMessageJoin final
+ : Message::Join
{
IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() < 2)
return;
@@ -409,17 +402,18 @@ struct IRCDMessageJoin : Message::Join
std::vector<Anope::string> p = params;
p.erase(p.begin());
- Message::Join::Run(source, p);
+ Message::Join::Run(source, p, tags);
}
};
-struct IRCDMessageMetadata : IRCDMessage
+struct IRCDMessageMetadata final
+ : IRCDMessage
{
- IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
/* 0 1 2 3 */
/* :0MC METADATA client 0MCAAAAAB certfp :4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params[0].equals_cs("client"))
{
@@ -439,13 +433,14 @@ struct IRCDMessageMetadata : IRCDMessage
}
};
-struct IRCDMessageMLock : IRCDMessage
+struct IRCDMessageMLock final
+ : IRCDMessage
{
- IRCDMessageMLock(Module *creator) : IRCDMessage(creator, "MLOCK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageMLock(Module *creator) : IRCDMessage(creator, "MLOCK", 4) { SetFlag(FLAG_REQUIRE_SERVER); }
/* 0 1 2 3 */
/* :0MC MLOCK 1350157102 #channel 1350158923 :nt */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Channel *c = Channel::Find(params[1]);
@@ -459,53 +454,57 @@ struct IRCDMessageMLock : IRCDMessage
// Mode lock string is not what we say it is?
if (modes != params[3])
- UplinkSocket::Message(Me) << "MLOCK " << c->creation_time << " " << c->name << " " << Anope::CurTime << " :" << modes;
+ Uplink::Send("MLOCK", c->creation_time, c->name, Anope::CurTime, modes);
}
}
};
-struct IRCDMessageNick : IRCDMessage
+struct IRCDMessageNick final
+ : IRCDMessage
{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(FLAG_REQUIRE_USER); }
/* 0 1 */
/* :0MCAAAAAB NICK newnick 1350157102 */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- source.GetUser()->ChangeNick(params[0], convertTo<time_t>(params[1]));
+ source.GetUser()->ChangeNick(params[0], IRCD->ExtractTimestamp(params[1]));
}
};
-struct IRCDMessagePass : IRCDMessage
+struct IRCDMessagePass final
+ : IRCDMessage
{
- IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 1) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
/* 0 */
/* PASS password */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() == 4)
UplinkSID = params[3];
}
};
-struct IRCDMessagePong : IRCDMessage
+struct IRCDMessagePong final
+ : IRCDMessage
{
- IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
source.GetServer()->Sync(false);
}
};
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
/* 0 1 2 3 4 */
/* SERVER hades.arpa 1 4XY + :ircd-hybrid test server */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/* Servers other than our immediate uplink are introduced via SID */
if (params[1] != "1")
@@ -523,37 +522,31 @@ struct IRCDMessageServer : IRCDMessage
}
};
-struct IRCDMessageSID : IRCDMessage
+struct IRCDMessageSID final
+ : IRCDMessage
{
- IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 5) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
/* 0 1 2 3 4 */
/* :0MC SID hades.arpa 2 4XY + :ircd-hybrid test server */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
+ auto hops = Anope::Convert(params[1], 0);
new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params.back(), params[2]);
IRCD->SendPing(Me->GetName(), params[0]);
}
};
-struct IRCDMessageSJoin : IRCDMessage
+struct IRCDMessageSJoin final
+ : IRCDMessage
{
- IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 4) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
/* 0 1 2 3 */
/* :0MC SJOIN 1654877335 #nether +nt :@0MCAAAAAB +0MCAAAAAC */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- Anope::string modes;
-
- for (unsigned i = 2; i < params.size() - 1; ++i)
- modes += " " + params[i];
-
- if (!modes.empty())
- modes.erase(modes.begin());
-
std::list<Message::Join::SJoinUser> users;
spacesepstream sep(params[params.size() - 1]);
@@ -580,42 +573,44 @@ struct IRCDMessageSJoin : IRCDMessage
users.push_back(sju);
}
- time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime;
- Message::Join::SJoin(source, params[1], ts, modes, users);
+ auto ts = IRCD->ExtractTimestamp(params[0]);
+ Message::Join::SJoin(source, params[1], ts, params[2], { params.begin() + 3, params.end() - 1 }, users);
}
};
-struct IRCDMessageSVSMode : IRCDMessage
+struct IRCDMessageSVSMode final
+ : IRCDMessage
{
- IRCDMessageSVSMode(Module *creator) : IRCDMessage(creator, "SVSMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageSVSMode(Module *creator) : IRCDMessage(creator, "SVSMODE", 3) { SetFlag(FLAG_SOFT_LIMIT); }
/* 0 1 2 */
/* :0MC SVSMODE 0MCAAAAAB 1350157102 +r */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = User::Find(params[0]);
if (!u)
return;
- if (!params[1].is_pos_number_only() || convertTo<time_t>(params[1]) != u->timestamp)
+ if (IRCD->ExtractTimestamp(params[1]) != u->timestamp)
return;
- u->SetModesInternal(source, "%s", params[2].c_str());
+ u->SetModesInternal(source, params[2]);
}
};
-struct IRCDMessageTBurst : IRCDMessage
+struct IRCDMessageTBurst final
+ : IRCDMessage
{
IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TBURST", 5) { }
/* 0 1 2 3 4 */
/* :0MC TBURST 1654867975 #nether 1654877335 Steve!~steve@the.mines :Join the ghast nation */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string setter;
sepstream(params[3], '!').GetToken(setter, 0);
- time_t topic_time = Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime;
+ auto topic_time = IRCD->ExtractTimestamp(params[2]);
Channel *c = Channel::Find(params[1]);
if (c)
@@ -623,40 +618,31 @@ struct IRCDMessageTBurst : IRCDMessage
}
};
-struct IRCDMessageTMode : IRCDMessage
+struct IRCDMessageTMode final
+ : IRCDMessage
{
- IRCDMessageTMode(Module *creator) : IRCDMessage(creator, "TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageTMode(Module *creator) : IRCDMessage(creator, "TMODE", 3) { SetFlag(FLAG_SOFT_LIMIT); }
/* 0 1 2 */
/* :0MC TMODE 1654867975 #nether +ntR */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- time_t ts = 0;
-
- try
- {
- ts = convertTo<time_t>(params[0]);
- }
- catch (const ConvertException &) { }
-
+ auto ts = IRCD->ExtractTimestamp(params[0]);
Channel *c = Channel::Find(params[1]);
- Anope::string modes = params[2];
-
- for (unsigned i = 3; i < params.size(); ++i)
- modes += " " + params[i];
if (c)
- c->SetModesInternal(source, modes, ts);
+ c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
}
};
-struct IRCDMessageUID : IRCDMessage
+struct IRCDMessageUID final
+ : IRCDMessage
{
- IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
/* 0 1 2 3 4 5 6 7 8 9 10 */
/* :0MC UID Steve 1 1350157102 +oi ~steve virtual.host real.host 10.0.0.1 0MCAAAAAB Steve :Mining all the time */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
NickAlias *na = NULL;
@@ -665,12 +651,12 @@ struct IRCDMessageUID : IRCDMessage
/* Source is always the server */
User::OnIntroduce(params[0], params[4], params[6], params[5], params[7], source.GetServer(), params[10],
- params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0,
- params[3], params[8], na ? *na->nc : NULL);
+ IRCD->ExtractTimestamp(params[2]), params[3], params[8], na ? *na->nc : NULL);
}
};
-class ProtoHybrid : public Module
+class ProtoHybrid final
+ : public Module
{
HybridProto ircd_proto;
@@ -713,9 +699,7 @@ class ProtoHybrid : public Module
IRCDMessageTMode message_tmode;
IRCDMessageUID message_uid;
- bool use_server_side_mlock;
-
- void AddModes()
+ static void AddModes()
{
/* Add user modes */
ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a'));
@@ -773,7 +757,7 @@ class ProtoHybrid : public Module
ModeManager::AddChannelMode(new ChannelModeNoone("ISSECURE", 'Z'));
}
- public:
+public:
ProtoHybrid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_away(this),
@@ -816,56 +800,51 @@ class ProtoHybrid : public Module
this->AddModes();
}
- void OnUserNickChange(User *u, const Anope::string &) anope_override
+ void OnUserNickChange(User *u, const Anope::string &) override
{
u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
}
- void OnReload(Configuration::Conf *conf) anope_override
- {
- use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- }
-
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
if (!c->ci)
return;
ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
- if (use_server_side_mlock && modelocks && Servers::Capab.count("MLOCK"))
+ if (modelocks && Servers::Capab.count("MLOCK"))
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- UplinkSocket::Message(Me) << "MLOCK " << c->creation_time << " " << c->ci->name << " " << Anope::CurTime << " :" << modes;
+ Uplink::Send("MLOCK", c->creation_time, c->ci->name, Anope::CurTime, modes);
}
}
- void OnDelChan(ChannelInfo *ci) anope_override
+ void OnDelChan(ChannelInfo *ci) override
{
- if (use_server_side_mlock && ci->c && Servers::Capab.count("MLOCK"))
- UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :";
+ if (ci->c && Servers::Capab.count("MLOCK"))
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, Anope::CurTime, "");
}
- EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
+ EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK"))
+ if (cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK"))
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
- UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :" << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, Anope::CurTime, modes);
}
return EVENT_CONTINUE;
}
- EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
+ EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK"))
+ if (cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK"))
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
- UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :" << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, Anope::CurTime, modes);
}
return EVENT_CONTINUE;
diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp
new file mode 100644
index 000000000..b0e059d73
--- /dev/null
+++ b/modules/protocol/inspircd.cpp
@@ -0,0 +1,2592 @@
+/* InspIRCd functions
+ *
+ * (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/cs_mode.h"
+#include "modules/encryption.h"
+#include "modules/httpd.h"
+#include "modules/ns_cert.h"
+#include "modules/sasl.h"
+
+typedef std::map<char, unsigned> ListLimits;
+
+struct SASLUser final
+{
+ Anope::string uid;
+ Anope::string acc;
+ time_t created;
+};
+
+namespace
+{
+ /** Whether we should send extbans using their named form. */
+ bool named_extbans = false;
+
+ // The SID of a server we are waiting to squit.
+ Anope::string rsquit_id;
+
+ // The hostname of a server we are waiting to squit.
+ Anope::string rsquit_server;
+
+ // Non-introduced users who have authenticated via SASL.
+ std::list<SASLUser> saslusers;
+
+ // A reference to the SHA-2 algorithm provider.
+ static ServiceReference<Encryption::Provider> sha256("Encryption::Provider", "sha256");
+
+ // The version of the InspIRCd protocol that we are using.
+ size_t spanningtree_proto_ver = 1205;
+
+ bool IsExtBan(const Anope::string &str, bool &inverted, Anope::string &name, Anope::string &value)
+ {
+ auto startpos = 0;
+ if (!str.empty() && str[0] == '!')
+ startpos++;
+
+ auto endpos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", startpos);
+ if (endpos == Anope::string::npos || str[endpos] != ':' || endpos+1 == str.length())
+ return false;
+
+ inverted = !!startpos;
+ name = str.substr(startpos, endpos - startpos);
+ value = str.substr(endpos + 1);
+ return true;
+ }
+
+ // Parses a module name in the format "m_foo.so=bar" to {foo, bar}.
+ void ParseModule(const Anope::string &module, Anope::string &modname, Anope::string &moddata)
+ {
+ size_t sep = module.find('=');
+
+ // Extract and clean up the module name.
+ modname = module.substr(0, sep);
+ if (modname.compare(0, 2, "m_", 2) == 0)
+ modname.erase(0, 2);
+
+ if (modname.length() > 3 && modname.compare(modname.length() - 3, 3, ".so", 3) == 0)
+ modname.erase(modname.length() - 3);
+
+ // Extract the module link data (if any).
+ moddata = (sep == Anope::string::npos) ? "" : module.substr(sep + 1);
+
+ if (Anope::ProtocolDebug)
+ Log(LOG_DEBUG) << "Parsed module: name=" << modname << " data=" << moddata;
+ }
+
+ void ParseModuleData(const Anope::string &moddata, Anope::map<Anope::string> &modmap)
+ {
+ sepstream datastream(moddata, '&');
+ for (Anope::string datapair; datastream.GetToken(datapair); )
+ {
+ size_t split = datapair.find('=');
+ std::pair<Anope::map<Anope::string>::iterator, bool> res;
+ if (split == Anope::string::npos)
+ res = modmap.emplace(datapair, "");
+ else
+ res = modmap.emplace(datapair.substr(0, split), HTTPUtils::URLDecode(datapair.substr(split + 1)));
+
+ if (Anope::ProtocolDebug && res.second)
+ Log(LOG_DEBUG) << "Parsed module data: key=" << res.first->first << " value=" << res.first->second;
+ }
+ }
+}
+
+class InspIRCdProto final
+ : public IRCDProto
+{
+private:
+ static Anope::string GetAccountNicks(NickAlias* na)
+ {
+ if (!na || Config->GetModule("nickserv")->Get<bool>("nonicknameownership"))
+ return {};
+
+ Anope::string nicks;
+ for (const auto &na : *na->nc->aliases)
+ nicks += " " + na->nick;
+ return nicks.substr(1);
+ }
+
+ static void SendChgIdentInternal(const Anope::string &uid, const Anope::string &vident)
+ {
+ if (!Servers::Capab.count("CHGIDENT"))
+ {
+ Log() << "Unable to change the vident of " << uid << " as the remote server does not have the chgident module loaded.";
+ return;
+ }
+ Uplink::Send("ENCAP", uid.substr(0, 3), "CHGIDENT", uid, vident);
+ }
+
+ static void SendChgHostInternal(const Anope::string &uid, const Anope::string &vhost)
+ {
+ if (!Servers::Capab.count("CHGHOST"))
+ {
+ Log() << "Unable to change the vhost of " << uid << " as the remote server does not have the chghost module loaded.";
+ return;
+ }
+ Uplink::Send("ENCAP", uid.substr(0, 3), "CHGHOST", uid, vhost);
+ }
+
+ static void SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason)
+ {
+ Uplink::Send("ADDLINE", xtype, mask, addedby, Anope::CurTime, duration, reason);
+ }
+
+ static void SendDelLine(const Anope::string &xtype, const Anope::string &mask)
+ {
+ Uplink::Send("DELLINE", xtype, mask);
+ }
+
+ static void SendAccount(const Anope::string &uid, NickAlias *na)
+ {
+ Uplink::Send("METADATA", uid, "accountid", na ? Anope::ToString(na->nc->GetId()) : Anope::string());
+ Uplink::Send("METADATA", uid, "accountname", na ? na->nc->display : Anope::string());
+ if (spanningtree_proto_ver >= 1206)
+ Uplink::Send("METADATA", uid, "accountnicks", GetAccountNicks(na));
+ }
+
+public:
+ PrimitiveExtensibleItem<ListLimits> maxlist;
+
+ InspIRCdProto(Module *creator) : IRCDProto(creator, "InspIRCd 3+"), maxlist(creator, "maxlist")
+ {
+ DefaultPseudoclientModes = "+oI";
+ CanSVSNick = true;
+ CanSVSJoin = true;
+ CanSetVHost = true;
+ CanSetVIdent = true;
+ CanSQLine = true;
+ CanSZLine = true;
+ CanCertFP = true;
+ RequiresID = true;
+ MaxModes = 0;
+ MaxLine = 0;
+ }
+
+ size_t GetMaxListFor(Channel *c, ChannelMode *cm) override
+ {
+ ListLimits *limits = maxlist.Get(c);
+ if (limits)
+ {
+ ListLimits::const_iterator limit = limits->find(cm->mchar);
+ if (limit != limits->end())
+ return limit->second;
+ }
+
+ // Fall back to the config limit if we can't find the mode.
+ return IRCDProto::GetMaxListFor(c, cm);
+ }
+
+
+ void SendConnect() override
+ {
+ Uplink::Send("CAPAB", "START", 1206);
+ Uplink::Send("CAPAB", "CAPABILITIES", "CASEMAPPING=" + Config->GetBlock("options")->Get<const Anope::string>("casemap", "ascii") + (sha256 ? " CHALLENGE=*" : ""));
+ Uplink::Send("CAPAB", "END");
+ }
+
+ void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) override
+ {
+ Anope::string mechlist;
+ for (const auto &mechanism : mechanisms)
+ mechlist += "," + mechanism;
+
+ Uplink::Send("METADATA", "*", "saslmechlist", mechanisms.empty() ? "" : mechlist.substr(1));
+ }
+
+ void SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) override
+ {
+ IRCDProto::SendSVSKill(source, user, buf);
+ user->KillInternal(source, buf);
+ }
+
+ void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) override
+ {
+ Uplink::Send("SVSNICK", u->GetUID(), newnick, when, u->timestamp);
+ }
+
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override
+ {
+ Uplink::Send(bi, "NOTICE", "$" + dest->GetName(), msg);
+ }
+
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override
+ {
+ Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg);
+ }
+
+ void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) override
+ {
+ if (spanningtree_proto_ver >= 1206)
+ {
+ IRCD->SendNotice(bi, target->GetUID(), msg, {
+ { "~context", context->name },
+ });
+ return;
+ }
+ IRCDProto::SendContextNotice(bi, target, context, msg);
+ }
+
+ void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg) override
+ {
+ if (spanningtree_proto_ver >= 1206)
+ {
+ IRCD->SendPrivmsg(bi, target->GetUID(), msg, {
+ { "~context", context->name },
+ });
+ return;
+ }
+ IRCDProto::SendContextPrivmsg(bi, target, context, msg);
+ }
+
+ void SendClearBans(const MessageSource &user, Channel *c, User* u) override
+ {
+ Uplink::Send(user, "SVSCMODE", u->GetUID(), c->name, 'b');
+ }
+
+ void SendPong(const Anope::string &servname, const Anope::string &who) override
+ {
+ Server *serv = servname.empty() ? NULL : Server::Find(servname);
+ if (!serv)
+ serv = Me;
+
+ Uplink::Send(serv, "PONG", who);
+ }
+
+ void SendAkillDel(const XLine *x) override
+ {
+ {
+ /* InspIRCd may support regex bans
+ * Mask is expected in format: 'n!u@h\sr' and spaces as '\s'
+ * We remove the '//' and replace '#' and any ' ' with '\s'
+ */
+ if (x->IsRegex() && Servers::Capab.count("RLINE"))
+ {
+ Anope::string mask = x->mask;
+ if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
+ mask = mask.substr(1, mask.length() - 2);
+ size_t h = mask.find('#');
+ if (h != Anope::string::npos)
+ {
+ mask = mask.replace(h, 1, "\\s");
+ mask = mask.replace_all_cs(" ", "\\s");
+ }
+ SendDelLine("R", mask);
+ return;
+ }
+ else if (x->IsRegex() || x->HasNickOrReal())
+ return;
+
+ /* ZLine if we can instead */
+ if (x->GetUser() == "*")
+ {
+ cidr addr(x->GetHost());
+ if (addr.valid())
+ {
+ IRCD->SendSZLineDel(x);
+ return;
+ }
+ }
+
+ SendDelLine("G", x->GetUser() + "@" + x->GetHost());
+ }
+ }
+
+ void SendInvite(const MessageSource &source, const Channel *c, User *u) override
+ {
+ Uplink::Send(source, "INVITE", u->GetUID(), c->name, c->creation_time);
+ }
+
+ void SendTopic(const MessageSource &source, Channel *c) override
+ {
+ if (Servers::Capab.count("TOPICLOCK"))
+ {
+ Uplink::Send(c->WhoSends(), "SVSTOPIC", c->name, c->topic_ts, c->topic_setter, c->topic);
+ }
+ else
+ {
+ /* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */
+ time_t ts = c->topic_ts;
+ if (c->topic_time > ts)
+ ts = Anope::CurTime;
+ /* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */
+ Uplink::Send(source, "FTOPIC", c->name, c->creation_time, ts, c->topic_setter, c->topic);
+ }
+ }
+
+ void SendVHostDel(User *u) override
+ {
+ UserMode *um = ModeManager::FindUserModeByName("CLOAK");
+
+ if (um && !u->HasMode(um->name))
+ // Just set +x if we can
+ u->SetMode(NULL, um);
+ else
+ // Try to restore cloaked host
+ this->SendChgHostInternal(u->nick, u->chost);
+ }
+
+ void SendAkill(User *u, XLine *x) override
+ {
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+
+ /* InspIRCd may support regex bans, if they do we can send this and forget about it
+ * Mask is expected in format: 'n!u@h\sr' and spaces as '\s'
+ * We remove the '//' and replace '#' and any ' ' with '\s'
+ */
+ if (x->IsRegex() && Servers::Capab.count("RLINE"))
+ {
+ Anope::string mask = x->mask;
+ if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
+ mask = mask.substr(1, mask.length() - 2);
+ size_t h = mask.find('#');
+ if (h != Anope::string::npos)
+ {
+ mask = mask.replace(h, 1, "\\s");
+ mask = mask.replace_all_cs(" ", "\\s");
+ }
+ SendAddLine("R", mask, timeleft, x->by, x->GetReason());
+ return;
+ }
+ else if (x->IsRegex() || x->HasNickOrReal())
+ {
+ if (!u)
+ {
+ /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
+ for (const auto &[_, user] : UserListByNick)
+ if (x->manager->Check(user, x))
+ this->SendAkill(user, x);
+ return;
+ }
+
+ const XLine *old = x;
+
+ if (old->manager->HasEntry("*@" + u->host))
+ return;
+
+ /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
+ x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
+ old->manager->AddXLine(x);
+
+ Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
+ }
+
+ /* ZLine if we can instead */
+ if (x->GetUser() == "*")
+ {
+ cidr addr(x->GetHost());
+ if (addr.valid())
+ {
+ IRCD->SendSZLine(u, x);
+ return;
+ }
+ }
+
+ SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->by, x->GetReason());
+ }
+
+ void SendNumericInternal(int numeric, const Anope::string &dest, const std::vector<Anope::string> &params) override
+ {
+ auto newparams = params;
+ newparams.insert(newparams.begin(), { Me->GetSID(), dest, Anope::ToString(numeric) });
+ Uplink::SendInternal({}, Me, "NUM", newparams);
+ }
+
+ void SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values) override
+ {
+ auto params = values;
+ params.insert(params.begin(), { chan->name, Anope::ToString(chan->creation_time), modes });
+ Uplink::SendInternal({}, source, "FMODE", params);
+ }
+
+ void SendClientIntroduction(User *u) override
+ {
+ if (spanningtree_proto_ver >= 1206)
+ {
+ Uplink::Send("UID", u->GetUID(), u->timestamp, u->nick, u->host, u->host, u->GetIdent(), u->GetIdent(),
+ "0.0.0.0", u->timestamp, "+" + u->GetModes(), u->realname);
+ }
+ else
+ {
+ Uplink::Send("UID", u->GetUID(), u->timestamp, u->nick, u->host, u->host, u->GetIdent(), "0.0.0.0",
+ u->timestamp, "+" + u->GetModes(), u->realname);
+ }
+
+ if (u->GetModes().find('o') != Anope::string::npos)
+ {
+ // Mark as introduced so we can send an oper type.
+ BotInfo *bi = BotInfo::Find(u->nick, true);
+ if (bi)
+ bi->introduced = true;
+
+ Uplink::Send(u, "OPERTYPE", "service");
+ }
+ }
+
+ void SendServer(const Server *server) override
+ {
+ /* if rsquit is set then we are waiting on a squit */
+ if (rsquit_id.empty() && rsquit_server.empty())
+ Uplink::Send("SERVER", server->GetName(), server->GetSID(), server->GetDescription());
+ }
+
+ void SendSquit(Server *s, const Anope::string &message) override
+ {
+ if (s != Me)
+ {
+ rsquit_id = s->GetSID();
+ rsquit_server = s->GetName();
+ Uplink::Send("RSQUIT", s->GetName(), message);
+ }
+ else
+ Uplink::Send("SQUIT", s->GetName(), message);
+ }
+
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override
+ {
+ Uplink::Send("FJOIN", c->name, c->creation_time, "+" + c->GetModes(true, true), "," + user->GetUID());
+ /* Note that we can send this with the FJOIN but choose not to
+ * because the mode stacker will handle this and probably will
+ * merge these modes with +nrt and other mlocked modes
+ */
+ if (status)
+ {
+ /* First save the channel status incase uc->Status == status */
+ ChannelStatus cs = *status;
+ /* If the user is internally on the channel with flags, kill them so that
+ * the stacker will allow this.
+ */
+ ChanUserContainer *uc = c->FindUser(user);
+ if (uc != NULL)
+ uc->status.Clear();
+
+ BotInfo *setter = BotInfo::Find(user->GetUID());
+ for (auto mode : cs.Modes())
+ c->SetMode(setter, ModeManager::FindChannelModeByChar(mode), user->GetUID(), false);
+
+ if (uc != NULL)
+ uc->status = cs;
+ }
+ }
+
+ void SendSQLineDel(const XLine *x) override
+ {
+ if (IRCD->CanSQLineChannel && (x->mask[0] == '#'))
+ SendDelLine("CBAN", x->mask);
+ else
+ SendDelLine("Q", x->mask);
+ }
+
+ void SendSQLine(User *u, const XLine *x) override
+ {
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+
+ if (IRCD->CanSQLineChannel && (x->mask[0] == '#'))
+ SendAddLine("CBAN", x->mask, timeleft, x->by, x->GetReason());
+ else
+ SendAddLine("Q", x->mask, timeleft, x->by, x->GetReason());
+ }
+
+ void SendVHost(User *u, const Anope::string &vident, const Anope::string &vhost) override
+ {
+ if (!vident.empty())
+ this->SendChgIdentInternal(u->GetUID(), vident);
+
+ if (!vhost.empty())
+ this->SendChgHostInternal(u->GetUID(), vhost);
+ }
+
+ void SendSVSHold(const Anope::string &nick, time_t t) override
+ {
+ Uplink::Send(Config->GetClient("NickServ"), "SVSHOLD", nick, t, "Being held for a registered user");
+ }
+
+ void SendSVSHoldDel(const Anope::string &nick) override
+ {
+ Uplink::Send(Config->GetClient("NickServ"), "SVSHOLD", nick);
+ }
+
+ void SendSZLineDel(const XLine *x) override
+ {
+ SendDelLine("Z", x->GetHost());
+ }
+
+ void SendSZLine(User *u, const XLine *x) override
+ {
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+
+ SendAddLine("Z", x->GetHost(), timeleft, x->by, x->GetReason());
+ }
+
+ void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &key) override
+ {
+ if (key.empty())
+ Uplink::Send(source, "SVSJOIN", u->GetUID(), chan);
+ else
+ Uplink::Send(source, "SVSJOIN", u->GetUID(), chan, key);
+ }
+
+ void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) override
+ {
+ if (!param.empty())
+ Uplink::Send(source, "SVSPART", u->GetUID(), chan, param);
+ else
+ Uplink::Send(source, "SVSPART", u->GetUID(), chan);
+ }
+
+ void SendSWhois(const MessageSource &bi, const Anope::string &who, const Anope::string &mask) override
+ {
+ User *u = User::Find(who);
+ Uplink::Send("METADATA", u->GetUID(), "swhois", mask);
+ }
+
+ void SendBOB() override
+ {
+ Uplink::Send("BURST", Anope::CurTime);
+ Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
+
+ if (spanningtree_proto_ver >= 1206)
+ {
+ Uplink::Send("SINFO", "customversion", Anope::printf("%s -- (%s) -- %s", IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str()));
+ Uplink::Send("SINFO", "rawbranch", "Anope-" + Anope::VersionShort());
+ }
+ else
+ {
+ Uplink::Send("SINFO", "version", Anope::printf("Anope-%s %s :%s -- (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str()));
+ Uplink::Send("SINFO", "fullversion", Anope::printf("Anope-%s %s :[%s] %s -- (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), Me->GetSID().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "none", Anope::VersionBuildString().c_str()));
+ }
+ Uplink::Send("SINFO", "rawversion", "Anope-" + Anope::VersionShort());
+ }
+
+ void SendEOB() override
+ {
+ Uplink::Send("ENDBURST");
+
+ if (spanningtree_proto_ver < 1206)
+ SendGlobops(Me, "Support for InspIRCd v3 is deprecated and will be removed in a future release. Please consider upgrading to InspIRCd v4.");
+ }
+
+ void SendGlobops(const MessageSource &source, const Anope::string &buf) override
+ {
+ if (Servers::Capab.count("GLOBOPS"))
+ Uplink::Send(source, "SNONOTICE", 'g', buf);
+ else
+ Uplink::Send(source, "SNONOTICE", "A", buf);
+ }
+
+ void SendLogin(User *u, NickAlias *na) override
+ {
+ /* InspIRCd uses an account to bypass chmode +R, not umode +r, so we can't send this here */
+ if (na->nc->HasExt("UNCONFIRMED"))
+ return;
+
+ IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
+ SendAccount(u->GetUID(), na);
+ }
+
+ void SendLogout(User *u) override
+ {
+ SendAccount(u->GetUID(), nullptr);
+ }
+
+ void SendChannel(Channel *c) override
+ {
+ Uplink::Send("FJOIN", c->name, c->creation_time, "+" + c->GetModes(true, true), "");
+ }
+
+ void SendSASLMessage(const SASL::Message &message) override
+ {
+ auto newparams = message.data;
+ newparams.insert(newparams.begin(), { message.target.substr(0, 3), "SASL", message.source, message.target, message.type });
+ Uplink::SendInternal({}, Me, "ENCAP", newparams);
+ }
+
+ void SendSVSLogin(const Anope::string &uid, NickAlias *na) override
+ {
+ SendAccount(uid, na);
+
+ // Expire old pending sessions or other sessions for this user.
+ for (auto it = saslusers.begin(); it != saslusers.end(); )
+ {
+ const SASLUser &u = *it;
+ if (u.created + 30 < Anope::CurTime || u.uid == uid)
+ it = saslusers.erase(it);
+ else
+ ++it;
+ }
+
+ if (na)
+ {
+ if (!na->GetVHostIdent().empty())
+ SendChgHostInternal(uid, na->GetVHostIdent());
+
+ if (!na->GetVHostHost().empty())
+ SendChgHostInternal(uid, na->GetVHostHost());
+
+ // Mark this SASL session as pending user introduction.
+ SASLUser su;
+ su.uid = uid;
+ su.acc = na->nc->display;
+ su.created = Anope::CurTime;
+ saslusers.push_back(su);
+ }
+ }
+
+ void SendOper(User *u) override
+ {
+ if (spanningtree_proto_ver < 1206)
+ return; // We can't force an oper on this version.
+
+ const Anope::map<Anope::string> tags = {
+ { "~automatic", "" },
+ };
+ Uplink::Send(tags, "SVSOPER", u->GetUID(), u->Account()->o->ot->GetName());
+ }
+
+ bool IsExtbanValid(const Anope::string &mask) override
+ {
+ bool inverted;
+ Anope::string name, value;
+ return IsExtBan(mask, inverted, name, value);
+ }
+
+ bool IsIdentValid(const Anope::string &ident) override
+ {
+ if (ident.empty() || ident.length() > IRCD->MaxUser)
+ return false;
+
+ for (auto c : ident)
+ {
+ if (c >= 'A' && c <= '}')
+ continue;
+
+ if ((c >= '0' && c <= '9') || c == '-' || c == '.')
+ continue;
+
+ return false;
+ }
+
+ return true;
+ }
+
+ bool IsTagValid(const Anope::string &tname, const Anope::string &tvalue) override
+ {
+ // InspIRCd accepts arbitrary message tags.
+ return true;
+ }
+};
+
+class InspIRCdAutoOpMode final
+ : public ChannelModeList
+{
+public:
+ InspIRCdAutoOpMode(char mode) : ChannelModeList("AUTOOP", mode)
+ {
+ }
+
+ bool IsValid(Anope::string &mask) const override
+ {
+ // We can not validate this because we don't know about the
+ // privileges of the setter so just reject attempts to set it.
+ return false;
+ }
+};
+
+// NOTE: matchers for the following extbans have not been implemented:
+//
+// * class(n): data not available
+// * country(G): data not available
+// * gateway(w): data not available in v3
+// * oper(o): todo
+// * realmask(a): todo
+namespace InspIRCdExtBan
+{
+ class Base
+ : public ChannelModeVirtual<ChannelModeList>
+ {
+ private:
+ unsigned char xbchar;
+ Anope::string xbname;
+
+ public:
+ Base(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : ChannelModeVirtual<ChannelModeList>(mname, "BAN")
+ , xbchar(xchar)
+ , xbname(xname)
+ {
+ }
+
+ ChannelMode *Wrap(Anope::string &param) override
+ {
+ auto xbprefix = named_extbans || !xbchar ? xbname : Anope::string(xbchar);
+ param = xbprefix + ":" + param;
+ return ChannelModeVirtual<ChannelModeList>::Wrap(param);
+ }
+
+ ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override
+ {
+ // The mask must be in the format [!]<letter>:<value> or [!]<name>:<value>.
+ if (cm->type != MODE_LIST)
+ return cm;
+
+ bool inverted;
+ Anope::string name, value;
+ if (!IsExtBan(param, inverted, name, value))
+ return cm;
+
+ if (name.length() == 1 ? name[0] != xbchar : name != xbname)
+ return cm;
+
+ param = value;
+ return this;
+ }
+ };
+
+ class EntryMatcher final
+ : public Base
+ {
+ public:
+ EntryMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ return Entry(this->name, e->GetMask()).Matches(u);
+ }
+ };
+
+ class ChannelMatcher final
+ : public Base
+ {
+ public:
+ ChannelMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ auto channel = e->GetMask();
+ ChannelMode *cm = NULL;
+ if (channel[0] != '#')
+ {
+ char modeChar = ModeManager::GetStatusChar(channel[0]);
+ channel.erase(channel.begin());
+ cm = ModeManager::FindChannelModeByChar(modeChar);
+ if (cm != NULL && cm->type != MODE_STATUS)
+ cm = NULL;
+ }
+
+ Channel *c = Channel::Find(channel);
+ if (c != NULL)
+ {
+ ChanUserContainer *uc = c->FindUser(u);
+ if (uc != NULL)
+ if (cm == NULL || uc->status.HasMode(cm->mchar))
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ class AccountMatcher final
+ : public Base
+ {
+ public:
+ AccountMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ return u->IsIdentified() && e->GetMask().equals_ci(u->Account()->display);
+ }
+ };
+
+ class RealnameMatcher final
+ : public Base
+ {
+ public:
+ RealnameMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ return Anope::Match(u->realname, e->GetMask());
+ }
+ };
+
+ class ServerMatcher final
+ : public Base
+ {
+ public:
+ ServerMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ return Anope::Match(u->server->GetName(), e->GetMask());
+ }
+ };
+
+ class FingerprintMatcher final
+ : public Base
+ {
+ public:
+ FingerprintMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ return !u->fingerprint.empty() && Anope::Match(u->fingerprint, e->GetMask());
+ }
+ };
+
+ class UnidentifiedMatcher final
+ : public Base
+ {
+ public:
+ UnidentifiedMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ return !u->Account() && Entry(this->base, e->GetMask()).Matches(u);
+ }
+ };
+
+ class OperTypeMatcher
+ : public Base
+ {
+ public:
+ OperTypeMatcher(const Anope::string &mname, const Anope::string &xname, char xchar)
+ : Base(mname, xname, xchar)
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ Anope::string *opertype = u->GetExt<Anope::string>("opertype");
+ if (!opertype)
+ return false; // Not an operator.
+
+ return Anope::Match(opertype->replace_all_cs(' ', '_'), e->GetMask());
+ }
+ };
+}
+
+class ColonDelimitedParamMode
+ : public ChannelModeParam
+{
+public:
+ ColonDelimitedParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
+
+ bool IsValid(Anope::string &value) const override
+ {
+ return IsValid(value, false);
+ }
+
+ static bool IsValid(const Anope::string &value, bool historymode)
+ {
+ if (value.empty())
+ return false; // empty param is never valid
+
+ Anope::string::size_type pos = value.find(':');
+ if ((pos == Anope::string::npos) || (pos == 0))
+ return false; // no ':' or it's the first char, both are invalid
+
+ Anope::string rest;
+ if (Anope::Convert<int>(value, 0, &rest) <= 0)
+ return false; // negative numbers and zero are invalid
+
+ rest = rest.substr(1);
+ if (historymode)
+ {
+ // For the history mode, the part after the ':' is a duration and it
+ // can be in the user friendly "1d3h20m" format, make sure we accept that
+ return Anope::DoTime(rest) <= 0;
+ }
+ else
+ {
+ return Anope::Convert(rest, 0) <= 0;
+ }
+ }
+};
+
+class SimpleNumberParamMode final
+ : public ChannelModeParam
+{
+public:
+ SimpleNumberParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
+
+ bool IsValid(Anope::string &value) const override
+ {
+ if (value.empty())
+ return false; // empty param is never valid
+
+ return Anope::Convert<int>(value, 0) <= 0;
+ }
+};
+
+class ChannelModeFlood final
+ : public ColonDelimitedParamMode
+{
+public:
+ ChannelModeFlood(char modeChar) : ColonDelimitedParamMode("FLOOD", modeChar) { }
+
+ bool IsValid(Anope::string &value) const override
+ {
+ // The parameter of this mode is a bit different, it may begin with a '*',
+ // ignore it if that's the case
+ Anope::string v = value[0] == '*' ? value.substr(1) : value;
+ return ((!value.empty()) && (ColonDelimitedParamMode::IsValid(v)));
+ }
+};
+
+class ChannelModeHistory final
+ : public ColonDelimitedParamMode
+{
+public:
+ ChannelModeHistory(char modeChar) : ColonDelimitedParamMode("HISTORY", modeChar) { }
+
+ bool IsValid(Anope::string &value) const override
+ {
+ return (ColonDelimitedParamMode::IsValid(value, true));
+ }
+};
+
+class ChannelModeRedirect final
+ : public ChannelModeParam
+{
+public:
+ ChannelModeRedirect(char modeChar) : ChannelModeParam("REDIRECT", modeChar, true) { }
+
+ bool IsValid(Anope::string &value) const override
+ {
+ // The parameter of this mode is a channel, and channel names start with '#'
+ return ((!value.empty()) && (value[0] == '#'));
+ }
+};
+
+struct IRCDMessageAway final
+ : Message::Away
+{
+ IRCDMessageAway(Module *creator) : Message::Away(creator, "AWAY") { SetFlag(FLAG_REQUIRE_USER); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ std::vector<Anope::string> newparams(params);
+ if (newparams.size() > 1)
+ newparams.erase(newparams.begin());
+
+ Message::Away::Run(source, newparams, tags);
+ }
+};
+
+struct IRCDMessageCapab final
+ : IRCDMessage
+{
+ struct ExtBanInfo final
+ {
+ // The letter assigned to the extban.
+ char letter = 0;
+
+ // The name of the extban.
+ Anope::string name;
+
+ // The type of extban.
+ Anope::string type;
+ };
+
+ struct ModeInfo final
+ {
+ // The letter assigned to the mode.
+ char letter = 0;
+
+ // If a prefix mode then the rank of the prefix.
+ unsigned level = 0;
+
+ // The name of the mode.
+ Anope::string name;
+
+ // If a prefix mode then the symbol associated with the prefix.
+ char symbol = 0;
+
+ // The type of mode.
+ Anope::string type;
+ };
+
+ // The HMAC challenge sent by the remote server.
+ Anope::string challenge;
+
+ Anope::string GetPassword()
+ {
+ if (challenge.empty() || !sha256)
+ return Config->Uplinks[Anope::CurrentUplink].password;
+
+ Anope::string b64challenge;
+ Anope::B64Encode(sha256->HMAC(Config->Uplinks[Anope::CurrentUplink].password, challenge), b64challenge);
+ challenge.clear();
+
+ return "AUTH:" + b64challenge.rtrim('=');
+ }
+
+ static std::pair<Anope::string, Anope::string> ParseCapability(const Anope::string &token)
+ {
+ Anope::string key;
+ Anope::string value;
+ auto sep = token.find('=');
+ if (sep == Anope::string::npos)
+ {
+ // FOO
+ key = token;
+ }
+ else
+ {
+ // FOO=bar
+ key = token.substr(0, sep);
+ value = token.substr(sep + 1);
+ }
+
+ if (Anope::ProtocolDebug)
+ Log(LOG_DEBUG) << "Parsed capability: key=" << key << " value=" << value;
+
+ return { key, value };
+ }
+
+ static bool ParseExtBan(const Anope::string &token, ExtBanInfo &extban)
+ {
+ // acting:foo=f matching:bar=b matching:baz
+ // A B A B A
+ auto a = token.find(':');
+ if (a == Anope::string::npos)
+ return false;
+
+ auto b = token.find('=', a + 1);
+ if (b == Anope::string::npos)
+ {
+ // ExtBan only has a name.
+ extban.name = token.substr(a + 1);
+ }
+ else
+ {
+ // ExtBan has a name and letter.
+ extban.name = token.substr(a + 1, b - a - 1);
+ extban.letter = token[b + 1];
+ }
+ extban.type = token.substr(0, a);
+
+ if (Anope::ProtocolDebug)
+ Log(LOG_DEBUG) << "Parsed extban: type=" << extban.type << " name=" << extban.name << " letter=" << extban.letter;
+ return true;
+ }
+
+ static bool ParseMode(const Anope::string &token, ModeInfo &mode)
+ {
+ // list:ban=b param-set:limit=l param:key=k prefix:30000:op=@o simple:noextmsg=n
+ // A C A C A C A B C A C
+ Anope::string::size_type a = token.find(':');
+ if (a == Anope::string::npos)
+ return false;
+
+ // If the mode is a prefix mode then it also has a rank.
+ mode.type = token.substr(0, a);
+ if (mode.type == "prefix")
+ {
+ Anope::string::size_type b = token.find(':', a + 1);
+ if (b == Anope::string::npos)
+ return false;
+
+ const Anope::string modelevel = token.substr(a + 1, b - a - 1);
+ mode.level = Anope::Convert<unsigned>(modelevel, 0);
+ a = b;
+ }
+
+ Anope::string::size_type c = token.find('=', a + 1);
+ if (c == Anope::string::npos)
+ return false;
+
+ mode.name = token.substr(a + 1, c - a - 1);
+ switch (token.length() - c)
+ {
+ case 2:
+ mode.letter = token[c + 1];
+ break;
+ case 3:
+ mode.symbol = token[c + 1];
+ mode.letter = token[c + 2];
+ break;
+ default:
+ return false;
+ }
+
+ if (Anope::ProtocolDebug)
+ {
+ Log(LOG_DEBUG) << "Parsed mode: type=" << mode.type << " name=" << mode.name << " level="
+ << mode.level << " symbol=" << mode.symbol << " letter=" << mode.letter;
+ }
+ return true;
+ }
+
+ IRCDMessageCapab(Module *creator)
+ : IRCDMessage(creator, "CAPAB", 1)
+ {
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (params[0].equals_cs("START"))
+ {
+ spanningtree_proto_ver = 0;
+ if (params.size() >= 2)
+ spanningtree_proto_ver = Anope::Convert<size_t>(params[1], 0);
+
+ if (spanningtree_proto_ver < 1205)
+ throw ProtocolException("Protocol mismatch, no or invalid protocol version given in CAPAB START.");
+
+ Servers::Capab.clear();
+ IRCD->CanClearBans = false;
+ IRCD->CanSQLineChannel = false;
+ IRCD->CanSVSHold = false;
+ IRCD->CanTagMessage = false;
+ IRCD->DefaultPseudoclientModes = "+oI";
+ }
+ else if (params[0].equals_cs("CHANMODES") && params.size() > 1)
+ {
+ spacesepstream ssep(params[1]);
+ Anope::string capab;
+
+ while (ssep.GetToken(capab))
+ {
+ ModeInfo mode;
+ if (!ParseMode(capab, mode))
+ continue;
+
+ ChannelMode *cm = NULL;
+ if (mode.name.equals_cs("admin"))
+ cm = new ChannelModeStatus("PROTECT", mode.letter, mode.symbol, mode.level);
+ else if (mode.name.equals_cs("allowinvite"))
+ {
+ cm = new ChannelMode("ALLINVITE", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("INVITEBAN", "", 'A'));
+ }
+ else if (mode.name.equals_cs("auditorium"))
+ cm = new ChannelMode("AUDITORIUM", mode.letter);
+ else if (mode.name.equals_cs("autoop"))
+ cm = new InspIRCdAutoOpMode(mode.letter);
+ else if (mode.name.equals_cs("ban"))
+ cm = new ChannelModeList("BAN", mode.letter);
+ else if (mode.name.equals_cs("banexception"))
+ cm = new ChannelModeList("EXCEPT", mode.letter);
+ else if (mode.name.equals_cs("blockcaps"))
+ {
+ cm = new ChannelMode("BLOCKCAPS", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("BLOCKCAPSBAN", "", 'B'));
+ }
+ else if (mode.name.equals_cs("blockcolor"))
+ {
+ cm = new ChannelMode("BLOCKCOLOR", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("BLOCKCOLORBAN", "", 'c'));
+ }
+ else if (mode.name.equals_cs("c_registered"))
+ cm = new ChannelModeNoone("REGISTERED", mode.letter);
+ else if (mode.name.equals_cs("censor"))
+ cm = new ChannelMode("CENSOR", mode.letter);
+ else if (mode.name.equals_cs("delayjoin"))
+ cm = new ChannelMode("DELAYEDJOIN", mode.letter);
+ else if (mode.name.equals_cs("delaymsg"))
+ cm = new SimpleNumberParamMode("DELAYMSG", mode.letter);
+ else if (mode.name.equals_cs("filter"))
+ cm = new ChannelModeList("FILTER", mode.letter);
+ else if (mode.name.equals_cs("flood"))
+ cm = new ChannelModeFlood(mode.letter);
+ else if (mode.name.equals_cs("founder"))
+ cm = new ChannelModeStatus("OWNER", mode.letter, mode.symbol, mode.level);
+ else if (mode.name.equals_cs("halfop"))
+ cm = new ChannelModeStatus("HALFOP", mode.letter, mode.symbol, mode.level);
+ else if (mode.name.equals_cs("history"))
+ cm = new ChannelModeHistory(mode.letter);
+ else if (mode.name.equals_cs("invex"))
+ cm = new ChannelModeList("INVITEOVERRIDE", mode.letter);
+ else if (mode.name.equals_cs("inviteonly"))
+ cm = new ChannelMode("INVITE", mode.letter);
+ else if (mode.name.equals_cs("joinflood"))
+ cm = new ColonDelimitedParamMode("JOINFLOOD", mode.letter);
+ else if (mode.name.equals_cs("key"))
+ cm = new ChannelModeKey(mode.letter);
+ else if (mode.name.equals_cs("kicknorejoin"))
+ cm = new SimpleNumberParamMode("NOREJOIN", mode.letter);
+ else if (mode.name.equals_cs("limit"))
+ cm = new ChannelModeParam("LIMIT", mode.letter, true);
+ else if (mode.name.equals_cs("moderated"))
+ cm = new ChannelMode("MODERATED", mode.letter);
+ else if (mode.name.equals_cs("nickflood"))
+ cm = new ColonDelimitedParamMode("NICKFLOOD", mode.letter);
+ else if (mode.name.equals_cs("noctcp"))
+ {
+ cm = new ChannelMode("NOCTCP", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("NOCTCPBAN", "", 'C'));
+ }
+ else if (mode.name.equals_cs("noextmsg"))
+ cm = new ChannelMode("NOEXTERNAL", mode.letter);
+ else if (mode.name.equals_cs("nokick"))
+ {
+ cm = new ChannelMode("NOKICK", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("NOKICKBAN", "", 'Q'));
+ }
+ else if (mode.name.equals_cs("noknock"))
+ cm = new ChannelMode("NOKNOCK", mode.letter);
+ else if (mode.name.equals_cs("nonick"))
+ {
+ cm = new ChannelMode("NONICK", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("NONICKBAN", "", 'N'));
+ }
+ else if (mode.name.equals_cs("nonotice"))
+ {
+ cm = new ChannelMode("NONOTICE", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("NONOTICEBAN", "", 'T'));
+ }
+ else if (mode.name.equals_cs("official-join"))
+ cm = new ChannelModeStatus("OFFICIALJOIN", mode.letter, mode.symbol, mode.level);
+ else if (mode.name.equals_cs("op"))
+ cm = new ChannelModeStatus("OP", mode.letter, mode.symbol, mode.level);
+ else if (mode.name.equals_cs("operonly"))
+ {
+ cm = new ChannelModeOperOnly("OPERONLY", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::OperTypeMatcher("OPERTYPEBAN", "", 'O'));
+ }
+ else if (mode.name.equals_cs("operprefix"))
+ cm = new ChannelModeStatus("OPERPREFIX", mode.letter, mode.symbol, mode.level);
+ else if (mode.name.equals_cs("permanent"))
+ cm = new ChannelMode("PERM", mode.letter);
+ else if (mode.name.equals_cs("private"))
+ cm = new ChannelMode("PRIVATE", mode.letter);
+ else if (mode.name.equals_cs("redirect"))
+ cm = new ChannelModeRedirect(mode.letter);
+ else if (mode.name.equals_cs("reginvite"))
+ cm = new ChannelMode("REGISTEREDONLY", mode.letter);
+ else if (mode.name.equals_cs("regmoderated"))
+ cm = new ChannelMode("REGMODERATED", mode.letter);
+ else if (mode.name.equals_cs("secret"))
+ cm = new ChannelMode("SECRET", mode.letter);
+ else if (mode.name.equals_cs("sslonly"))
+ {
+ cm = new ChannelMode("SSL", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::FingerprintMatcher("SSLBAN", "", 'z'));
+ }
+ else if (mode.name.equals_cs("stripcolor"))
+ {
+ cm = new ChannelMode("STRIPCOLOR", mode.letter);
+ if (spanningtree_proto_ver < 1206)
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("STRIPCOLORBAN", "", 'S'));
+ }
+ else if (mode.name.equals_cs("topiclock"))
+ cm = new ChannelMode("TOPIC", mode.letter);
+ else if (mode.name.equals_cs("voice"))
+ cm = new ChannelModeStatus("VOICE", mode.letter, mode.symbol, mode.level);
+
+ // Handle unknown modes.
+ else if (mode.type.equals_cs("list"))
+ cm = new ChannelModeList(mode.name.upper(), mode.letter);
+ else if (mode.type.equals_cs("param-set"))
+ cm = new ChannelModeParam(mode.name.upper(), mode.letter, true);
+ else if (mode.type.equals_cs("param"))
+ cm = new ChannelModeParam(mode.name.upper(), mode.letter, false);
+ else if (mode.type.equals_cs("prefix"))
+ cm = new ChannelModeStatus(mode.name.upper(), mode.letter, mode.symbol, mode.level);
+ else if (mode.type.equals_cs("simple"))
+ cm = new ChannelMode(mode.name.upper(), mode.letter);
+ else
+ Log(LOG_DEBUG) << "Unknown channel mode: " << capab;
+
+ if (cm)
+ ModeManager::AddChannelMode(cm);
+ }
+ }
+ if (params[0].equals_cs("USERMODES") && params.size() > 1)
+ {
+ spacesepstream ssep(params[1]);
+ Anope::string capab;
+
+ while (ssep.GetToken(capab))
+ {
+ ModeInfo mode;
+ if (!ParseMode(capab, mode))
+ continue;
+
+ UserMode *um = NULL;
+ if (mode.name.equals_cs("bot"))
+ {
+ um = new UserMode("BOT", mode.letter);
+ IRCD->DefaultPseudoclientModes += mode.letter;
+ }
+ else if (mode.name.equals_cs("callerid"))
+ um = new UserMode("CALLERID", mode.letter);
+ else if (mode.name.equals_cs("cloak"))
+ um = new UserMode("CLOAK", mode.letter);
+ else if (mode.name.equals_cs("deaf"))
+ um = new UserMode("DEAF", mode.letter);
+ else if (mode.name.equals_cs("deaf_commonchan"))
+ um = new UserMode("COMMONCHANS", mode.letter);
+ else if (mode.name.equals_cs("helpop"))
+ um = new UserModeOperOnly("HELPOP", mode.letter);
+ else if (mode.name.equals_cs("hidechans"))
+ um = new UserMode("PRIV", mode.letter);
+ else if (mode.name.equals_cs("hideoper"))
+ um = new UserModeOperOnly("HIDEOPER", mode.letter);
+ else if (mode.name.equals_cs("invisible"))
+ um = new UserMode("INVIS", mode.letter);
+ else if (mode.name.equals_cs("invis-oper"))
+ um = new UserModeOperOnly("INVISIBLE_OPER", mode.letter);
+ else if (mode.name.equals_cs("oper"))
+ um = new UserModeOperOnly("OPER", mode.letter);
+ else if (mode.name.equals_cs("regdeaf"))
+ um = new UserMode("REGPRIV", mode.letter);
+ else if (mode.name.equals_cs("servprotect"))
+ {
+ um = new UserModeNoone("PROTECTED", mode.letter);
+ IRCD->DefaultPseudoclientModes += mode.letter;
+ }
+ else if (mode.name.equals_cs("showwhois"))
+ um = new UserMode("WHOIS", mode.letter);
+ else if (mode.name.equals_cs("u_censor"))
+ um = new UserMode("CENSOR", mode.letter);
+ else if (mode.name.equals_cs("u_registered"))
+ um = new UserModeNoone("REGISTERED", mode.letter);
+ else if (mode.name.equals_cs("u_stripcolor"))
+ um = new UserMode("STRIPCOLOR", mode.letter);
+ else if (mode.name.equals_cs("wallops"))
+ um = new UserMode("WALLOPS", mode.letter);
+
+ // Handle unknown modes.
+ else if (mode.type.equals_cs("param-set"))
+ um = new UserModeParam(mode.name.upper(), mode.letter);
+ else if (mode.type.equals_cs("simple"))
+ um = new UserMode(mode.name.upper(), mode.letter);
+ else
+ Log(LOG_DEBUG) << "Unknown user mode: " << capab;
+
+ if (um)
+ ModeManager::AddUserMode(um);
+ }
+ }
+ else if (params[0].equals_cs("EXTBANS"))
+ {
+ spacesepstream ssep(params[1]);
+ Anope::string capab;
+
+ while (ssep.GetToken(capab))
+ {
+ ExtBanInfo extban;
+ if (!ParseExtBan(capab, extban))
+ continue;
+
+ InspIRCdExtBan::Base *xb = nullptr;
+ if (extban.name.equals_cs("account"))
+ xb = new InspIRCdExtBan::AccountMatcher("ACCOUNTBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("blockcolor"))
+ xb = new InspIRCdExtBan::EntryMatcher("BLOCKCOLORBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("blockinvite"))
+ xb = new InspIRCdExtBan::EntryMatcher("INVITEBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("channel"))
+ xb = new InspIRCdExtBan::ChannelMatcher("CHANNELBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("fingerprint"))
+ xb = new InspIRCdExtBan::FingerprintMatcher("SSLBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("mute"))
+ xb = new InspIRCdExtBan::EntryMatcher("QUIET", extban.name, extban.letter);
+ else if (extban.name.equals_cs("noctcp"))
+ xb = new InspIRCdExtBan::EntryMatcher("NOCTCPBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("nokick"))
+ xb = new InspIRCdExtBan::EntryMatcher("NOKICKBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("nonick"))
+ xb = new InspIRCdExtBan::EntryMatcher("NONICKBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("nonotice"))
+ xb = new InspIRCdExtBan::EntryMatcher("NONOTICEBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("opertype"))
+ xb = new InspIRCdExtBan::OperTypeMatcher("OPERTYPEBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("opmoderated"))
+ xb = new InspIRCdExtBan::EntryMatcher("OPMODERATEDBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("realname"))
+ xb = new InspIRCdExtBan::RealnameMatcher("REALNAMEBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("server"))
+ xb = new InspIRCdExtBan::ServerMatcher("SERVERBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("stripcolor"))
+ xb = new InspIRCdExtBan::EntryMatcher("STRIPCOLORBAN", extban.name, extban.letter);
+ else if (extban.name.equals_cs("unauthed"))
+ xb = new InspIRCdExtBan::UnidentifiedMatcher("UNREGISTEREDBAN", extban.name, extban.letter);
+
+ // Handle unknown extbans.
+ else if (extban.type.equals_cs("acting"))
+ xb = new InspIRCdExtBan::EntryMatcher(extban.name.upper() + "BAN", extban.name, extban.letter);
+ else
+ Log(LOG_DEBUG) << "Unknown extban: " << capab;
+
+ if (xb)
+ ModeManager::AddChannelMode(xb);
+ }
+ }
+
+ else if ((params[0].equals_cs("MODULES") || params[0].equals_cs("MODSUPPORT")) && params.size() > 1)
+ {
+ spacesepstream ssep(params[1]);
+ Anope::string module;
+
+ Anope::string inspircdregex;
+ while (ssep.GetToken(module))
+ {
+ Anope::string modname, moddata;
+ ParseModule(module, modname, moddata);
+
+ if (spanningtree_proto_ver >= 1206)
+ {
+ // InspIRCd v4
+ Anope::map<Anope::string> modmap;
+ ParseModuleData(moddata, modmap);
+
+ if (modname.equals_cs("account"))
+ Servers::Capab.insert("ACCOUNT");
+
+ else if (modname.equals_cs("cban"))
+ IRCD->CanSQLineChannel = true;
+
+ else if (modname.equals_cs("globops"))
+ Servers::Capab.insert("GLOBOPS");
+
+ else if (modname.equals_cs("rline"))
+ {
+ Servers::Capab.insert("RLINE");
+ auto iter = modmap.find("regex");
+ if (iter != modmap.end())
+ inspircdregex = "regex/" + iter->second;
+ }
+
+ else if (modname.equals_cs("services"))
+ {
+ IRCD->CanClearBans = true;
+ IRCD->CanSVSHold = true;
+ Servers::Capab.insert("SERVICES");
+ Servers::Capab.insert("TOPICLOCK");
+ }
+ }
+ else
+ {
+ // InspIRCd v3
+ if (modname.equals_cs("cban") && moddata.equals_cs("glob"))
+ IRCD->CanSQLineChannel = true;
+
+ else if (modname.equals_cs("channelban"))
+ ModeManager::AddChannelMode(new InspIRCdExtBan::ChannelMatcher("CHANNELBAN", "", 'j'));
+
+ else if (modname.equals_cs("gecosban"))
+ ModeManager::AddChannelMode(new InspIRCdExtBan::RealnameMatcher("REALNAMEBAN", "", 'r'));
+
+ else if (modname.equals_cs("muteban"))
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("QUIET", "", 'm'));
+
+ else if (modname.equals_cs("nopartmsg"))
+ ModeManager::AddChannelMode(new InspIRCdExtBan::EntryMatcher("PARTMESSAGEBAN", "", 'p'));
+
+ else if (modname.equals_cs("rline"))
+ {
+ Servers::Capab.insert("RLINE");
+ inspircdregex = moddata;
+ }
+
+ else if (modname.equals_cs("serverban"))
+ ModeManager::AddChannelMode(new InspIRCdExtBan::ServerMatcher("SERVERBAN", "", 's'));
+
+ else if (modname.equals_cs("services_account"))
+ {
+ Servers::Capab.insert("ACCOUNT");
+ Servers::Capab.insert("SERVICES");
+ ModeManager::AddChannelMode(new InspIRCdExtBan::AccountMatcher("ACCOUNTBAN", "", 'R'));
+ ModeManager::AddChannelMode(new InspIRCdExtBan::UnidentifiedMatcher("UNREGISTEREDBAN", "", 'U'));
+ }
+
+ else if (modname.equals_cs("svshold"))
+ IRCD->CanSVSHold = true;
+
+ else if (modname.equals_cs("topiclock"))
+ Servers::Capab.insert("TOPICLOCK");
+ }
+
+ // InspIRCd v3 and v4
+ if (modname.equals_cs("chghost"))
+ Servers::Capab.insert("CHGHOST");
+
+ else if (modname.equals_cs("chgident"))
+ Servers::Capab.insert("CHGIDENT");
+
+ else if (modname.equals_cs("ircv3_ctctags"))
+ IRCD->CanTagMessage = true;
+ }
+
+ const auto &anoperegex = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
+ if (!anoperegex.empty() && !inspircdregex.empty() && anoperegex != inspircdregex)
+ Log() << "Warning: InspIRCd is using regex engine " << inspircdregex << ", but we have " << anoperegex << ". This may cause inconsistencies.";
+ }
+ else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
+ {
+ spacesepstream ssep(params[1]);
+ Anope::string capab;
+ while (ssep.GetToken(capab))
+ {
+ auto [tokname, tokvalue] = ParseCapability(capab);
+ if (tokname == "CHALLENGE")
+ challenge = tokvalue;
+ if (tokname == "EXTBANFORMAT")
+ named_extbans = tokvalue.equals_ci("any") || tokvalue.equals_ci("name");
+ else if (tokname == "MAXCHANNEL")
+ IRCD->MaxChannel = Anope::Convert<size_t>(tokvalue, IRCD->MaxChannel);
+ else if (tokname == "MAXHOST")
+ IRCD->MaxHost = Anope::Convert<size_t>(tokvalue, IRCD->MaxHost);
+ else if (tokname == "MAXNICK")
+ IRCD->MaxNick = Anope::Convert<size_t>(tokvalue, IRCD->MaxNick);
+ else if (tokname == "MAXUSER")
+ IRCD->MaxUser = Anope::Convert<size_t>(tokvalue, IRCD->MaxUser);
+
+ // Deprecated 1205 keys.
+ else if (tokname == "CHANMAX")
+ IRCD->MaxChannel = Anope::Convert<size_t>(tokvalue, IRCD->MaxChannel);
+ else if (tokname == "GLOBOPS" && Anope::Convert<bool>(tokvalue, false))
+ Servers::Capab.insert("GLOBOPS");
+ else if (tokname == "IDENTMAX")
+ IRCD->MaxUser = Anope::Convert<size_t>(tokvalue, IRCD->MaxUser);
+ else if (tokname == "NICKMAX")
+ IRCD->MaxNick = Anope::Convert<size_t>(tokvalue, IRCD->MaxNick);
+ }
+ }
+ else if (params[0].equals_cs("END"))
+ {
+ if (spanningtree_proto_ver < 1206)
+ {
+ if (!Servers::Capab.count("ACCOUNT") || !Servers::Capab.count("SERVICES"))
+ throw ProtocolException("The services_account module is not loaded. This is required by Anope.");
+ }
+ else
+ {
+ if (!Servers::Capab.count("ACCOUNT"))
+ throw ProtocolException("The account module is not loaded. This is required by Anope.");
+
+ if (!Servers::Capab.count("SERVICES"))
+ throw ProtocolException("The services module is not loaded. This is required by Anope.");
+ }
+
+ if (!ModeManager::FindUserModeByName("PRIV"))
+ throw ProtocolException("The hidechans module is not loaded. This is required by Anope.");
+
+ if (!IRCD->CanSVSHold)
+ Log() << "The remote server does not have the svshold module; fake users will be used for nick protection until the module is loaded.";
+
+ if (!IRCD->CanSQLineChannel)
+ Log() << "The remote server does not have the cban module; services will manually enforce forbidden channels until the module is loaded.";
+
+ if (!IRCD->CanTagMessage)
+ Log() << "The remote server does not have the ircv3_ctctags module; sending tag messages is disabled until the module is loaded.";
+
+ if (!Servers::Capab.count("CHGHOST"))
+ Log() << "The remote server does not have the chghost module; vhosts are disabled until the module is loaded.";
+
+ if (!Servers::Capab.count("CHGIDENT"))
+ Log() << "The remote server does not have the chgident module; vidents are disabled until the module is loaded.";
+
+ if (!Servers::Capab.count("GLOBOPS"))
+ Log() << "The remote server does not have the globops module; oper notices will be sent as announcements until the module is loaded.";
+
+ if (spanningtree_proto_ver < 1206)
+ Uplink::Send("SERVER", Me->GetName(), GetPassword(), 0, Me->GetSID(), Me->GetDescription());
+ else
+ Uplink::Send("SERVER", Me->GetName(), GetPassword(), Me->GetSID(), Me->GetDescription());
+ }
+ }
+};
+
+struct IRCDMessageChgHost final
+ : IRCDMessage
+{
+ IRCDMessageChgHost(Module *creator)
+ : IRCDMessage(creator, "CHGHOST", 2)
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ auto *u = User::Find(params[0]);
+ if (!u || u->server != Me)
+ return;
+
+ u->SetDisplayedHost(params[1]);
+ if (spanningtree_proto_ver >= 1206)
+ Uplink::Send(u, "FHOST", u->GetDisplayedHost(), '*');
+ else
+ Uplink::Send(u, "FHOST", u->GetDisplayedHost());
+ }
+};
+
+struct IRCDMessageChgIdent final
+ : IRCDMessage
+{
+ IRCDMessageChgIdent(Module *creator)
+ : IRCDMessage(creator, "CHGIDENT", 2)
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ auto *u = User::Find(params[0]);
+ if (!u || u->server != Me)
+ return;
+
+ u->SetIdent(params[1]);
+ if (spanningtree_proto_ver >= 1206)
+ Uplink::Send(u, "FIDENT", u->GetIdent(), '*');
+ else
+ Uplink::Send(u, "FIDENT", u->GetIdent());
+ }
+};
+
+struct IRCDMessageChgName final
+ : IRCDMessage
+{
+ IRCDMessageChgName(Module *creator)
+ : IRCDMessage(creator, "CHGNAME", 2)
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ auto *u = User::Find(params[0]);
+ if (!u || u->server != Me)
+ return;
+
+ u->SetRealname(params[1]);
+ Uplink::Send(u, "FNAME", u->realname);
+ }
+};
+
+struct IRCDMessageEncap final
+ : IRCDMessage
+{
+ IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 2)
+ {
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (!Anope::Match(Me->GetSID(), params[0]) && !Anope::Match(Me->GetName(), params[0]))
+ return;
+
+ std::vector<Anope::string> newparams(params.begin() + 2, params.end());
+ Anope::ProcessInternal(source, params[1], newparams, tags);
+ }
+};
+
+struct IRCDMessageFHost final
+ : IRCDMessage
+{
+ IRCDMessageFHost(Module *creator)
+ : IRCDMessage(creator, "FHOST", 1)
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ User *u = source.GetUser();
+ if (params[0] != "*")
+ {
+ if (u->HasMode("CLOAK"))
+ u->RemoveModeInternal(source, ModeManager::FindUserModeByName("CLOAK"));
+ u->SetDisplayedHost(params[0]);
+ }
+
+ if (params.size() > 1 && params[1] != "*")
+ u->host = params[1];
+ }
+};
+
+struct IRCDMessageFIdent final
+ : IRCDMessage
+{
+ IRCDMessageFIdent(Module *creator)
+ : IRCDMessage(creator, "FIDENT", 1)
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ User *u = source.GetUser();
+ if (params[0] != "*")
+ u->SetDisplayedHost(params[0]);
+ }
+};
+
+struct IRCDMessageKick final
+ : IRCDMessage
+{
+ IRCDMessageKick(Module *creator) : IRCDMessage(creator, "KICK", 3) { SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ // Received: :715AAAAAA KICK #chan 715AAAAAD :reason
+ // Received: :715AAAAAA KICK #chan 628AAAAAA 4 :reason
+ Channel *c = Channel::Find(params[0]);
+ if (!c)
+ return;
+
+ const Anope::string &reason = params.size() > 3 ? params[3] : params[2];
+ c->KickInternal(source, params[1], reason);
+ }
+};
+
+struct IRCDMessageSASL final
+ : IRCDMessage
+{
+ IRCDMessageSASL(Module *creator)
+ : IRCDMessage(creator, "SASL", 4)
+ {
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (!SASL::sasl)
+ return;
+
+ SASL::Message m;
+ m.source = params[0];
+ m.target = params[1];
+ m.type = params[2];
+ m.data.assign(params.begin() + 3, params.end());
+ SASL::sasl->ProcessMessage(m);
+ }
+};
+
+struct IRCDMessageSave final
+ : IRCDMessage
+{
+ time_t last_collide = 0;
+
+ IRCDMessageSave(Module *creator) : IRCDMessage(creator, "SAVE", 2) { }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ User *targ = User::Find(params[0]);
+ auto ts = IRCD->ExtractTimestamp(params[1]);
+ if (!targ || !ts || targ->timestamp != ts)
+ return;
+
+ BotInfo *bi;
+ if (targ->server == Me && (bi = dynamic_cast<BotInfo *>(targ)))
+ {
+ if (last_collide == Anope::CurTime)
+ {
+ Anope::QuitReason = "Nick collision fight on " + targ->nick;
+ Anope::Quitting = true;
+ return;
+ }
+
+ IRCD->SendKill(Me, targ->nick, "Nick collision");
+ IRCD->SendNickChange(targ, targ->nick);
+ last_collide = Anope::CurTime;
+ }
+ else
+ targ->ChangeNick(targ->GetUID());
+ }
+};
+
+class IRCDMessageMetadata final
+ : IRCDMessage
+{
+private:
+ ServiceReference<CertService> certs;
+ PrimitiveExtensibleItem<ListLimits> &maxlist;
+
+
+public:
+ IRCDMessageMetadata(Module *creator, PrimitiveExtensibleItem<ListLimits> &listlimits)
+ : IRCDMessage(creator, "METADATA", 3)
+ , certs("CertService", "certs")
+ , maxlist(listlimits)
+ {
+ SetFlag(FLAG_REQUIRE_SERVER);
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ // We deliberately ignore non-bursting servers to avoid pseudoserver fights
+ // Channel METADATA has an additional parameter: the channel TS
+ // Received: :715 METADATA #chan 1572026333 mlock :nt
+ if ((params[0][0] == '#') && (params.size() > 3) && (!source.GetServer()->IsSynced()))
+ {
+ Channel *c = Channel::Find(params[0]);
+ if (c)
+ {
+ if (c->ci && params[2] == "mlock")
+ {
+ ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
+ Anope::string modes;
+ if (modelocks)
+ modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
+
+ // Mode lock string is not what we say it is?
+ if (modes != params[3])
+ Uplink::Send("METADATA", c->name, c->creation_time, "mlock", modes);
+ }
+ else if (c->ci && params[2] == "topiclock")
+ {
+ bool mystate = c->ci->HasExt("TOPICLOCK");
+ bool serverstate = (params[3] == "1");
+ if (mystate != serverstate)
+ Uplink::Send("METADATA", c->name, c->creation_time, "topiclock", !!mystate);
+ }
+ else if (params[2] == "maxlist")
+ {
+ ListLimits limits;
+ spacesepstream limitstream(params[3]);
+ Anope::string modechr, modelimit;
+ while (limitstream.GetToken(modechr) && limitstream.GetToken(modelimit))
+ {
+ limits.emplace(modechr[0], Anope::Convert<unsigned>(modelimit, 0));
+ }
+ maxlist.Set(c, limits);
+ }
+ }
+ }
+ else if (isdigit(params[0][0]))
+ {
+ auto *u = User::Find(params[0]);
+ if (!u)
+ return;
+
+ if (params[1].equals_cs("accountname"))
+ {
+ if (params[2].empty())
+ {
+ // The user has been logged out by the IRC server.
+ u->Logout();
+ }
+ else
+ {
+ // If we're bursting then then the user was probably logged
+ // in during a previous connection.
+ NickCore *nc = NickCore::Find(params[2]);
+ if (nc)
+ u->Login(nc);
+ }
+ }
+
+ /*
+ * possible incoming ssl_cert messages:
+ * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...>
+ * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0)
+ */
+ else if (params[1].equals_cs("ssl_cert"))
+ {
+ u->Extend<bool>("ssl");
+
+ Anope::string data;
+ spacesepstream tokens(params[2]);
+ if (!tokens.GetToken(data) || data.find('E') != Anope::string::npos || !tokens.GetToken(data))
+ return; // Malformed or no client certificate.
+
+ commasepstream fingerprints(data);
+ if (!fingerprints.GetToken(data))
+ return; // Should never happen?
+
+ u->fingerprint = data;
+ FOREACH_MOD(OnFingerprint, (u));
+
+ while (certs && fingerprints.GetToken(data))
+ certs->ReplaceCert(data, u->fingerprint);
+ }
+ }
+ else if (params[0] == "*")
+ {
+ // Wed Oct 3 15:40:27 2012: S[14] O :20D METADATA * modules :-m_svstopic.so
+
+ if (params[1].equals_cs("modules") && !params[2].empty())
+ {
+ // only interested when it comes from our uplink
+ Server *server = source.GetServer();
+ if (!server || server->GetUplink() != Me)
+ return;
+
+ bool plus = (params[2][0] == '+');
+ if (!plus && params[2][0] != '-')
+ return;
+
+ bool required = false;
+ Anope::string capab, modname, moddata;
+ ParseModule(params[2].substr(1), modname, moddata);
+
+ if (modname.equals_cs("account"))
+ required = true;
+
+ else if (modname.equals_cs("cban"))
+ {
+ if (plus && (spanningtree_proto_ver >= 1206 || moddata == "glob"))
+ IRCD->CanSQLineChannel = true;
+ else
+ IRCD->CanSQLineChannel = false;
+ }
+
+ else if (modname.equals_cs("cban") && spanningtree_proto_ver >= 1206)
+ IRCD->CanSQLineChannel = plus;
+
+ else if (modname.equals_cs("chghost"))
+ capab = "CHGHOST";
+
+ else if (modname.equals_cs("chgident"))
+ capab = "CHGIDENT";
+
+ else if (modname.equals_cs("globops"))
+ capab = "GLOBOPS";
+
+ else if (modname.equals_cs("hidechans"))
+ required = true;
+
+ else if (modname.equals_cs("ircv3_ctctags"))
+ IRCD->CanTagMessage = plus;
+
+ else if (modname.equals_cs("rline"))
+ capab = "RLINE";
+
+ else if (modname.equals_cs("services"))
+ required = true;
+
+ // Deprecated 1205 modules.
+ else if (modname.equals_cs("services_account"))
+ required = true;
+
+ else if (modname.equals_cs("svshold"))
+ IRCD->CanSVSHold = plus;
+
+ else if (modname.equals_cs("topiclock"))
+ capab = "TOPICLOCK";
+
+ else
+ return;
+
+ if (required)
+ {
+ if (plus)
+ Log() << "Warning: InspIRCd unloaded the " << modname << " module. Anope won't function correctly without it.";
+ }
+ else
+ {
+ if (plus && !capab.empty())
+ Servers::Capab.insert(capab);
+ else if (!capab.empty())
+ Servers::Capab.erase(capab);
+
+ Log() << "InspIRCd " << (plus ? "loaded" : "unloaded") << " the " << modname << " module; adjusted functionality.";
+ }
+
+ }
+ }
+ }
+};
+
+struct IRCDMessageEndburst final
+ : IRCDMessage
+{
+ IRCDMessageEndburst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { SetFlag(FLAG_REQUIRE_SERVER); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ Server *s = source.GetServer();
+
+ Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName();
+
+ s->Sync(true);
+ }
+};
+
+struct IRCDMessageFJoin final
+ : IRCDMessage
+{
+ IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ std::list<Message::Join::SJoinUser> users;
+
+ spacesepstream sep(params[params.size() - 1]);
+ Anope::string buf;
+ while (sep.GetToken(buf))
+ {
+ Message::Join::SJoinUser sju;
+
+ /* Loop through prefixes and find modes for them */
+ for (char c; (c = buf[0]) != ',' && c;)
+ {
+ buf.erase(buf.begin());
+ sju.first.AddMode(c);
+ }
+ /* Erase the , */
+ if (!buf.empty())
+ buf.erase(buf.begin());
+
+ /* Erase the :membid */
+ if (!buf.empty())
+ {
+ Anope::string::size_type membid = buf.find(':');
+ if (membid != Anope::string::npos)
+ buf.erase(membid, Anope::string::npos);
+ }
+
+ sju.second = User::Find(buf);
+ if (!sju.second)
+ {
+ Log(LOG_DEBUG) << "FJOIN for nonexistent user " << buf << " on " << params[0];
+ continue;
+ }
+
+ users.push_back(sju);
+ }
+
+ auto ts = IRCD->ExtractTimestamp(params[1]);
+ Message::Join::SJoin(source, params[0], ts, params[2], { params.begin() + 3, params.end() - 1 }, users);
+ }
+};
+
+struct IRCDMessageFMode final
+ : IRCDMessage
+{
+ IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ /* :source FMODE #test 12345678 +nto foo */
+ Channel *c = Channel::Find(params[0]);
+ auto ts = IRCD->ExtractTimestamp(params[1]);
+ if (c)
+ c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() }, ts);
+ }
+};
+
+struct IRCDMessageFTopic final
+ : IRCDMessage
+{
+ IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ // :source FTOPIC channel ts topicts :topic
+ // :source FTOPIC channel ts topicts setby :topic (burst or RESYNC)
+
+ auto ts = IRCD->ExtractTimestamp(params[2]);
+ const Anope::string &setby = params.size() > 4 ? params[3] : source.GetName();
+ const Anope::string &topic = params.size() > 4 ? params[4] : params[3];
+
+ Channel *c = Channel::Find(params[0]);
+ if (c)
+ c->ChangeTopicInternal(NULL, setby, topic, ts);
+ }
+};
+
+struct IRCDMessageIdle final
+ : IRCDMessage
+{
+ IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ BotInfo *bi = BotInfo::Find(params[0]);
+ if (bi)
+ Uplink::Send(bi, "IDLE", source.GetSource(), bi->signon, Anope::CurTime - bi->lastmsg);
+ else
+ {
+ User *u = User::Find(params[0]);
+ if (u && u->server == Me)
+ Uplink::Send(u, "IDLE", source.GetSource(), u->signon, 0);
+ }
+ }
+};
+
+struct IRCDMessageIJoin final
+ : IRCDMessage
+{
+ IRCDMessageIJoin(Module *creator) : IRCDMessage(creator, "IJOIN", 2) { SetFlag(FLAG_REQUIRE_USER); SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ // :<uid> IJOIN <chan> <membid> [<ts> [<flags>]]
+ Channel *c = Channel::Find(params[0]);
+ if (!c)
+ {
+ // When receiving an IJOIN, first check if the target channel exists. If it does not exist,
+ // ignore the join (that is, do not create the channel) and send a RESYNC back to the source.
+ Uplink::Send("RESYNC", params[0]);
+ return;
+ }
+
+ // If the channel does exist then join the user, and in case any prefix modes were sent (found in
+ // the 3rd parameter), compare the TS of the channel to the TS in the IJOIN (2nd parameter). If
+ // the timestamps match, set the modes on the user, otherwise ignore the modes.
+ Message::Join::SJoinUser user;
+ user.second = source.GetUser();
+
+ time_t chants = Anope::CurTime;
+ if (params.size() >= 4)
+ {
+ chants = IRCD->ExtractTimestamp(params[2]);
+ for (auto mode : params[3])
+ user.first.AddMode(mode);
+ }
+
+ std::list<Message::Join::SJoinUser> users;
+ users.push_back(user);
+ Message::Join::SJoin(source, params[0], chants, "", {}, users);
+ }
+};
+
+struct IRCDMessageLMode final
+ : IRCDMessage
+{
+ IRCDMessageLMode(Module *creator)
+ : IRCDMessage(creator, "LMODE", 3)
+ {
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ // :<sid> LMODE <chan> <chants> <modechr> [<mask> <setts> <setter>]+
+ auto *chan = Channel::Find(params[0]);
+ if (!chan)
+ return; // Channel doesn't exist.
+
+ // If the TS is greater than ours, we drop the mode and don't pass it anywhere.
+ auto chants = IRCD->ExtractTimestamp(params[1]);
+ if (chants > chan->creation_time)
+ return;
+
+ auto *cm = ModeManager::FindChannelModeByChar(params[2][0]);
+ if (!cm || cm->type != MODE_LIST)
+ return; // Mode doesn't exist or isn't a list mode.
+
+ if (params.size() % 3)
+ return; // Invalid parameter count.
+
+ for (auto it = params.begin() + 3; it != params.end(); it += 3)
+ {
+ // TODO: Anope doesn't store set time and setter for list modes yet.
+ chan->SetModeInternal(source, cm, *it);
+ }
+ }
+};
+
+
+struct IRCDMessageMode final
+ : IRCDMessage
+{
+ IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (IRCD->IsChannelValid(params[0]))
+ {
+ Channel *c = Channel::Find(params[0]);
+
+ if (c)
+ c->SetModesInternal(source, params[2], { params.begin() + 3, params.end() });
+ }
+ else
+ {
+ /* InspIRCd lets opers change another
+ users modes, we have to kludge this
+ as it slightly breaks RFC1459
+ */
+ User *u = User::Find(params[0]);
+ if (u)
+ u->SetModesInternal(source, params[1]);
+ }
+ }
+};
+
+struct IRCDMessageNick final
+ : IRCDMessage
+{
+ IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(FLAG_REQUIRE_USER); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ source.GetUser()->ChangeNick(params[0]);
+ }
+};
+
+struct IRCDMessageOperType final
+ : IRCDMessage
+{
+ PrimitiveExtensibleItem<Anope::string> opertype;
+
+ IRCDMessageOperType(Module *creator)
+ : IRCDMessage(creator, "OPERTYPE", 1)
+ , opertype(creator, "opertype")
+ {
+ SetFlag(FLAG_REQUIRE_USER);
+ }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ /* opertype is equivalent to mode +o because servers
+ don't do this directly */
+ User *u = source.GetUser();
+ if (!u->HasMode("OPER"))
+ u->SetModesInternal(source, "+o");
+
+ opertype.Set(u, params[0]);
+ }
+};
+
+struct IRCDMessagePing final
+ : IRCDMessage
+{
+ IRCDMessagePing(Module *creator) : IRCDMessage(creator, "PING", 1) { SetFlag(FLAG_SOFT_LIMIT); SetFlag(FLAG_REQUIRE_SERVER); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (params[0] == Me->GetSID())
+ IRCD->SendPong(params[0], source.GetServer()->GetSID());
+ }
+};
+
+struct IRCDMessageRSQuit final
+ : IRCDMessage
+{
+ IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 1) { SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ Server *s = Server::Find(params[0]);
+ const Anope::string &reason = params.size() > 1 ? params[1] : "";
+ if (!s)
+ return;
+
+ Uplink::Send("SQUIT", s->GetSID(), reason);
+ s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
+ }
+};
+
+struct IRCDMessageServer final
+ : IRCDMessage
+{
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ size_t paramcount = spanningtree_proto_ver < 1206 ? 5 : 4;
+ if (!source.GetServer() && params.size() == paramcount)
+ {
+ /*
+ * SERVER testnet.inspircd.org hunter7 0 123 :InspIRCd Test Network
+ * 0: name
+ * 1: pass
+ * 2: unused (v3 only)
+ * 3(2): numeric
+ * 4(3): desc
+ */
+ new Server(Me, params[0], 0, params.back(), params[spanningtree_proto_ver < 1206 ? 3 : 2]);
+ }
+ else if (source.GetServer())
+ {
+ /*
+ * SERVER testnet.inspircd.org 123 burst=1234 hidden=0 :InspIRCd Test Network
+ * 0: name
+ * 1: numeric
+ * 2 to N-1: various key=value pairs.
+ * N: desc
+ */
+ new Server(source.GetServer(), params[0], 1, params.back(), params[1]);
+ }
+ }
+};
+
+struct IRCDMessageSQuit final
+ : Message::SQuit
+{
+ IRCDMessageSQuit(Module *creator) : Message::SQuit(creator) { }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (params[0] == rsquit_id || params[0] == rsquit_server)
+ {
+ /* squit for a recently squit server, introduce the juped server now */
+ Server *s = Server::Find(rsquit_server);
+
+ rsquit_id.clear();
+ rsquit_server.clear();
+
+ if (s && s->IsJuped())
+ IRCD->SendServer(s);
+ }
+ else
+ Message::SQuit::Run(source, params, tags);
+ }
+};
+
+struct IRCDMessageUID final
+ : IRCDMessage
+{
+ IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 8) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
+
+ /*
+ * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org>
+ * 0: uid
+ * 1: ts
+ * 2: nick
+ * 3: host
+ * 4: dhost
+ * 5: ident
+ * 6: dident (v4 only)
+ * 7: ip
+ * 8: signon
+ * 9+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname!
+ * last: realname
+ */
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ size_t offset = params[8][0] == '+' ? 0 : 1;
+ auto ts = IRCD->ExtractTimestamp(params[1]);
+
+ NickAlias *na = NULL;
+ if (SASL::sasl)
+ for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
+ {
+ SASLUser &u = *it;
+
+ if (u.created + 30 < Anope::CurTime)
+ it = saslusers.erase(it);
+ else if (u.uid == params[0])
+ {
+ na = NickAlias::Find(u.acc);
+ it = saslusers.erase(it);
+ }
+ else
+ ++it;
+ }
+
+ auto *u = User::OnIntroduce(params[2], params[5+offset], params[3], params[4], params[6+offset], source.GetServer(), params[params.size() - 1], ts, params[8 + offset], params[0], na ? *na->nc : NULL, { params.begin() + 9 + offset, params.end() - 1 });
+ if (u)
+ u->signon = IRCD->ExtractTimestamp(params[7+offset]);
+ }
+};
+
+class ProtoInspIRCd final
+ : public Module
+{
+ InspIRCdProto ircd_proto;
+ ExtensibleItem<bool> ssl;
+
+ /* Core message handlers */
+ Message::Error message_error;
+ Message::Invite message_invite;
+ Message::Kill message_kill;
+ Message::MOTD message_motd;
+ Message::Notice message_notice;
+ Message::Part message_part;
+ Message::Privmsg message_privmsg;
+ Message::Quit message_quit;
+ Message::Privmsg message_squery;
+ Message::Stats message_stats;
+ Message::Time message_time;
+
+ /* Our message handlers */
+ IRCDMessageAway message_away;
+ IRCDMessageCapab message_capab;
+ IRCDMessageChgHost message_chghost;
+ IRCDMessageChgIdent message_chgident;
+ IRCDMessageChgName message_chgname;
+ IRCDMessageEncap message_encap;
+ IRCDMessageEndburst message_endburst;
+ IRCDMessageFHost message_fhost;
+ IRCDMessageFIdent message_fident;
+ IRCDMessageFJoin message_fjoin;
+ IRCDMessageFMode message_fmode;
+ IRCDMessageFTopic message_ftopic;
+ IRCDMessageIdle message_idle;
+ IRCDMessageIJoin message_ijoin;
+ IRCDMessageKick message_kick;
+ IRCDMessageLMode message_lmode;
+ IRCDMessageMetadata message_metadata;
+ IRCDMessageMode message_mode;
+ IRCDMessageNick message_nick;
+ IRCDMessageOperType message_opertype;
+ IRCDMessagePing message_ping;
+ IRCDMessageRSQuit message_rsquit;
+ IRCDMessageSASL message_sasl;
+ IRCDMessageSave message_save;
+ IRCDMessageServer message_server;
+ IRCDMessageSQuit message_squit;
+ IRCDMessageUID message_uid;
+
+ static void SendChannelMetadata(Channel *c, const Anope::string &metadataname, const Anope::string &value)
+ {
+ Uplink::Send("METADATA", c->name, c->creation_time, metadataname, value);
+ }
+
+public:
+ ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, PROTOCOL | VENDOR)
+ , ircd_proto(this), ssl(this, "ssl")
+ , message_error(this)
+ , message_invite(this)
+ , message_kill(this)
+ , message_motd(this)
+ , message_notice(this)
+ , message_part(this)
+ , message_privmsg(this)
+ , message_quit(this)
+ , message_squery(this, "SQUERY")
+ , message_stats(this)
+ , message_time(this)
+ , message_away(this)
+ , message_capab(this)
+ , message_chghost(this)
+ , message_chgident(this)
+ , message_chgname(this)
+ , message_encap(this)
+ , message_endburst(this)
+ , message_fhost(this)
+ , message_fident(this)
+ , message_fjoin(this)
+ , message_fmode(this)
+ , message_ftopic(this)
+ , message_idle(this)
+ , message_ijoin(this)
+ , message_kick(this)
+ , message_lmode(this)
+ , message_metadata(this, ircd_proto.maxlist)
+ , message_mode(this)
+ , message_nick(this)
+ , message_opertype(this)
+ , message_ping(this)
+ , message_rsquit(this)
+ , message_sasl(this)
+ , message_save(this)
+ , message_server(this)
+ , message_squit(this)
+ , message_uid(this)
+ {
+ }
+
+ void OnUserNickChange(User *u, const Anope::string &) override
+ {
+ u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
+ }
+
+ void OnChannelSync(Channel *c) override
+ {
+ if (c->ci)
+ this->OnChanRegistered(c->ci);
+ }
+
+ void OnChanRegistered(ChannelInfo *ci) override
+ {
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
+ if (ci->c && modelocks && !modelocks->GetMLockAsString(false).empty())
+ {
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
+ SendChannelMetadata(ci->c, "mlock", modes);
+ }
+
+ if (Servers::Capab.count("TOPICLOCK") && ci->c)
+ {
+ if (ci->HasExt("TOPICLOCK"))
+ SendChannelMetadata(ci->c, "topiclock", "1");
+ }
+ }
+
+ void OnDelChan(ChannelInfo *ci) override
+ {
+ if (!ci->c)
+ return;
+
+ SendChannelMetadata(ci->c, "mlock", "");
+ if (Servers::Capab.count("TOPICLOCK"))
+ SendChannelMetadata(ci->c, "topiclock", "");
+ }
+
+ EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) override
+ {
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
+ ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
+ if (cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
+ {
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
+ SendChannelMetadata(ci->c, "mlock", modes);
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) override
+ {
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
+ ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
+ if (cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
+ {
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
+ SendChannelMetadata(ci->c, "mlock", modes);
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) override
+ {
+ if (cmd->name == "chanserv/topic" && ci->c)
+ {
+ if (setting == "topiclock on")
+ SendChannelMetadata(ci->c, "topiclock", "1");
+ else if (setting == "topiclock off")
+ SendChannelMetadata(ci->c, "topiclock", "0");
+ }
+
+ return EVENT_CONTINUE;
+ }
+};
+
+MODULE_INIT(ProtoInspIRCd)
diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp
deleted file mode 100644
index 8d6c95dc3..000000000
--- a/modules/protocol/inspircd12.cpp
+++ /dev/null
@@ -1,1408 +0,0 @@
-/* inspircd 1.2 functions
- *
- * (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/sasl.h"
-
-struct SASLUser
-{
- Anope::string uid;
- Anope::string acc;
- time_t created;
-};
-
-static std::list<SASLUser> saslusers;
-
-static Anope::string rsquit_server, rsquit_id;
-
-class ChannelModeFlood : public ChannelModeParam
-{
- public:
- ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- try
- {
- Anope::string rest;
- if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty())
- return true;
- }
- catch (const ConvertException &) { }
-
- return false;
- }
-};
-
-class InspIRCd12Proto : public IRCDProto
-{
- private:
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override
- {
- IRCDProto::SendSVSKillInternal(source, user, buf);
- user->KillInternal(source, buf);
- }
-
- void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent)
- {
- if (!Servers::Capab.count("CHGIDENT"))
- Log() << "CHGIDENT not loaded!";
- else
- UplinkSocket::Message(Me) << "CHGIDENT " << nick << " " << vIdent;
- }
-
- void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost)
- {
- if (!Servers::Capab.count("CHGHOST"))
- Log() << "CHGHOST not loaded!";
- else
- UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost;
- }
-
- void SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason)
- {
- UplinkSocket::Message(Me) << "ADDLINE " << xtype << " " << mask << " " << addedby << " " << Anope::CurTime << " " << duration << " :" << reason;
- }
-
- void SendDelLine(const Anope::string &xtype, const Anope::string &mask)
- {
- UplinkSocket::Message(Me) << "DELLINE " << xtype << " " << mask;
- }
-
- public:
- InspIRCd12Proto(Module *creator) : IRCDProto(creator, "InspIRCd 1.2")
- {
- DefaultPseudoclientModes = "+I";
- CanSVSNick = true;
- CanSVSJoin = true;
- CanSetVHost = true;
- CanSetVIdent = true;
- CanSQLine = true;
- CanSZLine = true;
- CanSVSHold = true;
- CanCertFP = true;
- RequiresID = true;
- MaxModes = 20;
- }
-
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
- {
- UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
- }
-
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
- {
- UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
- }
-
- void SendAkillDel(const XLine *x) anope_override
- {
- /* InspIRCd may support regex bans
- * Mask is expected in format: 'n!u@h\sr' and spaces as '\s'
- * We remove the '//' and replace '#' and any ' ' with '\s'
- */
- if (x->IsRegex() && Servers::Capab.count("RLINE"))
- {
- Anope::string mask = x->mask;
- if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
- mask = mask.substr(1, mask.length() - 2);
- size_t h = mask.find('#');
- if (h != Anope::string::npos)
- {
- mask = mask.replace(h, 1, "\\s");
- mask = mask.replace_all_cs(" ", "\\s");
- }
- SendDelLine("R", mask);
- return;
- }
- else if (x->IsRegex() || x->HasNickOrReal())
- return;
-
- /* ZLine if we can instead */
- if (x->GetUser() == "*")
- {
- cidr addr(x->GetHost());
- if (addr.valid())
- {
- IRCD->SendSZLineDel(x);
- return;
- }
- }
-
- SendDelLine("G", x->GetUser() + "@" + x->GetHost());
- }
-
- void SendTopic(const MessageSource &source, Channel *c) anope_override
- {
- if (Servers::Capab.count("SVSTOPIC"))
- {
- UplinkSocket::Message(c->WhoSends()) << "SVSTOPIC " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic;
- }
- else
- {
- /* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */
- time_t ts = c->topic_ts;
- if (c->topic_time > ts)
- ts = Anope::CurTime;
- /* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */
- UplinkSocket::Message(source) << "FTOPIC " << c->name << " " << ts << " " << c->topic_setter << " :" << c->topic;
- }
- }
-
- void SendVhostDel(User *u) anope_override
- {
- UserMode *um = ModeManager::FindUserModeByName("CLOAK");
-
- if (um && !u->HasMode(um->name))
- // Just set +x if we can
- u->SetMode(NULL, um);
- else
- // Try to restore cloaked host
- this->SendChgHostInternal(u->nick, u->chost);
- }
-
- void SendAkill(User *u, XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
-
- /* InspIRCd may support regex bans, if they do we can send this and forget about it
- * Mask is expected in format: 'n!u@h\sr' and spaces as '\s'
- * We remove the '//' and replace '#' and any ' ' with '\s'
- */
- if (x->IsRegex() && Servers::Capab.count("RLINE"))
- {
- Anope::string mask = x->mask;
- if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
- mask = mask.substr(1, mask.length() - 2);
- size_t h = mask.find('#');
- if (h != Anope::string::npos)
- {
- mask = mask.replace(h, 1, "\\s");
- mask = mask.replace_all_cs(" ", "\\s");
- }
- SendAddLine("R", mask, timeleft, x->by, x->GetReason());
- return;
- }
- else if (x->IsRegex() || x->HasNickOrReal())
- {
- if (!u)
- {
- /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (x->manager->Check(it->second, x))
- this->SendAkill(it->second, x);
- return;
- }
-
- const XLine *old = x;
-
- if (old->manager->HasEntry("*@" + u->host))
- return;
-
- /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
- x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
- old->manager->AddXLine(x);
-
- Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
- }
-
- /* ZLine if we can instead */
- if (x->GetUser() == "*")
- {
- cidr addr(x->GetHost());
- if (addr.valid())
- {
- IRCD->SendSZLine(u, x);
- return;
- }
- }
-
- SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->by, x->GetReason());
- }
-
- void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override
- {
- User *u = User::Find(dest);
- UplinkSocket::Message() << "PUSH " << dest << " ::" << Me->GetName() << " " << numeric << " " << (u ? u->nick : dest) << " " << buf;
- }
-
- void SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) anope_override
- {
- UplinkSocket::Message(source) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
- }
-
- void SendClientIntroduction(User *u) anope_override
- {
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(Me) << "UID " << u->GetUID() << " " << u->timestamp << " " << u->nick << " " << u->host << " " << u->host << " " << u->GetIdent() << " 0.0.0.0 " << u->timestamp << " " << modes << " :" << u->realname;
-
- if (modes.find('o') != Anope::string::npos)
- {
- // Mark as introduced so we can send an oper type.
- BotInfo *bi = BotInfo::Find(u->nick, true);
- if (bi)
- bi->introduced = true;
-
- UplinkSocket::Message(u) << "OPERTYPE :service";
- }
- }
-
- /* SERVER services-dev.chatspike.net password 0 :Description here */
- void SendServer(const Server *server) anope_override
- {
- /* if rsquit is set then we are waiting on a squit */
- if (rsquit_id.empty() && rsquit_server.empty())
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << Config->Uplinks[Anope::CurrentUplink].password << " " << server->GetHops() << " " << server->GetSID() << " :" << server->GetDescription();
- }
-
- void SendSquit(Server *s, const Anope::string &message) anope_override
- {
- if (s != Me)
- {
- rsquit_id = s->GetSID();
- rsquit_server = s->GetName();
- UplinkSocket::Message() << "RSQUIT " << s->GetName() << " :" << message;
- }
- else
- UplinkSocket::Message() << "SQUIT " << s->GetName() << " :" << message;
- }
-
- /* JOIN */
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
- {
- UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :," << user->GetUID();
- /* Note that we can send this with the FJOIN but choose not to
- * because the mode stacker will handle this and probably will
- * merge these modes with +nrt and other mlocked modes
- */
- if (status)
- {
- /* First save the channel status incase uc->Status == status */
- ChannelStatus cs = *status;
- /* If the user is internally on the channel with flags, kill them so that
- * the stacker will allow this.
- */
- ChanUserContainer *uc = c->FindUser(user);
- if (uc != NULL)
- uc->status.Clear();
-
- BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
-
- if (uc != NULL)
- uc->status = cs;
- }
- }
-
- /* UNSQLINE */
- void SendSQLineDel(const XLine *x) anope_override
- {
- SendDelLine("Q", x->mask);
- }
-
- /* SQLINE */
- void SendSQLine(User *, const XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- SendAddLine("Q", x->mask, timeleft, x->by, x->GetReason());
- }
-
- void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
- {
- if (!vIdent.empty())
- this->SendChgIdentInternal(u->nick, vIdent);
- if (!vhost.empty())
- this->SendChgHostInternal(u->nick, vhost);
- }
-
- void SendConnect() anope_override
- {
- SendServer(Me);
- }
-
- /* SVSHOLD - set */
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override
- {
- UplinkSocket::Message(Config->GetClient("NickServ")) << "SVSHOLD " << nick << " " << t << " :Being held for registered user";
- }
-
- /* SVSHOLD - release */
- void SendSVSHoldDel(const Anope::string &nick) anope_override
- {
- UplinkSocket::Message(Config->GetClient("NickServ")) << "SVSHOLD " << nick;
- }
-
- /* UNSZLINE */
- void SendSZLineDel(const XLine *x) anope_override
- {
- SendDelLine("Z", x->GetHost());
- }
-
- /* SZLINE */
- void SendSZLine(User *, const XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- SendAddLine("Z", x->GetHost(), timeleft, x->by, x->GetReason());
- }
-
- void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) anope_override
- {
- UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
- }
-
- void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) anope_override
- {
- if (!param.empty())
- UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
- else
- UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
- }
-
- void SendSWhois(const MessageSource &, const Anope::string &who, const Anope::string &mask) anope_override
- {
- User *u = User::Find(who);
-
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " swhois :" << mask;
- }
-
- void SendBOB() anope_override
- {
- UplinkSocket::Message(Me) << "BURST " << Anope::CurTime;
- Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
- UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << IRCD->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString();
- }
-
- void SendEOB() anope_override
- {
- UplinkSocket::Message(Me) << "ENDBURST";
- }
-
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
- {
- if (Servers::Capab.count("GLOBOPS"))
- UplinkSocket::Message(source) << "SNONOTICE g :" << buf;
- else
- UplinkSocket::Message(source) << "SNONOTICE A :" << buf;
- }
-
- void SendLogin(User *u, NickAlias *na) anope_override
- {
- /* InspIRCd uses an account to bypass chmode +R, not umode +r, so we can't send this here */
- if (na->nc->HasExt("UNCONFIRMED"))
- return;
-
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :" << na->nc->display;
- }
-
- void SendLogout(User *u) anope_override
- {
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :";
- }
-
- void SendChannel(Channel *c) anope_override
- {
- UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :";
- }
-
- void SendOper(User *u) anope_override
- {
- }
-
- void SendSASLMessage(const SASL::Message &message) anope_override
- {
- UplinkSocket::Message(Me) << "ENCAP " << message.target.substr(0, 3) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
- }
-
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
- {
- UplinkSocket::Message(Me) << "METADATA " << uid << " accountname :" << acc;
-
- if (!vident.empty())
- UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGIDENT " << uid << " " << vident;
- if (!vhost.empty())
- UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGHOST " << uid << " " << vhost;
-
- SASLUser su;
- su.uid = uid;
- su.acc = acc;
- su.created = Anope::CurTime;
-
- for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
- {
- SASLUser &u = *it;
-
- if (u.created + 30 < Anope::CurTime || u.uid == uid)
- it = saslusers.erase(it);
- else
- ++it;
- }
-
- saslusers.push_back(su);
- }
-
- bool IsExtbanValid(const Anope::string &mask) anope_override
- {
- return mask.length() >= 3 && mask[1] == ':';
- }
-
- bool IsIdentValid(const Anope::string &ident) anope_override
- {
- if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
- return false;
-
- for (unsigned i = 0; i < ident.length(); ++i)
- {
- const char &c = ident[i];
-
- if (c >= 'A' && c <= '}')
- continue;
-
- if ((c >= '0' && c <= '9') || c == '-' || c == '.')
- continue;
-
- return false;
- }
-
- return true;
- }
-};
-
-class InspIRCdExtBan : public ChannelModeList
-{
- public:
- InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
-
- if (mask.find("m:") == 0 || mask.find("N:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
-
- Entry en(this->name, real_mask);
- if (en.Matches(u))
- return true;
- }
- else if (mask.find("j:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
-
- Channel *c = Channel::Find(real_mask);
- if (c != NULL && c->FindUser(u) != NULL)
- return true;
- }
- else if (mask.find("M:") == 0 || mask.find("R:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
-
- if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display))
- return true;
- }
- else if (mask.find("r:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
-
- if (Anope::Match(u->realname, real_mask))
- return true;
- }
- else if (mask.find("s:") == 0)
- {
- Anope::string real_mask = mask.substr(2);
-
- if (Anope::Match(u->server->GetName(), real_mask))
- return true;
- }
-
- return false;
- }
-};
-
-struct IRCDMessageCapab : Message::Capab
-{
- IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params[0].equals_cs("START"))
- {
- /* reset CAPAB */
- Servers::Capab.clear();
- Servers::Capab.insert("NOQUIT");
- IRCD->CanSVSHold = false;
- }
- else if (params[0].equals_cs("MODULES") && params.size() > 1)
- {
- if (params[1].find("m_globops.so") != Anope::string::npos)
- Servers::Capab.insert("GLOBOPS");
- if (params[1].find("m_services_account.so") != Anope::string::npos)
- Servers::Capab.insert("SERVICES");
- if (params[1].find("m_svshold.so") != Anope::string::npos)
- IRCD->CanSVSHold = true;
- if (params[1].find("m_chghost.so") != Anope::string::npos)
- Servers::Capab.insert("CHGHOST");
- if (params[1].find("m_chgident.so") != Anope::string::npos)
- Servers::Capab.insert("CHGIDENT");
- if (params[1].find("m_hidechans.so") != Anope::string::npos)
- Servers::Capab.insert("HIDECHANS");
- if (params[1].find("m_servprotect.so") != Anope::string::npos)
- IRCD->DefaultPseudoclientModes = "+Ik";
- if (params[1].find("m_rline.so") != Anope::string::npos)
- Servers::Capab.insert("RLINE");
- }
- else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
- while (ssep.GetToken(capab))
- {
- if (capab.find("CHANMODES") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 10, capab.end());
- commasepstream sep(modes);
- Anope::string modebuf;
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'b':
- ModeManager::AddChannelMode(new InspIRCdExtBan("BAN", 'b'));
- continue;
- case 'e':
- ModeManager::AddChannelMode(new InspIRCdExtBan("EXCEPT", 'e'));
- continue;
- case 'I':
- ModeManager::AddChannelMode(new InspIRCdExtBan("INVITEOVERRIDE", 'I'));
- continue;
- /* InspIRCd sends q and a here if they have no prefixes */
- case 'q':
- ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '@', 4));
- continue;
- case 'a':
- ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT" , 'a', '@', 3));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeList("", modebuf[t]));
- }
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'k':
- ModeManager::AddChannelMode(new ChannelModeKey('k'));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t]));
- }
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'F':
- ModeManager::AddChannelMode(new ChannelModeParam("NICKFLOOD", 'F', true));
- continue;
- case 'J':
- ModeManager::AddChannelMode(new ChannelModeParam("NOREJOIN", 'J', true));
- continue;
- case 'L':
- ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L', true));
- continue;
- case 'f':
- ModeManager::AddChannelMode(new ChannelModeFlood('f', true));
- continue;
- case 'j':
- ModeManager::AddChannelMode(new ChannelModeParam("JOINFLOOD", 'j', true));
- continue;
- case 'l':
- ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t], true));
- }
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'A':
- ModeManager::AddChannelMode(new ChannelMode("ALLINVITE", 'A'));
- continue;
- case 'B':
- ModeManager::AddChannelMode(new ChannelMode("BLOCKCAPS", 'B'));
- continue;
- case 'C':
- ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
- continue;
- case 'D':
- ModeManager::AddChannelMode(new ChannelMode("DELAYEDJOIN", 'D'));
- continue;
- case 'G':
- ModeManager::AddChannelMode(new ChannelMode("CENSOR", 'G'));
- continue;
- case 'K':
- ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K'));
- continue;
- case 'M':
- ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
- continue;
- case 'N':
- ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N'));
- continue;
- case 'O':
- ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O'));
- continue;
- case 'P':
- ModeManager::AddChannelMode(new ChannelMode("PERM", 'P'));
- continue;
- case 'Q':
- ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q'));
- continue;
- case 'R':
- ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
- continue;
- case 'S':
- ModeManager::AddChannelMode(new ChannelMode("STRIPCOLOR", 'S'));
- continue;
- case 'T':
- ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'T'));
- continue;
- case 'c':
- ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c'));
- continue;
- case 'i':
- ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i'));
- continue;
- case 'm':
- ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm'));
- continue;
- case 'n':
- ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n'));
- continue;
- case 'p':
- ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
- continue;
- case 'r':
- ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r'));
- continue;
- case 's':
- ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
- continue;
- case 't':
- ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
- continue;
- case 'u':
- ModeManager::AddChannelMode(new ChannelMode("AUDITORIUM", 'u'));
- continue;
- case 'z':
- ModeManager::AddChannelMode(new ChannelMode("SSL", 'z'));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelMode("", modebuf[t]));
- }
- }
- }
- else if (capab.find("USERMODES") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 10, capab.end());
- commasepstream sep(modes);
- Anope::string modebuf;
-
- while (sep.GetToken(modebuf))
- {
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'h':
- ModeManager::AddUserMode(new UserModeOperOnly("HELPOP", 'h'));
- continue;
- case 'B':
- ModeManager::AddUserMode(new UserMode("BOT", 'B'));
- continue;
- case 'G':
- ModeManager::AddUserMode(new UserMode("CENSOR", 'G'));
- continue;
- case 'H':
- ModeManager::AddUserMode(new UserModeOperOnly("HIDEOPER", 'H'));
- continue;
- case 'I':
- ModeManager::AddUserMode(new UserMode("PRIV", 'I'));
- continue;
- case 'Q':
- ModeManager::AddUserMode(new UserModeOperOnly("HIDDEN", 'Q'));
- continue;
- case 'R':
- ModeManager::AddUserMode(new UserMode("REGPRIV", 'R'));
- continue;
- case 'S':
- ModeManager::AddUserMode(new UserMode("STRIPCOLOR", 'S'));
- continue;
- case 'W':
- ModeManager::AddUserMode(new UserMode("WHOIS", 'W'));
- continue;
- case 'c':
- ModeManager::AddUserMode(new UserMode("COMMONCHANS", 'c'));
- continue;
- case 'g':
- ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
- continue;
- case 'i':
- ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
- continue;
- case 'k':
- ModeManager::AddUserMode(new UserModeNoone("PROTECTED", 'k'));
- continue;
- case 'o':
- ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
- continue;
- case 'r':
- ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r'));
- continue;
- case 'w':
- ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
- continue;
- case 'x':
- ModeManager::AddUserMode(new UserMode("CLOAK", 'x'));
- continue;
- case 'd':
- ModeManager::AddUserMode(new UserMode("DEAF", 'd'));
- continue;
- default:
- ModeManager::AddUserMode(new UserMode("", modebuf[t]));
- }
- }
- }
- }
- else if (capab.find("PREFIX=(") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')'));
- Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end());
- unsigned short level = modes.length() - 1;
-
- for (size_t t = 0, end = modes.length(); t < end; ++t)
- {
- switch (modes[t])
- {
- case 'q':
- ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', chars[t], level--));
- continue;
- case 'a':
- ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', chars[t], level--));
- continue;
- case 'o':
- ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', chars[t], level--));
- continue;
- case 'h':
- ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', chars[t], level--));
- continue;
- case 'v':
- ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', chars[t], level--));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeStatus("", modes[t], chars[t], level--));
- }
- }
-
- ModeManager::RebuildStatusModes();
- }
- else if (capab.find("MAXMODES=") != Anope::string::npos)
- {
- Anope::string maxmodes(capab.begin() + 9, capab.end());
- IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
- }
- }
- }
- else if (params[0].equals_cs("END"))
- {
- if (!Servers::Capab.count("GLOBOPS"))
- {
- UplinkSocket::Message() << "ERROR :m_globops is not loaded. This is required by Anope";
- Anope::QuitReason = "Remote server does not have the m_globops module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!Servers::Capab.count("SERVICES"))
- {
- UplinkSocket::Message() << "ERROR :m_services_account.so is not loaded. This is required by Anope";
- Anope::QuitReason = "ERROR: Remote server does not have the m_services_account module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!Servers::Capab.count("HIDECHANS"))
- {
- UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope";
- Anope::QuitReason = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!IRCD->CanSVSHold)
- Log() << "SVSHOLD missing, Usage disabled until module is loaded.";
- if (!Servers::Capab.count("CHGHOST"))
- Log() << "CHGHOST missing, Usage disabled until module is loaded.";
- if (!Servers::Capab.count("CHGIDENT"))
- Log() << "CHGIDENT missing, Usage disabled until module is loaded.";
- }
-
- Message::Capab::Run(source, params);
- }
-};
-
-struct IRCDMessageChgIdent : IRCDMessage
-{
- IRCDMessageChgIdent(Module *creator) : IRCDMessage(creator, "CHGIDENT", 2) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = User::Find(params[0]);
- if (u)
- u->SetIdent(params[1]);
- }
-};
-
-struct IRCDMessageChgName : IRCDMessage
-{
- IRCDMessageChgName(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->SetRealname(params[0]);
- }
-};
-
-struct IRCDMessageEncap : IRCDMessage
-{
- IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!Anope::Match(Me->GetSID(), params[0]) && !Anope::Match(Me->GetName(), params[0]))
- return;
-
- if (SASL::sasl && params[1] == "SASL" && params.size() >= 6)
- {
- SASL::Message m;
- m.source = params[2];
- m.target = params[3];
- m.type = params[4];
- m.data = params[5];
- m.ext = params.size() > 6 ? params[6] : "";
-
- SASL::sasl->ProcessMessage(m);
- }
- }
-};
-
-struct IRCDMessageEndburst : IRCDMessage
-{
- IRCDMessageEndburst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Server *s = source.GetServer();
-
- Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName();
-
- s->Sync(true);
- }
-};
-
-struct IRCDMessageFHost : IRCDMessage
-{
- IRCDMessageFHost(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->SetDisplayedHost(params[0]);
- }
-};
-
-struct IRCDMessageFJoin : IRCDMessage
-{
- IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Anope::string modes;
- if (params.size() >= 3)
- {
- for (unsigned i = 2; i < params.size() - 1; ++i)
- modes += " " + params[i];
- if (!modes.empty())
- modes.erase(modes.begin());
- }
-
- std::list<Message::Join::SJoinUser> users;
-
- spacesepstream sep(params[params.size() - 1]);
- Anope::string buf;
- while (sep.GetToken(buf))
- {
- Message::Join::SJoinUser sju;
-
- /* Loop through prefixes and find modes for them */
- for (char c; (c = buf[0]) != ',' && c;)
- {
- buf.erase(buf.begin());
- sju.first.AddMode(c);
- }
- /* Erase the , */
- if (!buf.empty())
- buf.erase(buf.begin());
-
- sju.second = User::Find(buf);
- if (!sju.second)
- {
- Log(LOG_DEBUG) << "FJOIN for nonexistent user " << buf << " on " << params[0];
- continue;
- }
-
- users.push_back(sju);
- }
-
- time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
- Message::Join::SJoin(source, params[0], ts, modes, users);
- }
-};
-
-struct IRCDMessageFMode : IRCDMessage
-{
- IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- /* :source FMODE #test 12345678 +nto foo */
-
- Anope::string modes = params[2];
- for (unsigned n = 3; n < params.size(); ++n)
- modes += " " + params[n];
-
- Channel *c = Channel::Find(params[0]);
- time_t ts;
-
- try
- {
- ts = convertTo<time_t>(params[1]);
- }
- catch (const ConvertException &)
- {
- ts = 0;
- }
-
- if (c)
- c->SetModesInternal(source, modes, ts);
- }
-};
-
-struct IRCDMessageFTopic : IRCDMessage
-{
- IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- /* :source FTOPIC channel topicts setby :topic */
-
- Channel *c = Channel::Find(params[0]);
- if (c)
- c->ChangeTopicInternal(NULL, params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime);
- }
-};
-
-struct IRCDMessageIdle : IRCDMessage
-{
- IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- BotInfo *bi = BotInfo::Find(params[0]);
- if (bi)
- UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " " << (Anope::CurTime - bi->lastmsg);
- else
- {
- User *u = User::Find(params[0]);
- if (u && u->server == Me)
- UplinkSocket::Message(u) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " 0";
- }
- }
-};
-
-/*
- * source = numeric of the sending server
- * params[0] = uuid
- * params[1] = metadata name
- * params[2] = data
- */
-struct IRCDMessageMetadata : IRCDMessage
-{
- IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (isdigit(params[0][0]))
- {
- if (params[1].equals_cs("accountname"))
- {
- User *u = User::Find(params[0]);
- NickCore *nc = NickCore::Find(params[2]);
- if (u && nc)
- u->Login(nc);
- }
-
- /*
- * possible incoming ssl_cert messages:
- * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...>
- * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0)
- */
- else if (params[1].equals_cs("ssl_cert"))
- {
- User *u = User::Find(params[0]);
- if (!u)
- return;
- u->Extend<bool>("ssl");
- Anope::string data = params[2].c_str();
- size_t pos1 = data.find(' ') + 1;
- size_t pos2 = data.find(' ', pos1);
- if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes.
- {
- u->fingerprint = data.substr(pos1, pos2 - pos1);
- }
- FOREACH_MOD(OnFingerprint, (u));
- }
- }
- else if (params[0][0] == '#')
- {
- }
- else if (params[0] == "*")
- {
- // Wed Oct 3 15:40:27 2012: S[14] O :20D METADATA * modules :-m_svstopic.so
-
- if (params[1].equals_cs("modules") && !params[2].empty())
- {
- // only interested when it comes from our uplink
- Server* server = source.GetServer();
- if (!server || server->GetUplink() != Me)
- return;
-
- bool plus = (params[2][0] == '+');
- if (!plus && params[2][0] != '-')
- return;
-
- bool required = false;
- Anope::string capab, module = params[2].substr(1);
-
- if (module.equals_cs("m_services_account.so"))
- required = true;
- else if (module.equals_cs("m_hidechans.so"))
- required = true;
- else if (module.equals_cs("m_chghost.so"))
- capab = "CHGHOST";
- else if (module.equals_cs("m_chgident.so"))
- capab = "CHGIDENT";
- else if (module.equals_cs("m_svshold.so"))
- capab = "SVSHOLD";
- else if (module.equals_cs("m_rline.so"))
- capab = "RLINE";
- else if (module.equals_cs("m_topiclock.so"))
- capab = "TOPICLOCK";
- else
- return;
-
- if (required)
- {
- if (!plus)
- Log() << "Warning: InspIRCd unloaded module " << module << ", Anope won't function correctly without it";
- }
- else
- {
- if (plus)
- Servers::Capab.insert(capab);
- else
- Servers::Capab.erase(capab);
-
- Log() << "InspIRCd " << (plus ? "loaded" : "unloaded") << " module " << module << ", adjusted functionality";
- }
-
- }
- }
- }
-};
-
-struct IRCDMessageMode : IRCDMessage
-{
- IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (IRCD->IsChannelValid(params[0]))
- {
- Channel *c = Channel::Find(params[0]);
-
- Anope::string modes = params[1];
- for (unsigned n = 2; n < params.size(); ++n)
- modes += " " + params[n];
-
- if (c)
- c->SetModesInternal(source, modes);
- }
- else
- {
- /* InspIRCd lets opers change another
- users modes, we have to kludge this
- as it slightly breaks RFC1459
- */
- User *u = User::Find(params[0]);
- if (u)
- u->SetModesInternal(source, "%s", params[1].c_str());
- }
- }
-};
-
-struct IRCDMessageNick : IRCDMessage
-{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->ChangeNick(params[0]);
- }
-};
-
-struct IRCDMessageOperType : IRCDMessage
-{
- IRCDMessageOperType(Module *creator) : IRCDMessage(creator, "OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- /* opertype is equivalent to mode +o because servers
- don't do this directly */
- User *u = source.GetUser();
- if (!u->HasMode("OPER"))
- u->SetModesInternal(source, "+o");
- }
-};
-
-struct IRCDMessageRSQuit : IRCDMessage
-{
- IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Server *s = Server::Find(params[0]);
- const Anope::string &reason = params.size() > 1 ? params[1] : "";
- if (!s)
- return;
-
- UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << reason;
- s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
- }
-};
-
-struct IRCDMessageSetIdent : IRCDMessage
-{
- IRCDMessageSetIdent(Module *creator) : IRCDMessage(creator, "SETIDENT", 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->SetIdent(params[0]);
- }
-};
-
-struct IRCDMessageServer : IRCDMessage
-{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- /*
- * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central!
- * 0: name
- * 1: pass
- * 2: hops
- * 3: numeric
- * 4: desc
- */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0;
- new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[4], params[3]);
- }
-};
-
-struct IRCDMessageSQuit : Message::SQuit
-{
- IRCDMessageSQuit(Module *creator) : Message::SQuit(creator) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params[0] == rsquit_id || params[0] == rsquit_server)
- {
- /* squit for a recently squit server, introduce the juped server now */
- Server *s = Server::Find(rsquit_server);
-
- rsquit_id.clear();
- rsquit_server.clear();
-
- if (s && s->IsJuped())
- IRCD->SendServer(s);
- }
- else
- Message::SQuit::Run(source, params);
- }
-};
-
-struct IRCDMessageTime : IRCDMessage
-{
- IRCDMessageTime(Module *creator) : IRCDMessage(creator, "TIME", 2) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- UplinkSocket::Message(Me) << "TIME " << source.GetSource() << " " << params[1] << " " << Anope::CurTime;
- }
-};
-
-struct IRCDMessageUID : IRCDMessage
-{
- IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- /*
- * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org>
- * 0: uid
- * 1: ts
- * 2: nick
- * 3: host
- * 4: dhost
- * 5: ident
- * 6: ip
- * 7: signon
- * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname!
- * last: realname
- */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- time_t ts = convertTo<time_t>(params[1]);
-
- Anope::string modes = params[8];
- for (unsigned i = 9; i < params.size() - 1; ++i)
- modes += " " + params[i];
-
- NickAlias *na = NULL;
- if (SASL::sasl)
- for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
- {
- SASLUser &u = *it;
-
- if (u.created + 30 < Anope::CurTime)
- it = saslusers.erase(it);
- else if (u.uid == params[0])
- {
- na = NickAlias::Find(u.acc);
- it = saslusers.erase(it);
- }
- else
- ++it;
- }
-
- User *u = User::OnIntroduce(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0], na ? *na->nc : NULL);
- if (u)
- u->signon = convertTo<time_t>(params[7]);
- }
-};
-
-class ProtoInspIRCd12 : public Module
-{
- InspIRCd12Proto ircd_proto;
- ExtensibleItem<bool> ssl;
-
- /* Core message handlers */
- Message::Away message_away;
- Message::Error message_error;
- Message::Invite message_invite;
- Message::Join message_join;
- Message::Kick message_kick;
- Message::Kill message_kill;
- Message::MOTD message_motd;
- Message::Notice message_notice;
- Message::Part message_part;
- Message::Ping message_ping;
- Message::Privmsg message_privmsg;
- Message::Quit message_quit;
- Message::Stats message_stats;
- Message::Topic message_topic;
-
- /* Our message handlers */
- IRCDMessageChgIdent message_chgident;
- IRCDMessageChgName message_setname, message_chgname;
- IRCDMessageCapab message_capab;
- IRCDMessageEncap message_encap;
- IRCDMessageEndburst message_endburst;
- IRCDMessageFHost message_fhost, message_sethost;
- IRCDMessageFJoin message_fjoin;
- IRCDMessageFMode message_fmode;
- IRCDMessageFTopic message_ftopic;
- IRCDMessageIdle message_idle;
- IRCDMessageMetadata message_metadata;
- IRCDMessageMode message_mode;
- IRCDMessageNick message_nick;
- IRCDMessageOperType message_opertype;
- IRCDMessageRSQuit message_rsquit;
- IRCDMessageSetIdent message_setident;
- IRCDMessageServer message_server;
- IRCDMessageSQuit message_squit;
- IRCDMessageTime message_time;
- IRCDMessageUID message_uid;
-
- public:
- ProtoInspIRCd12(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
- ircd_proto(this), ssl(this, "ssl"),
- message_away(this), message_error(this), message_invite(this), message_join(this), message_kick(this), message_kill(this),
- message_motd(this), message_notice(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this),
- message_stats(this), message_topic(this),
-
- message_chgident(this), message_setname(this, "SETNAME"), message_chgname(this, "FNAME"), message_capab(this), message_encap(this),
- message_endburst(this),
- message_fhost(this, "FHOST"), message_sethost(this, "SETHOST"), message_fjoin(this), message_fmode(this), message_ftopic(this),
- message_idle(this), message_metadata(this), message_mode(this), message_nick(this), message_opertype(this), message_rsquit(this),
- message_setident(this), message_server(this), message_squit(this), message_time(this), message_uid(this)
- {
- Servers::Capab.insert("NOQUIT");
- }
-
- void OnUserNickChange(User *u, const Anope::string &) anope_override
- {
- /* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later
- * this will cancel out this -r, resulting in no mode changes.
- *
- * Do not set -r if we don't have a NickServ loaded - DP
- */
- BotInfo *NickServ = Config->GetClient("NickServ");
- if (NickServ)
- u->RemoveMode(NickServ, "REGISTERED");
- }
-};
-
-MODULE_INIT(ProtoInspIRCd12)
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp
deleted file mode 100644
index dc7deaea0..000000000
--- a/modules/protocol/inspircd20.cpp
+++ /dev/null
@@ -1,1106 +0,0 @@
-/* InspIRCd 2.0 functions
- *
- * (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/cs_mode.h"
-
-static unsigned int spanningtree_proto_ver = 0;
-
-static ServiceReference<IRCDProto> insp12("IRCDProto", "inspircd12");
-
-class InspIRCd20Proto : public IRCDProto
-{
- public:
- InspIRCd20Proto(Module *creator) : IRCDProto(creator, "InspIRCd 2.0")
- {
- DefaultPseudoclientModes = "+I";
- CanSVSNick = true;
- CanSVSJoin = true;
- CanSetVHost = true;
- CanSetVIdent = true;
- CanSQLine = true;
- CanSZLine = true;
- CanSVSHold = true;
- CanCertFP = true;
- RequiresID = true;
- MaxModes = 20;
- }
-
- void SendConnect() anope_override
- {
- UplinkSocket::Message() << "CAPAB START 1202";
- UplinkSocket::Message() << "CAPAB CAPABILITIES :PROTOCOL=1202";
- UplinkSocket::Message() << "CAPAB END";
- insp12->SendConnect();
- }
-
- void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
- {
- Anope::string mechlist;
- for (unsigned i = 0; i < mechanisms.size(); ++i)
- mechlist += "," + mechanisms[i];
-
- UplinkSocket::Message(Me) << "METADATA * saslmechlist :" << (mechanisms.empty() ? "" : mechlist.substr(1));
- }
-
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override { insp12->SendSVSKillInternal(source, user, buf); }
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { insp12->SendGlobalNotice(bi, dest, msg); }
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { insp12->SendGlobalPrivmsg(bi, dest, msg); }
- void SendAkillDel(const XLine *x) anope_override { insp12->SendAkillDel(x); }
- void SendTopic(const MessageSource &whosets, Channel *c) anope_override { insp12->SendTopic(whosets, c); };
- void SendVhostDel(User *u) anope_override { insp12->SendVhostDel(u); }
- void SendAkill(User *u, XLine *x) anope_override { insp12->SendAkill(u, x); }
- void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override { insp12->SendNumericInternal(numeric, dest, buf); }
- void SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) anope_override { insp12->SendModeInternal(source, dest, buf); }
- void SendClientIntroduction(User *u) anope_override { insp12->SendClientIntroduction(u); }
- void SendServer(const Server *server) anope_override { insp12->SendServer(server); }
- void SendSquit(Server *s, const Anope::string &message) anope_override { insp12->SendSquit(s, message); }
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { insp12->SendJoin(user, c, status); }
- void SendSQLineDel(const XLine *x) anope_override { insp12->SendSQLineDel(x); }
- void SendSQLine(User *u, const XLine *x) anope_override { insp12->SendSQLine(u, x); }
- void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) anope_override { insp12->SendVhost(u, vident, vhost); }
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override { insp12->SendSVSHold(nick, t); }
- void SendSVSHoldDel(const Anope::string &nick) anope_override { insp12->SendSVSHoldDel(nick); }
- void SendSZLineDel(const XLine *x) anope_override { insp12->SendSZLineDel(x); }
- void SendSZLine(User *u, const XLine *x) anope_override { insp12->SendSZLine(u, x); }
- void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &other) anope_override { insp12->SendSVSJoin(source, u, chan, other); }
- void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) anope_override { insp12->SendSVSPart(source, u, chan, param); }
- void SendSWhois(const MessageSource &bi, const Anope::string &who, const Anope::string &mask) anope_override { insp12->SendSWhois(bi, who, mask); }
- void SendBOB() anope_override { insp12->SendBOB(); }
- void SendEOB() anope_override { insp12->SendEOB(); }
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) { insp12->SendGlobopsInternal(source, buf); }
- void SendLogin(User *u, NickAlias *na) anope_override { insp12->SendLogin(u, na); }
- void SendLogout(User *u) anope_override { insp12->SendLogout(u); }
- void SendChannel(Channel *c) anope_override { insp12->SendChannel(c); }
- void SendSASLMessage(const SASL::Message &message) anope_override { insp12->SendSASLMessage(message); }
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override { insp12->SendSVSLogin(uid, acc, vident, vhost); }
- bool IsExtbanValid(const Anope::string &mask) anope_override { return insp12->IsExtbanValid(mask); }
- bool IsIdentValid(const Anope::string &ident) anope_override { return insp12->IsIdentValid(ident); }
-};
-
-class InspIRCdAutoOpMode : public ChannelModeList
-{
- public:
- InspIRCdAutoOpMode(char mode) : ChannelModeList("AUTOOP", mode)
- {
- }
-
- bool IsValid(Anope::string &mask) const anope_override
- {
- // We can not validate this because we don't know about the
- // privileges of the setter so just reject attempts to set it.
- return false;
- }
-};
-
-class InspIRCdExtBan : public ChannelModeVirtual<ChannelModeList>
-{
- char ext;
-
- public:
- InspIRCdExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
- , ext(extban)
- {
- }
-
- ChannelMode *Wrap(Anope::string &param) anope_override
- {
- param = Anope::string(ext) + ":" + param;
- return ChannelModeVirtual<ChannelModeList>::Wrap(param);
- }
-
- ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) anope_override
- {
- if (cm->type != MODE_LIST || param.length() < 3 || param[0] != ext || param[1] != ':')
- return cm;
-
- param = param.substr(2);
- return this;
- }
-};
-
-namespace InspIRCdExtban
-{
- class EntryMatcher : public InspIRCdExtBan
- {
- public:
- EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
-
- return Entry(this->name, real_mask).Matches(u);
- }
- };
-
- class ChannelMatcher : public InspIRCdExtBan
- {
- public:
- ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
-
- Anope::string channel = mask.substr(2);
-
- ChannelMode *cm = NULL;
- if (channel[0] != '#')
- {
- char modeChar = ModeManager::GetStatusChar(channel[0]);
- channel.erase(channel.begin());
- cm = ModeManager::FindChannelModeByChar(modeChar);
- if (cm != NULL && cm->type != MODE_STATUS)
- cm = NULL;
- }
-
- Channel *c = Channel::Find(channel);
- if (c != NULL)
- {
- ChanUserContainer *uc = c->FindUser(u);
- if (uc != NULL)
- if (cm == NULL || uc->status.HasMode(cm->mchar))
- return true;
- }
-
- return false;
- }
- };
-
- class AccountMatcher : public InspIRCdExtBan
- {
- public:
- AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
-
- return u->IsIdentified() && real_mask.equals_ci(u->Account()->display);
- }
- };
-
- class RealnameMatcher : public InspIRCdExtBan
- {
- public:
- RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return Anope::Match(u->realname, real_mask);
- }
- };
-
- class ServerMatcher : public InspIRCdExtBan
- {
- public:
- ServerMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return Anope::Match(u->server->GetName(), real_mask);
- }
- };
-
- class FingerprintMatcher : public InspIRCdExtBan
- {
- public:
- FingerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
- }
- };
-
- class UnidentifiedMatcher : public InspIRCdExtBan
- {
- public:
- UnidentifiedMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return !u->IsIdentified() && Entry("BAN", real_mask).Matches(u);
- }
- };
-}
-
-class ColonDelimitedParamMode : public ChannelModeParam
-{
- public:
- ColonDelimitedParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- return IsValid(value, false);
- }
-
- bool IsValid(const Anope::string &value, bool historymode) const
- {
- if (value.empty())
- return false; // empty param is never valid
-
- Anope::string::size_type pos = value.find(':');
- if ((pos == Anope::string::npos) || (pos == 0))
- return false; // no ':' or it's the first char, both are invalid
-
- Anope::string rest;
- try
- {
- if (convertTo<int>(value, rest, false) <= 0)
- return false; // negative numbers and zero are invalid
-
- rest = rest.substr(1);
- int n;
- if (historymode)
- {
- // For the history mode, the part after the ':' is a duration and it
- // can be in the user friendly "1d3h20m" format, make sure we accept that
- n = Anope::DoTime(rest);
- }
- else
- n = convertTo<int>(rest);
-
- if (n <= 0)
- return false;
- }
- catch (const ConvertException &e)
- {
- // conversion error, invalid
- return false;
- }
-
- return true;
- }
-};
-
-class SimpleNumberParamMode : public ChannelModeParam
-{
- public:
- SimpleNumberParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- if (value.empty())
- return false; // empty param is never valid
-
- try
- {
- if (convertTo<int>(value) <= 0)
- return false;
- }
- catch (const ConvertException &e)
- {
- // conversion error, invalid
- return false;
- }
-
- return true;
- }
-};
-
-class ChannelModeFlood : public ColonDelimitedParamMode
-{
- public:
- ChannelModeFlood(char modeChar) : ColonDelimitedParamMode("FLOOD", modeChar) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- // The parameter of this mode is a bit different, it may begin with a '*',
- // ignore it if that's the case
- Anope::string v = value[0] == '*' ? value.substr(1) : value;
- return ((!value.empty()) && (ColonDelimitedParamMode::IsValid(v)));
- }
-};
-
-class ChannelModeHistory : public ColonDelimitedParamMode
-{
- public:
- ChannelModeHistory(char modeChar) : ColonDelimitedParamMode("HISTORY", modeChar) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- return (ColonDelimitedParamMode::IsValid(value, true));
- }
-};
-
-class ChannelModeRedirect : public ChannelModeParam
-{
- public:
- ChannelModeRedirect(char modeChar) : ChannelModeParam("REDIRECT", modeChar, true) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- // The parameter of this mode is a channel, and channel names start with '#'
- return ((!value.empty()) && (value[0] == '#'));
- }
-};
-
-struct IRCDMessageAway : Message::Away
-{
- IRCDMessageAway(Module *creator) : Message::Away(creator, "AWAY") { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- std::vector<Anope::string> newparams(params);
- if (newparams.size() > 1)
- newparams.erase(newparams.begin());
-
- Message::Away::Run(source, newparams);
- }
-};
-
-struct IRCDMessageCapab : Message::Capab
-{
- std::map<char, Anope::string> chmodes, umodes;
-
- IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params[0].equals_cs("START"))
- {
- if (params.size() >= 2)
- spanningtree_proto_ver = (Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0);
-
- if (spanningtree_proto_ver < 1202)
- {
- UplinkSocket::Message() << "ERROR :Protocol mismatch, no or invalid protocol version given in CAPAB START";
- Anope::QuitReason = "Protocol mismatch, no or invalid protocol version given in CAPAB START";
- Anope::Quitting = true;
- return;
- }
-
- /* reset CAPAB */
- chmodes.clear();
- umodes.clear();
- Servers::Capab.insert("SERVERS");
- Servers::Capab.insert("TOPICLOCK");
- IRCD->CanSVSHold = false;
- IRCD->DefaultPseudoclientModes = "+I";
- }
- else if (params[0].equals_cs("CHANMODES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
-
- while (ssep.GetToken(capab))
- {
- Anope::string modename = capab.substr(0, capab.find('='));
- Anope::string modechar = capab.substr(capab.find('=') + 1);
- ChannelMode *cm = NULL;
-
- if (modename.equals_cs("admin"))
- cm = new ChannelModeStatus("PROTECT", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 3);
- else if (modename.equals_cs("allowinvite"))
- {
- cm = new ChannelMode("ALLINVITE", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("INVITEBAN", "BAN", 'A'));
- }
- else if (modename.equals_cs("auditorium"))
- cm = new ChannelMode("AUDITORIUM", modechar[0]);
- else if (modename.equals_cs("autoop"))
- cm = new InspIRCdAutoOpMode(modechar[0]);
- else if (modename.equals_cs("ban"))
- cm = new ChannelModeList("BAN", modechar[0]);
- else if (modename.equals_cs("banexception"))
- cm = new ChannelModeList("EXCEPT", modechar[0]);
- else if (modename.equals_cs("blockcaps"))
- {
- cm = new ChannelMode("BLOCKCAPS", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCAPSBAN", "BAN", 'B'));
- }
- else if (modename.equals_cs("blockcolor"))
- {
- cm = new ChannelMode("BLOCKCOLOR", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCOLORBAN", "BAN", 'c'));
- }
- else if (modename.equals_cs("c_registered"))
- cm = new ChannelModeNoone("REGISTERED", modechar[0]);
- else if (modename.equals_cs("censor"))
- cm = new ChannelMode("CENSOR", modechar[0]);
- else if (modename.equals_cs("delayjoin"))
- cm = new ChannelMode("DELAYEDJOIN", modechar[0]);
- else if (modename.equals_cs("delaymsg"))
- cm = new SimpleNumberParamMode("DELAYMSG", modechar[0]);
- else if (modename.equals_cs("filter"))
- cm = new ChannelModeList("FILTER", modechar[0]);
- else if (modename.equals_cs("flood"))
- cm = new ChannelModeFlood(modechar[0]);
- else if (modename.equals_cs("founder"))
- cm = new ChannelModeStatus("OWNER", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 4);
- else if (modename.equals_cs("halfop"))
- cm = new ChannelModeStatus("HALFOP", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 1);
- else if (modename.equals_cs("history"))
- cm = new ChannelModeHistory(modechar[0]);
- else if (modename.equals_cs("invex"))
- cm = new ChannelModeList("INVITEOVERRIDE", modechar[0]);
- else if (modename.equals_cs("inviteonly"))
- cm = new ChannelMode("INVITE", modechar[0]);
- else if (modename.equals_cs("joinflood"))
- cm = new ColonDelimitedParamMode("JOINFLOOD", modechar[0]);
- else if (modename.equals_cs("key"))
- cm = new ChannelModeKey(modechar[0]);
- else if (modename.equals_cs("kicknorejoin"))
- cm = new SimpleNumberParamMode("NOREJOIN", modechar[0]);
- else if (modename.equals_cs("limit"))
- cm = new ChannelModeParam("LIMIT", modechar[0], true);
- else if (modename.equals_cs("moderated"))
- cm = new ChannelMode("MODERATED", modechar[0]);
- else if (modename.equals_cs("nickflood"))
- cm = new ColonDelimitedParamMode("NICKFLOOD", modechar[0]);
- else if (modename.equals_cs("noctcp"))
- {
- cm = new ChannelMode("NOCTCP", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOCTCPBAN", "BAN", 'C'));
- }
- else if (modename.equals_cs("noextmsg"))
- cm = new ChannelMode("NOEXTERNAL", modechar[0]);
- else if (modename.equals_cs("nokick"))
- {
- cm = new ChannelMode("NOKICK", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOKICKBAN", "BAN", 'Q'));
- }
- else if (modename.equals_cs("noknock"))
- cm = new ChannelMode("NOKNOCK", modechar[0]);
- else if (modename.equals_cs("nonick"))
- {
- cm = new ChannelMode("NONICK", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONICKBAN", "BAN", 'N'));
- }
- else if (modename.equals_cs("nonotice"))
- {
- cm = new ChannelMode("NONOTICE", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONOTICEBAN", "BAN", 'T'));
- }
- else if (modename.equals_cs("official-join"))
- cm = new ChannelModeStatus("OFFICIALJOIN", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 2);
- else if (modename.equals_cs("op"))
- cm = new ChannelModeStatus("OP", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 2);
- else if (modename.equals_cs("operonly"))
- cm = new ChannelModeOperOnly("OPERONLY", modechar[0]);
- else if (modename.equals_cs("operprefix"))
- cm = new ChannelModeStatus("OPERPREFIX", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 2);
- else if (modename.equals_cs("permanent"))
- cm = new ChannelMode("PERM", modechar[0]);
- else if (modename.equals_cs("private"))
- cm = new ChannelMode("PRIVATE", modechar[0]);
- else if (modename.equals_cs("redirect"))
- cm = new ChannelModeRedirect(modechar[0]);
- else if (modename.equals_cs("reginvite"))
- cm = new ChannelMode("REGISTEREDONLY", modechar[0]);
- else if (modename.equals_cs("regmoderated"))
- cm = new ChannelMode("REGMODERATED", modechar[0]);
- else if (modename.equals_cs("secret"))
- cm = new ChannelMode("SECRET", modechar[0]);
- else if (modename.equals_cs("sslonly"))
- {
- cm = new ChannelMode("SSL", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::FingerprintMatcher("SSLBAN", "BAN", 'z'));
- }
- else if (modename.equals_cs("stripcolor"))
- {
- cm = new ChannelMode("STRIPCOLOR", modechar[0]);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("STRIPCOLORBAN", "BAN", 'S'));
- }
- else if (modename.equals_cs("topiclock"))
- cm = new ChannelMode("TOPIC", modechar[0]);
- else if (modename.equals_cs("voice"))
- cm = new ChannelModeStatus("VOICE", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 0);
- /* Unknown status mode, (customprefix) - add it */
- else if (modechar.length() == 2)
- cm = new ChannelModeStatus(modename.upper(), modechar[1], modechar[0], -1);
- /* Unknown non status mode, add it to our list for later */
- else
- chmodes[modechar[0]] = modename.upper();
-
- if (cm)
- ModeManager::AddChannelMode(cm);
- }
- }
- if (params[0].equals_cs("USERMODES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
-
- while (ssep.GetToken(capab))
- {
- Anope::string modename = capab.substr(0, capab.find('='));
- Anope::string modechar = capab.substr(capab.find('=') + 1);
- UserMode *um = NULL;
-
- if (modename.equals_cs("bot"))
- {
- um = new UserMode("BOT", modechar[0]);
- IRCD->DefaultPseudoclientModes += modechar;
- }
- else if (modename.equals_cs("callerid"))
- um = new UserMode("CALLERID", modechar[0]);
- else if (modename.equals_cs("cloak"))
- um = new UserMode("CLOAK", modechar[0]);
- else if (modename.equals_cs("deaf"))
- um = new UserMode("DEAF", modechar[0]);
- else if (modename.equals_cs("deaf_commonchan"))
- um = new UserMode("COMMONCHANS", modechar[0]);
- else if (modename.equals_cs("helpop"))
- um = new UserModeOperOnly("HELPOP", modechar[0]);
- else if (modename.equals_cs("hidechans"))
- um = new UserMode("PRIV", modechar[0]);
- else if (modename.equals_cs("hideoper"))
- um = new UserModeOperOnly("HIDEOPER", modechar[0]);
- else if (modename.equals_cs("invisible"))
- um = new UserMode("INVIS", modechar[0]);
- else if (modename.equals_cs("invis-oper"))
- um = new UserModeOperOnly("INVISIBLE_OPER", modechar[0]);
- else if (modename.equals_cs("oper"))
- um = new UserModeOperOnly("OPER", modechar[0]);
- else if (modename.equals_cs("regdeaf"))
- um = new UserMode("REGPRIV", modechar[0]);
- else if (modename.equals_cs("servprotect"))
- {
- um = new UserModeNoone("PROTECTED", modechar[0]);
- IRCD->DefaultPseudoclientModes += modechar;
- }
- else if (modename.equals_cs("showwhois"))
- um = new UserMode("WHOIS", modechar[0]);
- else if (modename.equals_cs("u_censor"))
- um = new UserMode("CENSOR", modechar[0]);
- else if (modename.equals_cs("u_registered"))
- um = new UserModeNoone("REGISTERED", modechar[0]);
- else if (modename.equals_cs("u_stripcolor"))
- um = new UserMode("STRIPCOLOR", modechar[0]);
- else if (modename.equals_cs("wallops"))
- um = new UserMode("WALLOPS", modechar[0]);
- else
- umodes[modechar[0]] = modename.upper();
-
- if (um)
- ModeManager::AddUserMode(um);
- }
- }
- else if (params[0].equals_cs("MODULES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string module;
-
- while (ssep.GetToken(module))
- {
- if (module.equals_cs("m_svshold.so"))
- IRCD->CanSVSHold = true;
- else if (module.find("m_rline.so") == 0)
- {
- Servers::Capab.insert("RLINE");
- const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
- if (!regexengine.empty() && module.length() > 11 && regexengine != module.substr(11))
- Log() << "Warning: InspIRCd is using regex engine " << module.substr(11) << ", but we have " << regexengine << ". This may cause inconsistencies.";
- }
- else if (module.equals_cs("m_topiclock.so"))
- Servers::Capab.insert("TOPICLOCK");
- }
- }
- else if (params[0].equals_cs("MODSUPPORT") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string module;
-
- while (ssep.GetToken(module))
- {
- if (module.equals_cs("m_services_account.so"))
- {
- Servers::Capab.insert("SERVICES");
- ModeManager::AddChannelMode(new InspIRCdExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'R'));
- ModeManager::AddChannelMode(new InspIRCdExtban::UnidentifiedMatcher("UNREGISTEREDBAN", "BAN", 'U'));
- }
- else if (module.equals_cs("m_chghost.so"))
- Servers::Capab.insert("CHGHOST");
- else if (module.equals_cs("m_chgident.so"))
- Servers::Capab.insert("CHGIDENT");
- else if (module == "m_channelban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::ChannelMatcher("CHANNELBAN", "BAN", 'j'));
- else if (module == "m_gecosban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
- else if (module == "m_nopartmsg.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("PARTMESSAGEBAN", "BAN", 'p'));
- else if (module == "m_serverban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::ServerMatcher("SERVERBAN", "BAN", 's'));
- else if (module == "m_muteban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("QUIET", "BAN", 'm'));
- }
- }
- else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
- while (ssep.GetToken(capab))
- {
- if (capab.find("CHANMODES") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 10, capab.end());
- commasepstream sep(modes, true);
- Anope::string modebuf;
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- if (ModeManager::FindChannelModeByChar(modebuf[t]))
- continue;
- ModeManager::AddChannelMode(new ChannelModeList(chmodes[modebuf[t]], modebuf[t]));
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- if (ModeManager::FindChannelModeByChar(modebuf[t]))
- continue;
- ModeManager::AddChannelMode(new ChannelModeParam(chmodes[modebuf[t]], modebuf[t]));
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- if (ModeManager::FindChannelModeByChar(modebuf[t]))
- continue;
- ModeManager::AddChannelMode(new ChannelModeParam(chmodes[modebuf[t]], modebuf[t], true));
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- if (ModeManager::FindChannelModeByChar(modebuf[t]))
- continue;
- ModeManager::AddChannelMode(new ChannelMode(chmodes[modebuf[t]], modebuf[t]));
- }
- }
- else if (capab.find("USERMODES") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 10, capab.end());
- commasepstream sep(modes, true);
- Anope::string modebuf;
-
- sep.GetToken(modebuf);
- sep.GetToken(modebuf);
-
- if (sep.GetToken(modebuf))
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- ModeManager::AddUserMode(new UserModeParam(umodes[modebuf[t]], modebuf[t]));
-
- if (sep.GetToken(modebuf))
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- ModeManager::AddUserMode(new UserMode(umodes[modebuf[t]], modebuf[t]));
- }
- else if (capab.find("MAXMODES=") != Anope::string::npos)
- {
- Anope::string maxmodes(capab.begin() + 9, capab.end());
- IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
- }
- else if (capab.find("PREFIX=") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')'));
- Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end());
- short level = modes.length() - 1;
-
- for (size_t t = 0, end = modes.length(); t < end; ++t)
- {
- ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[t]);
- if (cm == NULL || cm->type != MODE_STATUS)
- {
- Log() << "CAPAB PREFIX gave unknown channel status mode " << modes[t];
- continue;
- }
-
- ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
- cms->level = level--;
-
- Log(LOG_DEBUG) << cms->name << " is now level " << cms->level;
- }
-
- ModeManager::RebuildStatusModes();
- }
- else if (capab == "GLOBOPS=1")
- Servers::Capab.insert("GLOBOPS");
- }
- }
- else if (params[0].equals_cs("END"))
- {
- if (!Servers::Capab.count("SERVICES"))
- {
- UplinkSocket::Message() << "ERROR :m_services_account.so is not loaded. This is required by Anope";
- Anope::QuitReason = "ERROR: Remote server does not have the m_services_account module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!ModeManager::FindUserModeByName("PRIV"))
- {
- UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope";
- Anope::QuitReason = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!IRCD->CanSVSHold)
- Log() << "SVSHOLD missing, Usage disabled until module is loaded.";
- if (!Servers::Capab.count("CHGHOST"))
- Log() << "CHGHOST missing, Usage disabled until module is loaded.";
- if (!Servers::Capab.count("CHGIDENT"))
- Log() << "CHGIDENT missing, Usage disabled until module is loaded.";
-
- chmodes.clear();
- umodes.clear();
- }
-
- Message::Capab::Run(source, params);
- }
-};
-
-struct IRCDMessageEncap : IRCDMessage
-{
- ServiceReference<IRCDMessage> insp12_encap;
-
- IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4), insp12_encap("IRCDMessage", "inspircd12/encap") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!Anope::Match(Me->GetSID(), params[0]) && !Anope::Match(Me->GetName(), params[0]))
- return;
-
- if (params[1] == "CHGIDENT")
- {
- User *u = User::Find(params[2]);
- if (!u || u->server != Me)
- return;
-
- u->SetIdent(params[3]);
- UplinkSocket::Message(u) << "FIDENT :" << params[3];
- }
- else if (params[1] == "CHGHOST")
- {
- User *u = User::Find(params[2]);
- if (!u || u->server != Me)
- return;
-
- u->SetDisplayedHost(params[3]);
- UplinkSocket::Message(u) << "FHOST :" << params[3];
- }
- else if (params[1] == "CHGNAME")
- {
- User *u = User::Find(params[2]);
- if (!u || u->server != Me)
- return;
-
- u->SetRealname(params[3]);
- UplinkSocket::Message(u) << "FNAME :" << params[3];
- }
-
- if (insp12_encap)
- insp12_encap->Run(source, params);
- }
-};
-
-struct IRCDMessageFHost : IRCDMessage
-{
- IRCDMessageFHost(Module *creator) : IRCDMessage(creator, "FHOST", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = source.GetUser();
- if (u->HasMode("CLOAK"))
- u->RemoveModeInternal(source, ModeManager::FindUserModeByName("CLOAK"));
- u->SetDisplayedHost(params[0]);
- }
-};
-
-struct IRCDMessageFIdent : IRCDMessage
-{
- IRCDMessageFIdent(Module *creator) : IRCDMessage(creator, "FIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->SetIdent(params[0]);
- }
-};
-
-struct IRCDMessageSave : IRCDMessage
-{
- time_t last_collide;
-
- IRCDMessageSave(Module *creator) : IRCDMessage(creator, "SAVE", 2), last_collide(0) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *targ = User::Find(params[0]);
- time_t ts;
-
- try
- {
- ts = convertTo<time_t>(params[1]);
- }
- catch (const ConvertException &)
- {
- return;
- }
-
- if (!targ || targ->timestamp != ts)
- return;
-
- BotInfo *bi;
- if (targ->server == Me && (bi = dynamic_cast<BotInfo *>(targ)))
- {
- if (last_collide == Anope::CurTime)
- {
- Anope::QuitReason = "Nick collision fight on " + targ->nick;
- Anope::Quitting = true;
- return;
- }
-
- IRCD->SendKill(Me, targ->nick, "Nick collision");
- IRCD->SendNickChange(targ, targ->nick);
- last_collide = Anope::CurTime;
- }
- else
- targ->ChangeNick(targ->GetUID());
- }
-};
-
-class IRCDMessageMetadata : IRCDMessage
-{
- ServiceReference<IRCDMessage> insp12_metadata;
- const bool &do_topiclock;
- const bool &do_mlock;
-
- public:
- IRCDMessageMetadata(Module *creator, const bool &handle_topiclock, const bool &handle_mlock) : IRCDMessage(creator, "METADATA", 3), insp12_metadata("IRCDMessage", "inspircd12/metadata"), do_topiclock(handle_topiclock), do_mlock(handle_mlock) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- // We deliberately ignore non-bursting servers to avoid pseudoserver fights
- if ((params[0][0] == '#') && (!source.GetServer()->IsSynced()))
- {
- Channel *c = Channel::Find(params[0]);
- if (c && c->ci)
- {
- if ((do_mlock) && (params[1] == "mlock"))
- {
- ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
- Anope::string modes;
- if (modelocks)
- modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
-
- // Mode lock string is not what we say it is?
- if (modes != params[2])
- UplinkSocket::Message(Me) << "METADATA " << c->name << " mlock :" << modes;
- }
- else if ((do_topiclock) && (params[1] == "topiclock"))
- {
- bool mystate = c->ci->HasExt("TOPICLOCK");
- bool serverstate = (params[2] == "1");
- if (mystate != serverstate)
- UplinkSocket::Message(Me) << "METADATA " << c->name << " topiclock :" << (mystate ? "1" : "");
- }
- }
- }
-
- if (insp12_metadata)
- insp12_metadata->Run(source, params);
- }
-};
-
-class ProtoInspIRCd20 : public Module
-{
- Module *m_insp12;
-
- InspIRCd20Proto ircd_proto;
-
- /* Core message handlers */
- Message::Error message_error;
- Message::Invite message_invite;
- Message::Join message_join;
- Message::Kick message_kick;
- Message::Kill message_kill;
- Message::MOTD message_motd;
- Message::Notice message_notice;
- Message::Part message_part;
- Message::Ping message_ping;
- Message::Privmsg message_privmsg;
- Message::Quit message_quit;
- Message::Stats message_stats;
- Message::Topic message_topic;
-
- /* InspIRCd 1.2 message handlers */
- ServiceAlias message_endburst, message_fjoin, message_fmode,
- message_ftopic, message_idle, message_mode,
- message_nick, message_opertype, message_rsquit, message_server,
- message_squit, message_time, message_uid;
-
- /* Our message handlers */
- IRCDMessageAway message_away;
- IRCDMessageCapab message_capab;
- IRCDMessageEncap message_encap;
- IRCDMessageFHost message_fhost;
- IRCDMessageFIdent message_fident;
- IRCDMessageMetadata message_metadata;
- IRCDMessageSave message_save;
-
- bool use_server_side_topiclock, use_server_side_mlock;
-
- void SendChannelMetadata(Channel *c, const Anope::string &metadataname, const Anope::string &value)
- {
- UplinkSocket::Message(Me) << "METADATA " << c->name << " " << metadataname << " :" << value;
- }
-
- public:
- ProtoInspIRCd20(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
- ircd_proto(this),
- message_error(this), message_invite(this), message_join(this), message_kick(this), message_kill(this),
- message_motd(this), message_notice(this), message_part(this), message_ping(this), message_privmsg(this),
- message_quit(this), message_stats(this), message_topic(this),
-
- message_endburst("IRCDMessage", "inspircd20/endburst", "inspircd12/endburst"),
- message_fjoin("IRCDMessage", "inspircd20/fjoin", "inspircd12/fjoin"),
- message_fmode("IRCDMessage", "inspircd20/fmode", "inspircd12/fmode"),
- message_ftopic("IRCDMessage", "inspircd20/ftopic", "inspircd12/ftopic"),
- message_idle("IRCDMessage", "inspircd20/idle", "inspircd12/idle"),
- message_mode("IRCDMessage", "inspircd20/mode", "inspircd12/mode"),
- message_nick("IRCDMessage", "inspircd20/nick", "inspircd12/nick"),
- message_opertype("IRCDMessage", "inspircd20/opertype", "inspircd12/opertype"),
- message_rsquit("IRCDMessage", "inspircd20/rsquit", "inspircd12/rsquit"),
- message_server("IRCDMessage", "inspircd20/server", "inspircd12/server"),
- message_squit("IRCDMessage", "inspircd20/squit", "inspircd12/squit"),
- message_time("IRCDMessage", "inspircd20/time", "inspircd12/time"),
- message_uid("IRCDMessage", "inspircd20/uid", "inspircd12/uid"),
-
- message_away(this), message_capab(this), message_encap(this), message_fhost(this), message_fident(this),
- message_metadata(this, use_server_side_topiclock, use_server_side_mlock), message_save(this)
- {
-
- if (ModuleManager::LoadModule("inspircd12", User::Find(creator)) != MOD_ERR_OK)
- throw ModuleException("Unable to load inspircd12");
- m_insp12 = ModuleManager::FindModule("inspircd12");
- if (!m_insp12)
- throw ModuleException("Unable to find inspircd12");
- if (!insp12)
- throw ModuleException("No protocol interface for insp12");
- ModuleManager::DetachAll(m_insp12);
-
- }
-
- ~ProtoInspIRCd20()
- {
- m_insp12 = ModuleManager::FindModule("inspircd12");
- ModuleManager::UnloadModule(m_insp12, NULL);
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- use_server_side_topiclock = conf->GetModule(this)->Get<bool>("use_server_side_topiclock");
- use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- }
-
- void OnUserNickChange(User *u, const Anope::string &) anope_override
- {
- u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
- }
-
- void OnChannelSync(Channel *c) anope_override
- {
- if (c->ci)
- this->OnChanRegistered(c->ci);
- }
-
- void OnChanRegistered(ChannelInfo *ci) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- if (use_server_side_mlock && ci->c && modelocks && !modelocks->GetMLockAsString(false).empty())
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- SendChannelMetadata(ci->c, "mlock", modes);
- }
-
- if (use_server_side_topiclock && Servers::Capab.count("TOPICLOCK") && ci->c)
- {
- if (ci->HasExt("TOPICLOCK"))
- SendChannelMetadata(ci->c, "topiclock", "1");
- }
- }
-
- void OnDelChan(ChannelInfo *ci) anope_override
- {
- if (use_server_side_mlock && ci->c)
- SendChannelMetadata(ci->c, "mlock", "");
-
- if (use_server_side_topiclock && Servers::Capab.count("TOPICLOCK") && ci->c)
- SendChannelMetadata(ci->c, "topiclock", "");
- }
-
- EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
- SendChannelMetadata(ci->c, "mlock", modes);
- }
-
- return EVENT_CONTINUE;
- }
-
- EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
- SendChannelMetadata(ci->c, "mlock", modes);
- }
-
- return EVENT_CONTINUE;
- }
-
- EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) anope_override
- {
- if (cmd->name == "chanserv/topic" && ci->c)
- {
- if (setting == "topiclock on")
- SendChannelMetadata(ci->c, "topiclock", "1");
- else if (setting == "topiclock off")
- SendChannelMetadata(ci->c, "topiclock", "0");
- }
-
- return EVENT_CONTINUE;
- }
-};
-
-MODULE_INIT(ProtoInspIRCd20)
diff --git a/modules/protocol/inspircd3.cpp b/modules/protocol/inspircd3.cpp
deleted file mode 100644
index 83036cf0b..000000000
--- a/modules/protocol/inspircd3.cpp
+++ /dev/null
@@ -1,2031 +0,0 @@
-/* InspIRCd 3.0 functions
- *
- * (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/cs_mode.h"
-#include "modules/sasl.h"
-
-typedef std::map<char, unsigned> ListLimits;
-
-struct SASLUser
-{
- Anope::string uid;
- Anope::string acc;
- time_t created;
-};
-
-static std::list<SASLUser> saslusers;
-
-static Anope::string rsquit_server, rsquit_id;
-
-class InspIRCd3Proto : public IRCDProto
-{
- private:
- void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent)
- {
- if (!Servers::Capab.count("CHGIDENT"))
- Log() << "CHGIDENT not loaded!";
- else
- UplinkSocket::Message(Me) << "CHGIDENT " << nick << " " << vIdent;
- }
-
- void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost)
- {
- if (!Servers::Capab.count("CHGHOST"))
- Log() << "CHGHOST not loaded!";
- else
- UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost;
- }
-
- void SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason)
- {
- UplinkSocket::Message(Me) << "ADDLINE " << xtype << " " << mask << " " << addedby << " " << Anope::CurTime << " " << duration << " :" << reason;
- }
-
- void SendDelLine(const Anope::string &xtype, const Anope::string &mask)
- {
- UplinkSocket::Message(Me) << "DELLINE " << xtype << " " << mask;
- }
-
- public:
- PrimitiveExtensibleItem<ListLimits> maxlist;
-
- InspIRCd3Proto(Module *creator) : IRCDProto(creator, "InspIRCd 3"), maxlist(creator, "maxlist")
- {
- DefaultPseudoclientModes = "+oI";
- CanSVSNick = true;
- CanSVSJoin = true;
- CanSetVHost = true;
- CanSetVIdent = true;
- CanSQLine = true;
- CanSZLine = true;
- CanCertFP = true;
- RequiresID = true;
- MaxModes = 20;
- MaxLine = 4096;
- }
-
- unsigned GetMaxListFor(Channel *c, ChannelMode *cm) anope_override
- {
- ListLimits *limits = maxlist.Get(c);
- if (limits)
- {
- ListLimits::const_iterator limit = limits->find(cm->mchar);
- if (limit != limits->end())
- return limit->second;
- }
-
- // Fall back to the config limit if we can't find the mode.
- return IRCDProto::GetMaxListFor(c, cm);
- }
-
- void SendConnect() anope_override
- {
- UplinkSocket::Message() << "CAPAB START 1205";
- UplinkSocket::Message() << "CAPAB CAPABILITIES :CASEMAPPING=" << Config->GetBlock("options")->Get<const Anope::string>("casemap", "ascii");
- UplinkSocket::Message() << "CAPAB END";
- UplinkSocket::Message() << "SERVER " << Me->GetName() << " " << Config->Uplinks[Anope::CurrentUplink].password << " 0 " << Me->GetSID() << " :" << Me->GetDescription();
- }
-
- void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
- {
- Anope::string mechlist;
- for (unsigned i = 0; i < mechanisms.size(); ++i)
- mechlist += "," + mechanisms[i];
-
- UplinkSocket::Message(Me) << "METADATA * saslmechlist :" << (mechanisms.empty() ? "" : mechlist.substr(1));
- }
-
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override
- {
- IRCDProto::SendSVSKillInternal(source, user, buf);
- user->KillInternal(source, buf);
- }
-
- void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override
- {
- UplinkSocket::Message() << "SVSNICK " << u->GetUID() << " " << newnick << " " << when << " " << u->timestamp;
- }
-
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
- {
- UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
- }
-
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
- {
- UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
- }
-
- void SendPong(const Anope::string &servname, const Anope::string &who) anope_override
- {
- Server *serv = servname.empty() ? NULL : Server::Find(servname);
- if (!serv)
- serv = Me;
-
- UplinkSocket::Message(serv) << "PONG " << who;
- }
-
- void SendAkillDel(const XLine *x) anope_override
- {
- {
- /* InspIRCd may support regex bans
- * Mask is expected in format: 'n!u@h\sr' and spaces as '\s'
- * We remove the '//' and replace '#' and any ' ' with '\s'
- */
- if (x->IsRegex() && Servers::Capab.count("RLINE"))
- {
- Anope::string mask = x->mask;
- if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
- mask = mask.substr(1, mask.length() - 2);
- size_t h = mask.find('#');
- if (h != Anope::string::npos)
- {
- mask = mask.replace(h, 1, "\\s");
- mask = mask.replace_all_cs(" ", "\\s");
- }
- SendDelLine("R", mask);
- return;
- }
- else if (x->IsRegex() || x->HasNickOrReal())
- return;
-
- /* ZLine if we can instead */
- if (x->GetUser() == "*")
- {
- cidr addr(x->GetHost());
- if (addr.valid())
- {
- IRCD->SendSZLineDel(x);
- return;
- }
- }
-
- SendDelLine("G", x->GetUser() + "@" + x->GetHost());
- }
- }
-
- void SendInvite(const MessageSource &source, const Channel *c, User *u) anope_override
- {
- UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name << " " << c->creation_time;
- }
-
- void SendTopic(const MessageSource &source, Channel *c) anope_override
- {
- if (Servers::Capab.count("TOPICLOCK"))
- {
- UplinkSocket::Message(c->WhoSends()) << "SVSTOPIC " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic;
- }
- else
- {
- /* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */
- time_t ts = c->topic_ts;
- if (c->topic_time > ts)
- ts = Anope::CurTime;
- /* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */
- UplinkSocket::Message(source) << "FTOPIC " << c->name << " " << c->creation_time << " " << ts << " " << c->topic_setter << " :" << c->topic;
- }
- }
-
- void SendVhostDel(User *u) anope_override
- {
- UserMode *um = ModeManager::FindUserModeByName("CLOAK");
-
- if (um && !u->HasMode(um->name))
- // Just set +x if we can
- u->SetMode(NULL, um);
- else
- // Try to restore cloaked host
- this->SendChgHostInternal(u->nick, u->chost);
- }
-
- void SendAkill(User *u, XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
-
- /* InspIRCd may support regex bans, if they do we can send this and forget about it
- * Mask is expected in format: 'n!u@h\sr' and spaces as '\s'
- * We remove the '//' and replace '#' and any ' ' with '\s'
- */
- if (x->IsRegex() && Servers::Capab.count("RLINE"))
- {
- Anope::string mask = x->mask;
- if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
- mask = mask.substr(1, mask.length() - 2);
- size_t h = mask.find('#');
- if (h != Anope::string::npos)
- {
- mask = mask.replace(h, 1, "\\s");
- mask = mask.replace_all_cs(" ", "\\s");
- }
- SendAddLine("R", mask, timeleft, x->by, x->GetReason());
- return;
- }
- else if (x->IsRegex() || x->HasNickOrReal())
- {
- if (!u)
- {
- /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (x->manager->Check(it->second, x))
- this->SendAkill(it->second, x);
- return;
- }
-
- const XLine *old = x;
-
- if (old->manager->HasEntry("*@" + u->host))
- return;
-
- /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
- x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
- old->manager->AddXLine(x);
-
- Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
- }
-
- /* ZLine if we can instead */
- if (x->GetUser() == "*")
- {
- cidr addr(x->GetHost());
- if (addr.valid())
- {
- IRCD->SendSZLine(u, x);
- return;
- }
- }
-
- SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->by, x->GetReason());
- }
-
- void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override
- {
- UplinkSocket::Message() << "NUM " << Me->GetSID() << " " << dest << " " << numeric << " " << buf;
- }
-
- void SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) anope_override
- {
- UplinkSocket::Message(source) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
- }
-
- void SendClientIntroduction(User *u) anope_override
- {
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(Me) << "UID " << u->GetUID() << " " << u->timestamp << " " << u->nick << " " << u->host << " " << u->host << " " << u->GetIdent() << " 0.0.0.0 " << u->timestamp << " " << modes << " :" << u->realname;
-
- if (modes.find('o') != Anope::string::npos)
- {
- // Mark as introduced so we can send an oper type.
- BotInfo *bi = BotInfo::Find(u->nick, true);
- if (bi)
- bi->introduced = true;
-
- UplinkSocket::Message(u) << "OPERTYPE :service";
- }
- }
-
- void SendServer(const Server *server) anope_override
- {
- /* if rsquit is set then we are waiting on a squit */
- if (rsquit_id.empty() && rsquit_server.empty())
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetSID() << " :" << server->GetDescription();
- }
-
- void SendSquit(Server *s, const Anope::string &message) anope_override
- {
- if (s != Me)
- {
- rsquit_id = s->GetSID();
- rsquit_server = s->GetName();
- UplinkSocket::Message() << "RSQUIT " << s->GetName() << " :" << message;
- }
- else
- UplinkSocket::Message() << "SQUIT " << s->GetName() << " :" << message;
- }
-
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
- {
- UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :," << user->GetUID();
- /* Note that we can send this with the FJOIN but choose not to
- * because the mode stacker will handle this and probably will
- * merge these modes with +nrt and other mlocked modes
- */
- if (status)
- {
- /* First save the channel status incase uc->Status == status */
- ChannelStatus cs = *status;
- /* If the user is internally on the channel with flags, kill them so that
- * the stacker will allow this.
- */
- ChanUserContainer *uc = c->FindUser(user);
- if (uc != NULL)
- uc->status.Clear();
-
- BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
-
- if (uc != NULL)
- uc->status = cs;
- }
- }
-
- void SendSQLineDel(const XLine *x) anope_override
- {
- if (IRCD->CanSQLineChannel && (x->mask[0] == '#'))
- SendDelLine("CBAN", x->mask);
- else
- SendDelLine("Q", x->mask);
- }
-
- void SendSQLine(User *u, const XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
-
- if (IRCD->CanSQLineChannel && (x->mask[0] == '#'))
- SendAddLine("CBAN", x->mask, timeleft, x->by, x->GetReason());
- else
- SendAddLine("Q", x->mask, timeleft, x->by, x->GetReason());
- }
-
- void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
- {
- if (!vIdent.empty())
- this->SendChgIdentInternal(u->nick, vIdent);
- if (!vhost.empty())
- this->SendChgHostInternal(u->nick, vhost);
- }
-
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override
- {
- UplinkSocket::Message(Config->GetClient("NickServ")) << "SVSHOLD " << nick << " " << t << " :Being held for registered user";
- }
-
- void SendSVSHoldDel(const Anope::string &nick) anope_override
- {
- UplinkSocket::Message(Config->GetClient("NickServ")) << "SVSHOLD " << nick;
- }
-
- void SendSZLineDel(const XLine *x) anope_override
- {
- SendDelLine("Z", x->GetHost());
- }
-
- void SendSZLine(User *u, const XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- SendAddLine("Z", x->GetHost(), timeleft, x->by, x->GetReason());
- }
-
- void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &key) anope_override
- {
- if (key.empty())
- UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
- else
- UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan << " :" << key;
- }
-
- void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) anope_override
- {
- if (!param.empty())
- UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
- else
- UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
- }
-
- void SendSWhois(const MessageSource &bi, const Anope::string &who, const Anope::string &mask) anope_override
- {
- User *u = User::Find(who);
-
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " swhois :" << mask;
- }
-
- void SendBOB() anope_override
- {
- UplinkSocket::Message(Me) << "BURST " << Anope::CurTime;
- Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
- UplinkSocket::Message(Me) << "SINFO version :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << IRCD->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString();
- UplinkSocket::Message(Me) << "SINFO fullversion :Anope-" << Anope::Version() << " " << Me->GetName() << " :[" << Me->GetSID() << "] " << IRCD->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString();
- UplinkSocket::Message(Me) << "SINFO rawversion :Anope-" << Anope::VersionShort();
- }
-
- void SendEOB() anope_override
- {
- UplinkSocket::Message(Me) << "ENDBURST";
- }
-
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
- {
- if (Servers::Capab.count("GLOBOPS"))
- UplinkSocket::Message(source) << "SNONOTICE g :" << buf;
- else
- UplinkSocket::Message(source) << "SNONOTICE A :" << buf;
- }
-
- void SendLogin(User *u, NickAlias *na) anope_override
- {
- /* InspIRCd uses an account to bypass chmode +R, not umode +r, so we can't send this here */
- if (na->nc->HasExt("UNCONFIRMED"))
- return;
-
- IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountid :" << na->nc->GetId();
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :" << na->nc->display;
- }
-
- void SendLogout(User *u) anope_override
- {
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountid :";
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :";
- }
-
- void SendChannel(Channel *c) anope_override
- {
- UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :";
- }
-
- void SendSASLMessage(const SASL::Message &message) anope_override
- {
- UplinkSocket::Message(Me) << "ENCAP " << message.target.substr(0, 3) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
- }
-
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
- {
- // TODO: in 2.1 this function should take a NickAlias instead of strings.
- NickCore *nc = NickCore::Find(acc);
- if (!nc)
- return;
-
- UplinkSocket::Message(Me) << "METADATA " << uid << " accountid :" << nc->GetId();
- UplinkSocket::Message(Me) << "METADATA " << uid << " accountname :" << acc;
-
- if (!vident.empty())
- UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGIDENT " << uid << " " << vident;
- if (!vhost.empty())
- UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGHOST " << uid << " " << vhost;
-
- SASLUser su;
- su.uid = uid;
- su.acc = acc;
- su.created = Anope::CurTime;
-
- for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
- {
- SASLUser &u = *it;
-
- if (u.created + 30 < Anope::CurTime || u.uid == uid)
- it = saslusers.erase(it);
- else
- ++it;
- }
-
- saslusers.push_back(su);
- }
-
- bool IsExtbanValid(const Anope::string &mask) anope_override
- {
- return mask.length() >= 3 && mask[1] == ':';
- }
-
- bool IsIdentValid(const Anope::string &ident) anope_override
- {
- if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
- return false;
-
- for (unsigned i = 0; i < ident.length(); ++i)
- {
- const char &c = ident[i];
-
- if (c >= 'A' && c <= '}')
- continue;
-
- if ((c >= '0' && c <= '9') || c == '-' || c == '.')
- continue;
-
- return false;
- }
-
- return true;
- }
-};
-
-class InspIRCdAutoOpMode : public ChannelModeList
-{
- public:
- InspIRCdAutoOpMode(char mode) : ChannelModeList("AUTOOP", mode)
- {
- }
-
- bool IsValid(Anope::string &mask) const anope_override
- {
- // We can not validate this because we don't know about the
- // privileges of the setter so just reject attempts to set it.
- return false;
- }
-};
-
-// NOTE: matchers for the following extbans have not been implemented:
-//
-// * class(n): data not available
-// * country(G): data not available
-// * gateway(w): data not available in v3
-// * realmask(a): todo
-class InspIRCdExtBan : public ChannelModeVirtual<ChannelModeList>
-{
- char ext;
-
- public:
- InspIRCdExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
- , ext(extban)
- {
- }
-
- ChannelMode *Wrap(Anope::string &param) anope_override
- {
- param = Anope::string(ext) + ":" + param;
- return ChannelModeVirtual<ChannelModeList>::Wrap(param);
- }
-
- ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) anope_override
- {
- if (cm->type != MODE_LIST || param.length() < 3 || param[0] != ext || param[1] != ':')
- return cm;
-
- param = param.substr(2);
- return this;
- }
-};
-
-namespace InspIRCdExtban
-{
- class EntryMatcher : public InspIRCdExtBan
- {
- public:
- EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
-
- return Entry(this->name, real_mask).Matches(u);
- }
- };
-
- class ChannelMatcher : public InspIRCdExtBan
- {
- public:
- ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
-
- Anope::string channel = mask.substr(2);
-
- ChannelMode *cm = NULL;
- if (channel[0] != '#')
- {
- char modeChar = ModeManager::GetStatusChar(channel[0]);
- channel.erase(channel.begin());
- cm = ModeManager::FindChannelModeByChar(modeChar);
- if (cm != NULL && cm->type != MODE_STATUS)
- cm = NULL;
- }
-
- Channel *c = Channel::Find(channel);
- if (c != NULL)
- {
- ChanUserContainer *uc = c->FindUser(u);
- if (uc != NULL)
- if (cm == NULL || uc->status.HasMode(cm->mchar))
- return true;
- }
-
- return false;
- }
- };
-
- class AccountMatcher : public InspIRCdExtBan
- {
- public:
- AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
-
- return u->IsIdentified() && real_mask.equals_ci(u->Account()->display);
- }
- };
-
- class RealnameMatcher : public InspIRCdExtBan
- {
- public:
- RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return Anope::Match(u->realname, real_mask);
- }
- };
-
- class ServerMatcher : public InspIRCdExtBan
- {
- public:
- ServerMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return Anope::Match(u->server->GetName(), real_mask);
- }
- };
-
- class FingerprintMatcher : public InspIRCdExtBan
- {
- public:
- FingerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
- }
- };
-
- class UnidentifiedMatcher : public InspIRCdExtBan
- {
- public:
- UnidentifiedMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return !u->IsIdentified() && Entry("BAN", real_mask).Matches(u);
- }
- };
-
- class OperTypeMatcher : public InspIRCdExtBan
- {
- public:
- OperTypeMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- Anope::string *opertype = u->GetExt<Anope::string>("opertype");
- if (!opertype)
- return false; // Not an operator.
-
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(2);
- return Anope::Match(opertype->replace_all_cs(' ', '_'), real_mask);
- }
- };
-}
-
-class ColonDelimitedParamMode : public ChannelModeParam
-{
- public:
- ColonDelimitedParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- return IsValid(value, false);
- }
-
- bool IsValid(const Anope::string &value, bool historymode) const
- {
- if (value.empty())
- return false; // empty param is never valid
-
- Anope::string::size_type pos = value.find(':');
- if ((pos == Anope::string::npos) || (pos == 0))
- return false; // no ':' or it's the first char, both are invalid
-
- Anope::string rest;
- try
- {
- if (convertTo<int>(value, rest, false) <= 0)
- return false; // negative numbers and zero are invalid
-
- rest = rest.substr(1);
- int n;
- if (historymode)
- {
- // For the history mode, the part after the ':' is a duration and it
- // can be in the user friendly "1d3h20m" format, make sure we accept that
- n = Anope::DoTime(rest);
- }
- else
- n = convertTo<int>(rest);
-
- if (n <= 0)
- return false;
- }
- catch (const ConvertException &e)
- {
- // conversion error, invalid
- return false;
- }
-
- return true;
- }
-};
-
-class SimpleNumberParamMode : public ChannelModeParam
-{
- public:
- SimpleNumberParamMode(const Anope::string &modename, char modeChar) : ChannelModeParam(modename, modeChar, true) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- if (value.empty())
- return false; // empty param is never valid
-
- try
- {
- if (convertTo<int>(value) <= 0)
- return false;
- }
- catch (const ConvertException &e)
- {
- // conversion error, invalid
- return false;
- }
-
- return true;
- }
-};
-
-class ChannelModeFlood : public ColonDelimitedParamMode
-{
- public:
- ChannelModeFlood(char modeChar) : ColonDelimitedParamMode("FLOOD", modeChar) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- // The parameter of this mode is a bit different, it may begin with a '*',
- // ignore it if that's the case
- Anope::string v = value[0] == '*' ? value.substr(1) : value;
- return ((!value.empty()) && (ColonDelimitedParamMode::IsValid(v)));
- }
-};
-
-class ChannelModeHistory : public ColonDelimitedParamMode
-{
- public:
- ChannelModeHistory(char modeChar) : ColonDelimitedParamMode("HISTORY", modeChar) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- return (ColonDelimitedParamMode::IsValid(value, true));
- }
-};
-
-class ChannelModeRedirect : public ChannelModeParam
-{
- public:
- ChannelModeRedirect(char modeChar) : ChannelModeParam("REDIRECT", modeChar, true) { }
-
- bool IsValid(Anope::string &value) const anope_override
- {
- // The parameter of this mode is a channel, and channel names start with '#'
- return ((!value.empty()) && (value[0] == '#'));
- }
-};
-
-struct IRCDMessageAway : Message::Away
-{
- IRCDMessageAway(Module *creator) : Message::Away(creator, "AWAY") { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- std::vector<Anope::string> newparams(params);
- if (newparams.size() > 1)
- newparams.erase(newparams.begin());
-
- Message::Away::Run(source, newparams);
- }
-};
-
-struct IRCDMessageCapab : Message::Capab
-{
- struct ModeInfo
- {
- // The letter assigned to the mode (e.g. o).
- char letter;
-
- // If a prefix mode then the rank of the prefix.
- unsigned level;
-
- // The name of the mode.
- Anope::string name;
-
- // If a prefix mode then the symbol associated with the prefix.
- char symbol;
-
- // The type of mode.
- Anope::string type;
-
- ModeInfo() : letter(0), level(0), symbol(0) { }
- };
-
- static bool ParseMode(const Anope::string& token, ModeInfo& mode)
- {
- // list:ban=b param-set:limit=l param:key=k prefix:30000:op=@o simple:noextmsg=n
- // A C A C A C A B C A C
- Anope::string::size_type a = token.find(':');
- if (a == Anope::string::npos)
- return false;
-
- // If the mode is a prefix mode then it also has a rank.
- mode.type = token.substr(0, a);
- if (mode.type == "prefix")
- {
- Anope::string::size_type b = token.find(':', a + 1);
- if (b == Anope::string::npos)
- return false;
-
- const Anope::string modelevel = token.substr(a + 1, b - a - 1);
- mode.level = modelevel.is_pos_number_only() ? convertTo<unsigned>(modelevel) : 0;
- a = b;
- }
-
- Anope::string::size_type c = token.find('=', a + 1);
- if (c == Anope::string::npos)
- return false;
-
- mode.name = token.substr(a + 1, c - a - 1);
- switch (token.length() - c)
- {
- case 2:
- mode.letter = token[c + 1];
- break;
- case 3:
- mode.symbol = token[c + 1];
- mode.letter = token[c + 2];
- break;
- default:
- return false;
- }
-
- Log(LOG_DEBUG) << "Parsed mode: " << "type=" << mode.type << " name=" << mode.name << " level="
- << mode.level << " symbol=" << mode.symbol << " letter=" << mode.letter;
- return true;
- }
-
- IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params[0].equals_cs("START"))
- {
- unsigned int spanningtree_proto_ver = 0;
- if (params.size() >= 2)
- spanningtree_proto_ver = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
-
- if (spanningtree_proto_ver < 1205)
- {
- UplinkSocket::Message() << "ERROR :Protocol mismatch, no or invalid protocol version given in CAPAB START";
- Anope::QuitReason = "Protocol mismatch, no or invalid protocol version given in CAPAB START";
- Anope::Quitting = true;
- return;
- }
-
- /* reset CAPAB */
- Servers::Capab.clear();
- IRCD->CanSQLineChannel = false;
- IRCD->CanSVSHold = false;
- IRCD->DefaultPseudoclientModes = "+oI";
- }
- else if (params[0].equals_cs("CHANMODES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
-
- while (ssep.GetToken(capab))
- {
- ModeInfo mode;
- if (!ParseMode(capab, mode))
- continue;
-
- ChannelMode *cm = NULL;
- if (mode.name.equals_cs("admin"))
- cm = new ChannelModeStatus("PROTECT", mode.letter, mode.symbol, mode.level);
- else if (mode.name.equals_cs("allowinvite"))
- {
- cm = new ChannelMode("ALLINVITE", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("INVITEBAN", "BAN", 'A'));
- }
- else if (mode.name.equals_cs("auditorium"))
- cm = new ChannelMode("AUDITORIUM", mode.letter);
- else if (mode.name.equals_cs("autoop"))
- cm = new InspIRCdAutoOpMode(mode.letter);
- else if (mode.name.equals_cs("ban"))
- cm = new ChannelModeList("BAN", mode.letter);
- else if (mode.name.equals_cs("banexception"))
- cm = new ChannelModeList("EXCEPT", mode.letter);
- else if (mode.name.equals_cs("blockcaps"))
- {
- cm = new ChannelMode("BLOCKCAPS", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCAPSBAN", "BAN", 'B'));
- }
- else if (mode.name.equals_cs("blockcolor"))
- {
- cm = new ChannelMode("BLOCKCOLOR", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCOLORBAN", "BAN", 'c'));
- }
- else if (mode.name.equals_cs("c_registered"))
- cm = new ChannelModeNoone("REGISTERED", mode.letter);
- else if (mode.name.equals_cs("censor"))
- cm = new ChannelMode("CENSOR", mode.letter);
- else if (mode.name.equals_cs("delayjoin"))
- cm = new ChannelMode("DELAYEDJOIN", mode.letter);
- else if (mode.name.equals_cs("delaymsg"))
- cm = new SimpleNumberParamMode("DELAYMSG", mode.letter);
- else if (mode.name.equals_cs("filter"))
- cm = new ChannelModeList("FILTER", mode.letter);
- else if (mode.name.equals_cs("flood"))
- cm = new ChannelModeFlood(mode.letter);
- else if (mode.name.equals_cs("founder"))
- cm = new ChannelModeStatus("OWNER", mode.letter, mode.symbol, mode.level);
- else if (mode.name.equals_cs("halfop"))
- cm = new ChannelModeStatus("HALFOP", mode.letter, mode.symbol, mode.level);
- else if (mode.name.equals_cs("history"))
- cm = new ChannelModeHistory(mode.letter);
- else if (mode.name.equals_cs("invex"))
- cm = new ChannelModeList("INVITEOVERRIDE", mode.letter);
- else if (mode.name.equals_cs("inviteonly"))
- cm = new ChannelMode("INVITE", mode.letter);
- else if (mode.name.equals_cs("joinflood"))
- cm = new ColonDelimitedParamMode("JOINFLOOD", mode.letter);
- else if (mode.name.equals_cs("key"))
- cm = new ChannelModeKey(mode.letter);
- else if (mode.name.equals_cs("kicknorejoin"))
- cm = new SimpleNumberParamMode("NOREJOIN", mode.letter);
- else if (mode.name.equals_cs("limit"))
- cm = new ChannelModeParam("LIMIT", mode.letter, true);
- else if (mode.name.equals_cs("moderated"))
- cm = new ChannelMode("MODERATED", mode.letter);
- else if (mode.name.equals_cs("nickflood"))
- cm = new ColonDelimitedParamMode("NICKFLOOD", mode.letter);
- else if (mode.name.equals_cs("noctcp"))
- {
- cm = new ChannelMode("NOCTCP", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOCTCPBAN", "BAN", 'C'));
- }
- else if (mode.name.equals_cs("noextmsg"))
- cm = new ChannelMode("NOEXTERNAL", mode.letter);
- else if (mode.name.equals_cs("nokick"))
- {
- cm = new ChannelMode("NOKICK", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOKICKBAN", "BAN", 'Q'));
- }
- else if (mode.name.equals_cs("noknock"))
- cm = new ChannelMode("NOKNOCK", mode.letter);
- else if (mode.name.equals_cs("nonick"))
- {
- cm = new ChannelMode("NONICK", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONICKBAN", "BAN", 'N'));
- }
- else if (mode.name.equals_cs("nonotice"))
- {
- cm = new ChannelMode("NONOTICE", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONOTICEBAN", "BAN", 'T'));
- }
- else if (mode.name.equals_cs("official-join"))
- cm = new ChannelModeStatus("OFFICIALJOIN", mode.letter, mode.symbol, mode.level);
- else if (mode.name.equals_cs("op"))
- cm = new ChannelModeStatus("OP", mode.letter, mode.symbol, mode.level);
- else if (mode.name.equals_cs("operonly"))
- {
- cm = new ChannelModeOperOnly("OPERONLY", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::OperTypeMatcher("OPERTYPEBAN", "BAN", 'O'));
- }
- else if (mode.name.equals_cs("operprefix"))
- cm = new ChannelModeStatus("OPERPREFIX", mode.letter, mode.symbol, mode.level);
- else if (mode.name.equals_cs("permanent"))
- cm = new ChannelMode("PERM", mode.letter);
- else if (mode.name.equals_cs("private"))
- cm = new ChannelMode("PRIVATE", mode.letter);
- else if (mode.name.equals_cs("redirect"))
- cm = new ChannelModeRedirect(mode.letter);
- else if (mode.name.equals_cs("reginvite"))
- cm = new ChannelMode("REGISTEREDONLY", mode.letter);
- else if (mode.name.equals_cs("regmoderated"))
- cm = new ChannelMode("REGMODERATED", mode.letter);
- else if (mode.name.equals_cs("secret"))
- cm = new ChannelMode("SECRET", mode.letter);
- else if (mode.name.equals_cs("sslonly"))
- {
- cm = new ChannelMode("SSL", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::FingerprintMatcher("SSLBAN", "BAN", 'z'));
- }
- else if (mode.name.equals_cs("stripcolor"))
- {
- cm = new ChannelMode("STRIPCOLOR", mode.letter);
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("STRIPCOLORBAN", "BAN", 'S'));
- }
- else if (mode.name.equals_cs("topiclock"))
- cm = new ChannelMode("TOPIC", mode.letter);
- else if (mode.name.equals_cs("voice"))
- cm = new ChannelModeStatus("VOICE", mode.letter, mode.symbol, mode.level);
-
- // Handle unknown modes.
- else if (mode.type.equals_cs("list"))
- cm = new ChannelModeList(mode.name.upper(), mode.letter);
- else if (mode.type.equals_cs("param-set"))
- cm = new ChannelModeParam(mode.name.upper(), mode.letter, true);
- else if (mode.type.equals_cs("param"))
- cm = new ChannelModeParam(mode.name.upper(), mode.letter, false);
- else if (mode.type.equals_cs("prefix"))
- cm = new ChannelModeStatus(mode.name.upper(), mode.letter, mode.symbol, mode.level);
- else if (mode.type.equals_cs("simple"))
- cm = new ChannelMode(mode.name.upper(), mode.letter);
- else
- Log(LOG_DEBUG) << "Unknown channel mode: " << capab;
-
- if (cm)
- ModeManager::AddChannelMode(cm);
- }
- }
- if (params[0].equals_cs("USERMODES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
-
- while (ssep.GetToken(capab))
- {
- ModeInfo mode;
- if (!ParseMode(capab, mode))
- continue;
-
- UserMode *um = NULL;
- if (mode.name.equals_cs("bot"))
- {
- um = new UserMode("BOT", mode.letter);
- IRCD->DefaultPseudoclientModes += mode.letter;
- }
- else if (mode.name.equals_cs("callerid"))
- um = new UserMode("CALLERID", mode.letter);
- else if (mode.name.equals_cs("cloak"))
- um = new UserMode("CLOAK", mode.letter);
- else if (mode.name.equals_cs("deaf"))
- um = new UserMode("DEAF", mode.letter);
- else if (mode.name.equals_cs("deaf_commonchan"))
- um = new UserMode("COMMONCHANS", mode.letter);
- else if (mode.name.equals_cs("helpop"))
- um = new UserModeOperOnly("HELPOP", mode.letter);
- else if (mode.name.equals_cs("hidechans"))
- um = new UserMode("PRIV", mode.letter);
- else if (mode.name.equals_cs("hideoper"))
- um = new UserModeOperOnly("HIDEOPER", mode.letter);
- else if (mode.name.equals_cs("invisible"))
- um = new UserMode("INVIS", mode.letter);
- else if (mode.name.equals_cs("invis-oper"))
- um = new UserModeOperOnly("INVISIBLE_OPER", mode.letter);
- else if (mode.name.equals_cs("oper"))
- um = new UserModeOperOnly("OPER", mode.letter);
- else if (mode.name.equals_cs("regdeaf"))
- um = new UserMode("REGPRIV", mode.letter);
- else if (mode.name.equals_cs("servprotect"))
- {
- um = new UserModeNoone("PROTECTED", mode.letter);
- IRCD->DefaultPseudoclientModes += mode.letter;
- }
- else if (mode.name.equals_cs("showwhois"))
- um = new UserMode("WHOIS", mode.letter);
- else if (mode.name.equals_cs("u_censor"))
- um = new UserMode("CENSOR", mode.letter);
- else if (mode.name.equals_cs("u_registered"))
- um = new UserModeNoone("REGISTERED", mode.letter);
- else if (mode.name.equals_cs("u_stripcolor"))
- um = new UserMode("STRIPCOLOR", mode.letter);
- else if (mode.name.equals_cs("wallops"))
- um = new UserMode("WALLOPS", mode.letter);
-
- // Handle unknown modes.
- else if (mode.type.equals_cs("param-set"))
- um = new UserModeParam(mode.name.upper(), mode.letter);
- else if (mode.type.equals_cs("simple"))
- um = new UserMode(mode.name.upper(), mode.letter);
- else
- Log(LOG_DEBUG) << "Unknown user mode: " << capab;
-
- if (um)
- ModeManager::AddUserMode(um);
- }
- }
- else if (params[0].equals_cs("MODULES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string module;
-
- while (ssep.GetToken(module))
- {
- if (module.equals_cs("m_svshold.so"))
- IRCD->CanSVSHold = true;
- else if (module.find("m_rline.so") == 0)
- {
- Servers::Capab.insert("RLINE");
- const Anope::string &regexengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine");
- if (!regexengine.empty() && module.length() > 11 && regexengine != module.substr(11))
- Log() << "Warning: InspIRCd is using regex engine " << module.substr(11) << ", but we have " << regexengine << ". This may cause inconsistencies.";
- }
- else if (module.equals_cs("m_topiclock.so"))
- Servers::Capab.insert("TOPICLOCK");
- else if (module.equals_cs("m_cban.so=glob"))
- IRCD->CanSQLineChannel = true;
- }
- }
- else if (params[0].equals_cs("MODSUPPORT") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string module;
-
- while (ssep.GetToken(module))
- {
- if (module.equals_cs("m_services_account.so"))
- {
- Servers::Capab.insert("SERVICES");
- ModeManager::AddChannelMode(new InspIRCdExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'R'));
- ModeManager::AddChannelMode(new InspIRCdExtban::UnidentifiedMatcher("UNREGISTEREDBAN", "BAN", 'U'));
- }
- else if (module.equals_cs("m_chghost.so"))
- Servers::Capab.insert("CHGHOST");
- else if (module.equals_cs("m_chgident.so"))
- Servers::Capab.insert("CHGIDENT");
- else if (module == "m_channelban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::ChannelMatcher("CHANNELBAN", "BAN", 'j'));
- else if (module == "m_gecosban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
- else if (module == "m_nopartmsg.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("PARTMESSAGEBAN", "BAN", 'p'));
- else if (module == "m_serverban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::ServerMatcher("SERVERBAN", "BAN", 's'));
- else if (module == "m_muteban.so")
- ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("QUIET", "BAN", 'm'));
- }
- }
- else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
- {
- spacesepstream ssep(params[1]);
- Anope::string capab;
- while (ssep.GetToken(capab))
- {
- if (capab.find("MAXMODES=") != Anope::string::npos)
- {
- Anope::string maxmodes(capab.begin() + 9, capab.end());
- IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
- }
- else if (capab == "GLOBOPS=1")
- Servers::Capab.insert("GLOBOPS");
- }
- }
- else if (params[0].equals_cs("END"))
- {
- if (!Servers::Capab.count("SERVICES"))
- {
- UplinkSocket::Message() << "ERROR :The services_account module is not loaded. This is required by Anope";
- Anope::QuitReason = "ERROR: Remote server does not have the services_account module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!ModeManager::FindUserModeByName("PRIV"))
- {
- UplinkSocket::Message() << "ERROR :The hidechans module is not loaded. This is required by Anope";
- Anope::QuitReason = "ERROR: Remote server does not have the hidechans module loaded, and this is required.";
- Anope::Quitting = true;
- return;
- }
- if (!IRCD->CanSVSHold)
- Log() << "The remote server does not have the svshold module; fake users will be used for nick protection until the module is loaded.";
- if (!IRCD->CanSQLineChannel)
- Log() << "The remote server does not have the cban module; services will manually enforce forbidden channels until the module is loaded.";
- if (!Servers::Capab.count("CHGHOST"))
- Log() << "The remote server does not have the chghost module; vhosts are disabled until the module is loaded.";
- if (!Servers::Capab.count("CHGIDENT"))
- Log() << "The remote server does not have the chgident module; vidents are disabled until the module is loaded.";
- if (!Servers::Capab.count("GLOBOPS"))
- Log() << "The remote server does not have the globops module; oper notices will be sent as announcements until the module is loaded.";
- }
-
- Message::Capab::Run(source, params);
- }
-};
-
-struct IRCDMessageEncap : IRCDMessage
-{
- IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!Anope::Match(Me->GetSID(), params[0]) && !Anope::Match(Me->GetName(), params[0]))
- return;
-
- if (params[1] == "CHGIDENT")
- {
- User *u = User::Find(params[2]);
- if (!u || u->server != Me)
- return;
-
- u->SetIdent(params[3]);
- UplinkSocket::Message(u) << "FIDENT :" << params[3];
- }
- else if (params[1] == "CHGHOST")
- {
- User *u = User::Find(params[2]);
- if (!u || u->server != Me)
- return;
-
- u->SetDisplayedHost(params[3]);
- UplinkSocket::Message(u) << "FHOST :" << params[3];
- }
- else if (params[1] == "CHGNAME")
- {
- User *u = User::Find(params[2]);
- if (!u || u->server != Me)
- return;
-
- u->SetRealname(params[3]);
- UplinkSocket::Message(u) << "FNAME :" << params[3];
- }
- else if (SASL::sasl && params[1] == "SASL" && params.size() >= 6)
- {
- SASL::Message m;
- m.source = params[2];
- m.target = params[3];
- m.type = params[4];
- m.data = params[5];
- m.ext = params.size() > 6 ? params[6] : "";
-
- SASL::sasl->ProcessMessage(m);
- }
- }
-};
-
-struct IRCDMessageFHost : IRCDMessage
-{
- IRCDMessageFHost(Module *creator) : IRCDMessage(creator, "FHOST", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = source.GetUser();
- if (u->HasMode("CLOAK"))
- u->RemoveModeInternal(source, ModeManager::FindUserModeByName("CLOAK"));
- u->SetDisplayedHost(params[0]);
- }
-};
-
-struct IRCDMessageFIdent : IRCDMessage
-{
- IRCDMessageFIdent(Module *creator) : IRCDMessage(creator, "FIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->SetIdent(params[0]);
- }
-};
-
-struct IRCDMessageKick : IRCDMessage
-{
- IRCDMessageKick(Module *creator) : IRCDMessage(creator, "KICK", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- // Received: :715AAAAAA KICK #chan 715AAAAAD :reason
- // Received: :715AAAAAA KICK #chan 628AAAAAA 4 :reason
- Channel *c = Channel::Find(params[0]);
- if (!c)
- return;
-
- const Anope::string &reason = params.size() > 3 ? params[3] : params[2];
- c->KickInternal(source, params[1], reason);
- }
-};
-
-struct IRCDMessageSave : IRCDMessage
-{
- time_t last_collide;
-
- IRCDMessageSave(Module *creator) : IRCDMessage(creator, "SAVE", 2), last_collide(0) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *targ = User::Find(params[0]);
- time_t ts;
-
- try
- {
- ts = convertTo<time_t>(params[1]);
- }
- catch (const ConvertException &)
- {
- return;
- }
-
- if (!targ || targ->timestamp != ts)
- return;
-
- BotInfo *bi;
- if (targ->server == Me && (bi = dynamic_cast<BotInfo *>(targ)))
- {
- if (last_collide == Anope::CurTime)
- {
- Anope::QuitReason = "Nick collision fight on " + targ->nick;
- Anope::Quitting = true;
- return;
- }
-
- IRCD->SendKill(Me, targ->nick, "Nick collision");
- IRCD->SendNickChange(targ, targ->nick);
- last_collide = Anope::CurTime;
- }
- else
- targ->ChangeNick(targ->GetUID());
- }
-};
-
-class IRCDMessageMetadata : IRCDMessage
-{
- const bool &do_topiclock;
- const bool &do_mlock;
- PrimitiveExtensibleItem<ListLimits> &maxlist;
-
- public:
- IRCDMessageMetadata(Module *creator, const bool &handle_topiclock, const bool &handle_mlock, PrimitiveExtensibleItem<ListLimits> &listlimits) : IRCDMessage(creator, "METADATA", 3), do_topiclock(handle_topiclock), do_mlock(handle_mlock), maxlist(listlimits) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- // We deliberately ignore non-bursting servers to avoid pseudoserver fights
- // Channel METADATA has an additional parameter: the channel TS
- // Received: :715 METADATA #chan 1572026333 mlock :nt
- if ((params[0][0] == '#') && (params.size() > 3) && (!source.GetServer()->IsSynced()))
- {
- Channel *c = Channel::Find(params[0]);
- if (c)
- {
- if ((c->ci) && (do_mlock) && (params[2] == "mlock"))
- {
- ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
- Anope::string modes;
- if (modelocks)
- modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
-
- // Mode lock string is not what we say it is?
- if (modes != params[3])
- UplinkSocket::Message(Me) << "METADATA " << c->name << " " << c->creation_time << " mlock :" << modes;
- }
- else if ((c->ci) && (do_topiclock) && (params[2] == "topiclock"))
- {
- bool mystate = c->ci->HasExt("TOPICLOCK");
- bool serverstate = (params[3] == "1");
- if (mystate != serverstate)
- UplinkSocket::Message(Me) << "METADATA " << c->name << " " << c->creation_time << " topiclock :" << (mystate ? "1" : "");
- }
- else if (params[2] == "maxlist")
- {
- ListLimits limits;
- spacesepstream limitstream(params[3]);
- Anope::string modechr, modelimit;
- while (limitstream.GetToken(modechr) && limitstream.GetToken(modelimit))
- {
- limits.insert(std::make_pair(modechr[0], convertTo<unsigned>(modelimit)));
- }
- maxlist.Set(c, limits);
- }
- }
- }
- else if (isdigit(params[0][0]))
- {
- if (params[1].equals_cs("accountname"))
- {
- User *u = User::Find(params[0]);
- NickCore *nc = NickCore::Find(params[2]);
- if (u && nc)
- u->Login(nc);
- }
-
- /*
- * possible incoming ssl_cert messages:
- * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...>
- * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0)
- */
- else if (params[1].equals_cs("ssl_cert"))
- {
- User *u = User::Find(params[0]);
- if (!u)
- return;
- u->Extend<bool>("ssl");
- Anope::string data = params[2].c_str();
- size_t pos1 = data.find(' ') + 1;
- size_t pos2 = data.find(' ', pos1);
- if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes.
- {
- u->fingerprint = data.substr(pos1, pos2 - pos1);
- }
- FOREACH_MOD(OnFingerprint, (u));
- }
- }
- else if (params[0] == "*")
- {
- // Wed Oct 3 15:40:27 2012: S[14] O :20D METADATA * modules :-m_svstopic.so
-
- if (params[1].equals_cs("modules") && !params[2].empty())
- {
- // only interested when it comes from our uplink
- Server* server = source.GetServer();
- if (!server || server->GetUplink() != Me)
- return;
-
- bool plus = (params[2][0] == '+');
- if (!plus && params[2][0] != '-')
- return;
-
- bool required = false;
- Anope::string capab, module = params[2].substr(1);
-
- if (module.equals_cs("m_services_account.so"))
- required = true;
- else if (module.equals_cs("m_hidechans.so"))
- required = true;
- else if (module.equals_cs("m_cban.so=glob") && plus)
- IRCD->CanSQLineChannel = true;
- if (module.equals_cs("m_cban.so") && !plus)
- IRCD->CanSQLineChannel = false;
- else if (module.equals_cs("m_chghost.so"))
- capab = "CHGHOST";
- else if (module.equals_cs("m_chgident.so"))
- capab = "CHGIDENT";
- else if (module.equals_cs("m_svshold.so"))
- IRCD->CanSVSHold = plus;
- else if (module.equals_cs("m_rline.so"))
- capab = "RLINE";
- else if (module.equals_cs("m_topiclock.so"))
- capab = "TOPICLOCK";
- else
- return;
-
- if (required)
- {
- if (!plus)
- Log() << "Warning: InspIRCd unloaded module " << module << ", Anope won't function correctly without it";
- }
- else
- {
- if (plus && !capab.empty())
- Servers::Capab.insert(capab);
- else if (!capab.empty())
- Servers::Capab.erase(capab);
-
- Log() << "InspIRCd " << (plus ? "loaded" : "unloaded") << " module " << module << ", adjusted functionality";
- }
-
- }
- }
- }
-};
-
-struct IRCDMessageEndburst : IRCDMessage
-{
- IRCDMessageEndburst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Server *s = source.GetServer();
-
- Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName();
-
- s->Sync(true);
- }
-};
-
-struct IRCDMessageFJoin : IRCDMessage
-{
- IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Anope::string modes;
- if (params.size() >= 3)
- {
- for (unsigned i = 2; i < params.size() - 1; ++i)
- modes += " " + params[i];
- if (!modes.empty())
- modes.erase(modes.begin());
- }
-
- std::list<Message::Join::SJoinUser> users;
-
- spacesepstream sep(params[params.size() - 1]);
- Anope::string buf;
- while (sep.GetToken(buf))
- {
- Message::Join::SJoinUser sju;
-
- /* Loop through prefixes and find modes for them */
- for (char c; (c = buf[0]) != ',' && c;)
- {
- buf.erase(buf.begin());
- sju.first.AddMode(c);
- }
- /* Erase the , */
- if (!buf.empty())
- buf.erase(buf.begin());
-
- /* Erase the :membid */
- if (!buf.empty())
- {
- Anope::string::size_type membid = buf.find(':');
- if (membid != Anope::string::npos)
- buf.erase(membid, Anope::string::npos);
- }
-
- sju.second = User::Find(buf);
- if (!sju.second)
- {
- Log(LOG_DEBUG) << "FJOIN for nonexistent user " << buf << " on " << params[0];
- continue;
- }
-
- users.push_back(sju);
- }
-
- time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
- Message::Join::SJoin(source, params[0], ts, modes, users);
- }
-};
-
-struct IRCDMessageFMode : IRCDMessage
-{
- IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- /* :source FMODE #test 12345678 +nto foo */
-
- Anope::string modes = params[2];
- for (unsigned n = 3; n < params.size(); ++n)
- modes += " " + params[n];
-
- Channel *c = Channel::Find(params[0]);
- time_t ts;
-
- try
- {
- ts = convertTo<time_t>(params[1]);
- }
- catch (const ConvertException &)
- {
- ts = 0;
- }
-
- if (c)
- c->SetModesInternal(source, modes, ts);
- }
-};
-
-struct IRCDMessageFTopic : IRCDMessage
-{
- IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- // :source FTOPIC channel ts topicts :topic
- // :source FTOPIC channel ts topicts setby :topic (burst or RESYNC)
-
- const Anope::string &setby = params.size() > 4 ? params[3] : source.GetName();
- const Anope::string &topic = params.size() > 4 ? params[4] : params[3];
-
- Channel *c = Channel::Find(params[0]);
- if (c)
- c->ChangeTopicInternal(NULL, setby, topic, params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime);
- }
-};
-
-struct IRCDMessageIdle : IRCDMessage
-{
- IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- BotInfo *bi = BotInfo::Find(params[0]);
- if (bi)
- UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " " << (Anope::CurTime - bi->lastmsg);
- else
- {
- User *u = User::Find(params[0]);
- if (u && u->server == Me)
- UplinkSocket::Message(u) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " 0";
- }
- }
-};
-
-struct IRCDMessageIJoin : IRCDMessage
-{
- IRCDMessageIJoin(Module *creator) : IRCDMessage(creator, "IJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- // :<uid> IJOIN <chan> <membid> [<ts> [<flags>]]
- Channel *c = Channel::Find(params[0]);
- if (!c)
- {
- // When receiving an IJOIN, first check if the target channel exists. If it does not exist,
- // ignore the join (that is, do not create the channel) and send a RESYNC back to the source.
- UplinkSocket::Message(Me) << "RESYNC :" << params[0];
- return;
- }
-
- // If the channel does exist then join the user, and in case any prefix modes were sent (found in
- // the 3rd parameter), compare the TS of the channel to the TS in the IJOIN (2nd parameter). If
- // the timestamps match, set the modes on the user, otherwise ignore the modes.
- Message::Join::SJoinUser user;
- user.second = source.GetUser();
-
- time_t chants = Anope::CurTime;
- if (params.size() >= 4)
- {
- chants = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0;
- for (unsigned i = 0; i < params[3].length(); ++i)
- user.first.AddMode(params[3][i]);
- }
-
- std::list<Message::Join::SJoinUser> users;
- users.push_back(user);
- Message::Join::SJoin(source, params[0], chants, "", users);
- }
-};
-
-struct IRCDMessageMode : IRCDMessage
-{
- IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (IRCD->IsChannelValid(params[0]))
- {
- Channel *c = Channel::Find(params[0]);
-
- Anope::string modes = params[1];
- for (unsigned n = 2; n < params.size(); ++n)
- modes += " " + params[n];
-
- if (c)
- c->SetModesInternal(source, modes);
- }
- else
- {
- /* InspIRCd lets opers change another
- users modes, we have to kludge this
- as it slightly breaks RFC1459
- */
- User *u = User::Find(params[0]);
- if (u)
- u->SetModesInternal(source, "%s", params[1].c_str());
- }
- }
-};
-
-struct IRCDMessageNick : IRCDMessage
-{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->ChangeNick(params[0]);
- }
-};
-
-struct IRCDMessageOperType : IRCDMessage
-{
- PrimitiveExtensibleItem<Anope::string> opertype;
-
- IRCDMessageOperType(Module *creator) : IRCDMessage(creator, "OPERTYPE", 1), opertype(creator, "opertype") { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- /* opertype is equivalent to mode +o because servers
- don't do this directly */
- User *u = source.GetUser();
- if (!u->HasMode("OPER"))
- u->SetModesInternal(source, "+o");
-
- opertype.Set(u, params[0]);
- }
-};
-
-struct IRCDMessagePing : IRCDMessage
-{
- IRCDMessagePing(Module *creator) : IRCDMessage(creator, "PING", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params[0] == Me->GetSID())
- IRCD->SendPong(params[0], source.GetServer()->GetSID());
- }
-};
-
-struct IRCDMessageRSQuit : IRCDMessage
-{
- IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Server *s = Server::Find(params[0]);
- const Anope::string &reason = params.size() > 1 ? params[1] : "";
- if (!s)
- return;
-
- UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << reason;
- s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
- }
-};
-
-struct IRCDMessageServer : IRCDMessage
-{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!source.GetServer() && params.size() == 5)
- {
- /*
- * SERVER testnet.inspircd.org hunter7 0 123 :InspIRCd Test Network
- * 0: name
- * 1: pass
- * 2: hops
- * 3: numeric
- * 4: desc
- */
- unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0;
- new Server(Me, params[0], hops, params[4], params[3]);
- }
- else if (source.GetServer())
- {
- /*
- * SERVER testnet.inspircd.org 123 burst=1234 hidden=0 :InspIRCd Test Network
- * 0: name
- * 1: numeric
- * 2 to N-1: various key=value pairs.
- * N: desc
- */
- new Server(source.GetServer(), params[0], 1, params.back(), params[1]);
- }
- }
-};
-
-struct IRCDMessageSQuit : Message::SQuit
-{
- IRCDMessageSQuit(Module *creator) : Message::SQuit(creator) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params[0] == rsquit_id || params[0] == rsquit_server)
- {
- /* squit for a recently squit server, introduce the juped server now */
- Server *s = Server::Find(rsquit_server);
-
- rsquit_id.clear();
- rsquit_server.clear();
-
- if (s && s->IsJuped())
- IRCD->SendServer(s);
- }
- else
- Message::SQuit::Run(source, params);
- }
-};
-
-struct IRCDMessageUID : IRCDMessage
-{
- IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- /*
- * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org>
- * 0: uid
- * 1: ts
- * 2: nick
- * 3: host
- * 4: dhost
- * 5: ident
- * 6: ip
- * 7: signon
- * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname!
- * last: realname
- */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- time_t ts = convertTo<time_t>(params[1]);
-
- Anope::string modes = params[8];
- for (unsigned i = 9; i < params.size() - 1; ++i)
- modes += " " + params[i];
-
- NickAlias *na = NULL;
- if (SASL::sasl)
- for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();)
- {
- SASLUser &u = *it;
-
- if (u.created + 30 < Anope::CurTime)
- it = saslusers.erase(it);
- else if (u.uid == params[0])
- {
- na = NickAlias::Find(u.acc);
- it = saslusers.erase(it);
- }
- else
- ++it;
- }
-
- User *u = User::OnIntroduce(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0], na ? *na->nc : NULL);
- if (u)
- u->signon = convertTo<time_t>(params[7]);
- }
-};
-
-class ProtoInspIRCd3 : public Module
-{
- InspIRCd3Proto ircd_proto;
- ExtensibleItem<bool> ssl;
-
- /* Core message handlers */
- Message::Error message_error;
- Message::Invite message_invite;
- Message::Kill message_kill;
- Message::MOTD message_motd;
- Message::Notice message_notice;
- Message::Part message_part;
- Message::Privmsg message_privmsg;
- Message::Quit message_quit;
- Message::Stats message_stats;
- Message::Time message_time;
-
- /* Our message handlers */
- IRCDMessageAway message_away;
- IRCDMessageCapab message_capab;
- IRCDMessageEncap message_encap;
- IRCDMessageEndburst message_endburst;
- IRCDMessageFHost message_fhost;
- IRCDMessageFIdent message_fident;
- IRCDMessageFJoin message_fjoin;
- IRCDMessageFMode message_fmode;
- IRCDMessageFTopic message_ftopic;
- IRCDMessageIdle message_idle;
- IRCDMessageIJoin message_ijoin;
- IRCDMessageKick message_kick;
- IRCDMessageMetadata message_metadata;
- IRCDMessageMode message_mode;
- IRCDMessageNick message_nick;
- IRCDMessageOperType message_opertype;
- IRCDMessagePing message_ping;
- IRCDMessageRSQuit message_rsquit;
- IRCDMessageSave message_save;
- IRCDMessageServer message_server;
- IRCDMessageSQuit message_squit;
- IRCDMessageUID message_uid;
-
- bool use_server_side_topiclock, use_server_side_mlock;
-
- void SendChannelMetadata(Channel *c, const Anope::string &metadataname, const Anope::string &value)
- {
- UplinkSocket::Message(Me) << "METADATA " << c->name << " " << c->creation_time << " " << metadataname << " :" << value;
- }
-
- public:
- ProtoInspIRCd3(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
- ircd_proto(this), ssl(this, "ssl"),
- message_error(this), message_invite(this), message_kill(this), message_motd(this), message_notice(this),
- message_part(this), message_privmsg(this), message_quit(this), message_stats(this), message_time(this),
- message_away(this), message_capab(this), message_encap(this), message_endburst(this), message_fhost(this),
- message_fident(this), message_fjoin(this), message_fmode(this), message_ftopic(this), message_idle(this),
- message_ijoin(this), message_kick(this), message_metadata(this, use_server_side_topiclock, use_server_side_mlock, ircd_proto.maxlist),
- message_mode(this), message_nick(this), message_opertype(this), message_ping(this), message_rsquit(this),
- message_save(this), message_server(this), message_squit(this), message_uid(this)
- {
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- use_server_side_topiclock = conf->GetModule(this)->Get<bool>("use_server_side_topiclock");
- use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- }
-
- void OnUserNickChange(User *u, const Anope::string &) anope_override
- {
- u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
- }
-
- void OnChannelSync(Channel *c) anope_override
- {
- if (c->ci)
- this->OnChanRegistered(c->ci);
- }
-
- void OnChanRegistered(ChannelInfo *ci) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- if (use_server_side_mlock && ci->c && modelocks && !modelocks->GetMLockAsString(false).empty())
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- SendChannelMetadata(ci->c, "mlock", modes);
- }
-
- if (use_server_side_topiclock && Servers::Capab.count("TOPICLOCK") && ci->c)
- {
- if (ci->HasExt("TOPICLOCK"))
- SendChannelMetadata(ci->c, "topiclock", "1");
- }
- }
-
- void OnDelChan(ChannelInfo *ci) anope_override
- {
- if (use_server_side_mlock && ci->c)
- SendChannelMetadata(ci->c, "mlock", "");
-
- if (use_server_side_topiclock && Servers::Capab.count("TOPICLOCK") && ci->c)
- SendChannelMetadata(ci->c, "topiclock", "");
- }
-
- EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
- SendChannelMetadata(ci->c, "mlock", modes);
- }
-
- return EVENT_CONTINUE;
- }
-
- EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
- SendChannelMetadata(ci->c, "mlock", modes);
- }
-
- return EVENT_CONTINUE;
- }
-
- EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) anope_override
- {
- if (cmd->name == "chanserv/topic" && ci->c)
- {
- if (setting == "topiclock on")
- SendChannelMetadata(ci->c, "topiclock", "1");
- else if (setting == "topiclock off")
- SendChannelMetadata(ci->c, "topiclock", "0");
- }
-
- return EVENT_CONTINUE;
- }
-};
-
-MODULE_INIT(ProtoInspIRCd3)
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
index 9c5dd4cb9..cf97ee5ae 100644
--- a/modules/protocol/ngircd.cpp
+++ b/modules/protocol/ngircd.cpp
@@ -10,16 +10,18 @@
*/
#include "module.h"
+#include "numeric.h"
-class ngIRCdProto : public IRCDProto
+class ngIRCdProto final
+ : public IRCDProto
{
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override
+ void SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) override
{
- IRCDProto::SendSVSKillInternal(source, user, buf);
+ IRCDProto::SendSVSKill(source, user, buf);
user->KillInternal(source, buf);
}
- public:
+public:
ngIRCdProto(Module *creator) : IRCDProto(creator, "ngIRCd")
{
DefaultPseudoclientModes = "+oi";
@@ -30,64 +32,63 @@ class ngIRCdProto : public IRCDProto
MaxModes = 5;
}
- void SendAkill(User *u, XLine *x) anope_override
+ void SendAkill(User *u, XLine *x) override
{
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- UplinkSocket::Message(Me) << "GLINE " << x->mask << " " << timeleft << " :" << x->GetReason() << " (" << x->by << ")";
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+ Uplink::Send("GLINE", x->mask, timeleft, x->GetReason() + " (" + x->by + ")");
}
- void SendAkillDel(const XLine *x) anope_override
+ void SendAkillDel(const XLine *x) override
{
- UplinkSocket::Message(Me) << "GLINE " << x->mask;
+ Uplink::Send("GLINE", x->mask);
}
- void SendChannel(Channel *c) anope_override
+ void SendChannel(Channel *c) override
{
- UplinkSocket::Message(Me) << "CHANINFO " << c->name << " +" << c->GetModes(true, true);
+ Uplink::Send("CHANINFO", c->name, "+" + c->GetModes(true, true));
}
// Received: :dev.anope.de NICK DukeP 1 ~DukePyro p57ABF9C9.dip.t-dialin.net 1 +i :DukePyrolator
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(Me) << "NICK " << u->nick << " 1 " << u->GetIdent() << " " << u->host << " 1 " << modes << " :" << u->realname;
+ Uplink::Send("NICK", u->nick, 1, u->GetIdent(), u->host, 1, "+" + u->GetModes(), u->realname);
}
- void SendConnect() anope_override
+ void SendConnect() override
{
- UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " 0210-IRC+ Anope|" << Anope::VersionShort() << ":CLHMSo P";
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "0210-IRC+", "Anope|" + Anope::VersionShort() + ":CLHMSo P");
+
/* Make myself known to myself in the serverlist */
SendServer(Me);
+
/* finish the enhanced server handshake and register the connection */
- this->SendNumeric(376, "*", ":End of MOTD command");
+ this->SendNumeric(RPL_ENDOFMOTD, "*", "End of MOTD command");
}
- void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override
+ void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) override
{
- UplinkSocket::Message(Me) << "SVSNICK " << u->nick << " " << newnick;
+ Uplink::Send("SVSNICK", u->nick, newnick);
}
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "NOTICE", "$" + dest->GetName(), msg);
}
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg);
}
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
+ void SendGlobops(const MessageSource &source, const Anope::string &buf) override
{
- UplinkSocket::Message(source) << "WALLOPS :" << buf;
+ Uplink::Send(source, "WALLOPS", buf);
}
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override
{
- UplinkSocket::Message(user) << "JOIN " << c->name;
+ Uplink::Send(user, "JOIN", c->name);
if (status)
{
/* First save the channel status incase uc->Status == status */
@@ -100,36 +101,36 @@ class ngIRCdProto : public IRCDProto
uc->status.Clear();
BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
+ for (auto mode : cs.Modes())
+ c->SetMode(setter, ModeManager::FindChannelModeByChar(mode), user->GetUID(), false);
if (uc != NULL)
uc->status = cs;
}
}
- void SendLogin(User *u, NickAlias *na) anope_override
+ void SendLogin(User *u, NickAlias *na) override
{
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :" << na->nc->display;
+ Uplink::Send("METADATA", u->GetUID(), "accountname", na->nc->display);
}
- void SendLogout(User *u) anope_override
+ void SendLogout(User *u) override
{
- UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :";
+ Uplink::Send("METADATA", u->GetUID(), "accountname", "");
}
/* SERVER name hop descript */
- void SendServer(const Server *server) anope_override
+ void SendServer(const Server *server) override
{
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription();
+ Uplink::Send("SERVER", server->GetName(), server->GetHops(), server->GetDescription());
}
- void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
+ void SendVHost(User *u, const Anope::string &vident, const Anope::string &vhost) override
{
- if (!vIdent.empty())
- UplinkSocket::Message(Me) << "METADATA " << u->nick << " user :" << vIdent;
+ if (!vident.empty())
+ Uplink::Send("METADATA", u->nick, "user", vident);
- UplinkSocket::Message(Me) << "METADATA " << u->nick << " cloakhost :" << vhost;
+ Uplink::Send("METADATA", u->nick, "cloakhost", vhost);
if (!u->HasMode("CLOAK"))
{
u->SetMode(Config->GetClient("HostServ"), "CLOAK");
@@ -137,52 +138,49 @@ class ngIRCdProto : public IRCDProto
}
}
- void SendVhostDel(User *u) anope_override
+ void SendVHostDel(User *u) override
{
- this->SendVhost(u, u->GetIdent(), "");
+ this->SendVHost(u, u->GetIdent(), "");
}
- Anope::string Format(const Anope::string &source, const Anope::string &message) anope_override
+ bool Format(Anope::string &message, const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params) override
{
- return IRCDProto::Format(source.empty() ? Me->GetSID() : source, message);
+ return IRCDProto::Format(message, tags, source.GetSource().empty() ? Me : source, command, params);
}
};
-struct IRCDMessage005 : IRCDMessage
+struct IRCDMessage005 final
+ : IRCDMessage
{
- IRCDMessage005(Module *creator) : IRCDMessage(creator, "005", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessage005(Module *creator) : IRCDMessage(creator, "005", 1) { SetFlag(FLAG_SOFT_LIMIT); }
// Please see <http://www.irc.org/tech_docs/005.html> for details.
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
size_t pos;
Anope::string parameter, data;
- for (unsigned i = 0, end = params.size(); i < end; ++i)
+ for (const auto &param : params)
{
- pos = params[i].find('=');
+ pos = param.find('=');
if (pos != Anope::string::npos)
{
- parameter = params[i].substr(0, pos);
- data = params[i].substr(pos+1, params[i].length());
+ parameter = param.substr(0, pos);
+ data = param.substr(pos+1, param.length());
if (parameter == "MODES")
{
- unsigned maxmodes = convertTo<unsigned>(data);
- IRCD->MaxModes = maxmodes;
+ IRCD->MaxModes = Anope::Convert<unsigned>(data, IRCD->MaxModes);
}
else if (parameter == "NICKLEN")
{
- unsigned newlen = convertTo<unsigned>(data), len = Config->GetBlock("networkinfo")->Get<unsigned>("nicklen");
- if (len != newlen)
- {
- Log() << "Warning: NICKLEN is " << newlen << " but networkinfo:nicklen is " << len;
- }
+ IRCD->MaxNick = Anope::Convert<size_t>(data, IRCD->MaxNick);
}
}
}
}
};
-struct IRCDMessage376 : IRCDMessage
+struct IRCDMessage376 final
+ : IRCDMessage
{
IRCDMessage376(Module *creator) : IRCDMessage(creator, "376", 2) { }
@@ -194,14 +192,15 @@ struct IRCDMessage376 : IRCDMessage
*
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
}
};
-struct IRCDMessageChaninfo : IRCDMessage
+struct IRCDMessageChaninfo final
+ : IRCDMessage
{
- IRCDMessageChaninfo(Module *creator) : IRCDMessage(creator, "CHANINFO", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageChaninfo(Module *creator) : IRCDMessage(creator, "CHANINFO", 2) { SetFlag(FLAG_SOFT_LIMIT); SetFlag(FLAG_REQUIRE_SERVER); }
/*
* CHANINFO is used by servers to inform each other about a channel: its
@@ -220,12 +219,12 @@ struct IRCDMessageChaninfo : IRCDMessage
* a channel has no user limit (the parameter <modes> doesn't list the "l"
* channel mode). In this case <limit> should be "0".
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
bool created;
Channel *c = Channel::FindOrCreate(params[0], created);
- Anope::string modes = params[1];
+ std::vector<Anope::string> modeparams;
if (params.size() == 3)
{
@@ -238,23 +237,24 @@ struct IRCDMessageChaninfo : IRCDMessage
switch(params[1][i])
{
case 'k':
- modes += " " + params[2];
+ modeparams.push_back(params[2]);
continue;
case 'l':
- modes += " " + params[3];
+ modeparams.push_back(params[3]);
continue;
}
}
c->ChangeTopicInternal(NULL, source.GetName(), params[4], Anope::CurTime);
}
- c->SetModesInternal(source, modes);
+ c->SetModesInternal(source, params[1], modeparams);
}
};
-struct IRCDMessageJoin : Message::Join
+struct IRCDMessageJoin final
+ : Message::Join
{
- IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { SetFlag(FLAG_REQUIRE_USER); }
/*
* <@po||ux> DukeP: RFC 2813, 4.2.1: the JOIN command on server-server links
@@ -262,16 +262,18 @@ struct IRCDMessageJoin : Message::Join
*
* if a user joins a new channel, the ircd sends <channelname>\7<umode>
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *user = source.GetUser();
size_t pos = params[0].find('\7');
Anope::string channel, modes;
+ std::vector<Anope::string> modeparams;
if (pos != Anope::string::npos)
{
channel = params[0].substr(0, pos);
- modes = '+' + params[0].substr(pos+1, params[0].length()) + " " + user->nick;
+ modes = '+' + params[0].substr(pos+1, params[0].length());
+ modeparams.push_back(user->nick);
}
else
{
@@ -281,20 +283,21 @@ struct IRCDMessageJoin : Message::Join
std::vector<Anope::string> new_params;
new_params.push_back(channel);
- Message::Join::Run(source, new_params);
+ Message::Join::Run(source, new_params, tags);
if (!modes.empty())
{
Channel *c = Channel::Find(channel);
if (c)
- c->SetModesInternal(source, modes);
+ c->SetModesInternal(source, modes, modeparams);
}
}
};
-struct IRCDMessageMetadata : IRCDMessage
+struct IRCDMessageMetadata final
+ : IRCDMessage
{
- IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
/*
* Received: :ngircd.dev.anope.de METADATA DukePyrolator host :anope-e2ee5c7d
@@ -312,7 +315,7 @@ struct IRCDMessageMetadata : IRCDMessage
* - "user": the user name (ident) of a client (can't be empty)
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = User::Find(params[0]);
if (!u)
@@ -351,9 +354,10 @@ struct IRCDMessageMetadata : IRCDMessage
}
};
-struct IRCDMessageMode : IRCDMessage
+struct IRCDMessageMode final
+ : IRCDMessage
{
- IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(FLAG_SOFT_LIMIT); }
/*
* Received: :DukeP MODE #anope +b *!*@*.aol.com
@@ -363,33 +367,29 @@ struct IRCDMessageMode : IRCDMessage
* params[n] = parameters
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- Anope::string modes = params[1];
-
- for (size_t i = 2; i < params.size(); ++i)
- modes += " " + params[i];
-
if (IRCD->IsChannelValid(params[0]))
{
Channel *c = Channel::Find(params[0]);
if (c)
- c->SetModesInternal(source, modes);
+ c->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
}
else
{
User *u = User::Find(params[0]);
if (u)
- u->SetModesInternal(source, "%s", params[1].c_str());
+ u->SetModesInternal(source, params[1]);
}
}
};
-struct IRCDMessageNick : IRCDMessage
+struct IRCDMessageNick final
+ : IRCDMessage
{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 1) { SetFlag(FLAG_SOFT_LIMIT); }
/*
* NICK - NEW
@@ -410,7 +410,7 @@ struct IRCDMessageNick : IRCDMessage
* params[0] = newnick
*
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() == 1)
{
@@ -439,9 +439,10 @@ struct IRCDMessageNick : IRCDMessage
}
};
-struct IRCDMessageNJoin : IRCDMessage
+struct IRCDMessageNJoin final
+ : IRCDMessage
{
- IRCDMessageNJoin(Module *creator) : IRCDMessage(creator, "NJOIN",2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); };
+ IRCDMessageNJoin(Module *creator) : IRCDMessage(creator, "NJOIN",2) { SetFlag(FLAG_REQUIRE_SERVER); };
/*
* RFC 2813, 4.2.2: Njoin Message:
@@ -454,7 +455,7 @@ struct IRCDMessageNJoin : IRCDMessage
*
* Received: :dev.anope.de NJOIN #test :DukeP2,@DukeP,%test,+test2
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
std::list<Message::Join::SJoinUser> users;
@@ -481,29 +482,31 @@ struct IRCDMessageNJoin : IRCDMessage
users.push_back(sju);
}
- Message::Join::SJoin(source, params[0], 0, "", users);
+ Message::Join::SJoin(source, params[0], 0, "", {}, users);
}
};
-struct IRCDMessagePong : IRCDMessage
+struct IRCDMessagePong final
+ : IRCDMessage
{
- IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(FLAG_SOFT_LIMIT); SetFlag(FLAG_REQUIRE_SERVER); }
/*
* ngIRCd does not send an EOB, so we send a PING immediately
* when receiving a new server and then finish sync once we
* get a pong back from that server.
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (!source.GetServer()->IsSynced())
source.GetServer()->Sync(false);
}
};
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_SOFT_LIMIT); }
/*
* New directly linked server:
@@ -530,7 +533,7 @@ struct IRCDMessageServer : IRCDMessage
* params[3] = server description
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() == 3)
{
@@ -540,7 +543,7 @@ struct IRCDMessageServer : IRCDMessage
else
{
// our uplink is introducing a new server
- unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
+ auto hops = Anope::Convert<unsigned>(params[1], 0);
new Server(source.GetServer(), params[0], hops, params[3], params[2]);
}
/*
@@ -552,12 +555,13 @@ struct IRCDMessageServer : IRCDMessage
}
};
-struct IRCDMessageTopic : IRCDMessage
+struct IRCDMessageTopic final
+ : IRCDMessage
{
- IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 2) { SetFlag(FLAG_SOFT_LIMIT); }
// Received: :DukeP TOPIC #anope :test
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Channel *c = Channel::Find(params[0]);
if (!c)
@@ -571,7 +575,8 @@ struct IRCDMessageTopic : IRCDMessage
-class ProtongIRCd : public Module
+class ProtongIRCd final
+ : public Module
{
ngIRCdProto ircd_proto;
@@ -606,7 +611,7 @@ class ProtongIRCd : public Module
IRCDMessageServer message_server;
IRCDMessageTopic message_topic;
- void AddModes()
+ static void AddModes()
{
/* Add user modes */
ModeManager::AddUserMode(new UserMode("NOCTCP", 'b'));
@@ -651,7 +656,7 @@ class ProtongIRCd : public Module
ModeManager::AddChannelMode(new ChannelMode("SSL", 'z'));
}
- public:
+public:
ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_capab(this), message_error(this), message_invite(this), message_kick(this), message_kill(this),
@@ -670,7 +675,7 @@ class ProtongIRCd : public Module
}
- void OnUserNickChange(User *u, const Anope::string &) anope_override
+ void OnUserNickChange(User *u, const Anope::string &) override
{
u->RemoveMode(Config->GetClient("NickServ"), "REGISTERED");
}
diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp
index c481eb884..252134470 100644
--- a/modules/protocol/plexus.cpp
+++ b/modules/protocol/plexus.cpp
@@ -16,14 +16,16 @@ static Anope::string UplinkSID;
static ServiceReference<IRCDProto> hybrid("IRCDProto", "hybrid");
-class PlexusProto : public IRCDProto
+class PlexusProto final
+ : public IRCDProto
{
- public:
+public:
PlexusProto(Module *creator) : IRCDProto(creator, "hybrid-7.2.3+plexus-3.0.1")
{
DefaultPseudoclientModes = "+iU";
CanSVSNick = true;
CanSVSJoin = true;
+ CanSVSNOOP = true;
CanSetVHost = true;
CanSetVIdent = true;
CanSNLine = true;
@@ -35,28 +37,28 @@ class PlexusProto : public IRCDProto
MaxModes = 4;
}
- void SendSVSKillInternal(const MessageSource &source, User *targ, const Anope::string &reason) anope_override { hybrid->SendSVSKillInternal(source, targ, reason); }
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalNotice(bi, dest, msg); }
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalPrivmsg(bi, dest, msg); }
- void SendSQLine(User *u, const XLine *x) anope_override { hybrid->SendSQLine(u, x); }
- void SendSQLineDel(const XLine *x) anope_override { hybrid->SendSQLineDel(x); }
- void SendSGLineDel(const XLine *x) anope_override { hybrid->SendSGLineDel(x); }
- void SendSGLine(User *u, const XLine *x) anope_override { hybrid->SendSGLine(u, x); }
- void SendAkillDel(const XLine *x) anope_override { hybrid->SendAkillDel(x); }
- void SendAkill(User *u, XLine *x) anope_override { hybrid->SendAkill(u, x); }
- void SendServer(const Server *server) anope_override { hybrid->SendServer(server); }
- void SendChannel(Channel *c) anope_override { hybrid->SendChannel(c); }
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override { hybrid->SendSVSHold(nick, t); }
- void SendSVSHoldDel(const Anope::string &nick) anope_override { hybrid->SendSVSHoldDel(nick); }
-
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
+ void SendSVSKill(const MessageSource &source, User *targ, const Anope::string &reason) override { hybrid->SendSVSKill(source, targ, reason); }
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override { hybrid->SendGlobalNotice(bi, dest, msg); }
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override { hybrid->SendGlobalPrivmsg(bi, dest, msg); }
+ void SendSQLine(User *u, const XLine *x) override { hybrid->SendSQLine(u, x); }
+ void SendSQLineDel(const XLine *x) override { hybrid->SendSQLineDel(x); }
+ void SendSGLineDel(const XLine *x) override { hybrid->SendSGLineDel(x); }
+ void SendSGLine(User *u, const XLine *x) override { hybrid->SendSGLine(u, x); }
+ void SendAkillDel(const XLine *x) override { hybrid->SendAkillDel(x); }
+ void SendAkill(User *u, XLine *x) override { hybrid->SendAkill(u, x); }
+ void SendServer(const Server *server) override { hybrid->SendServer(server); }
+ void SendChannel(Channel *c) override { hybrid->SendChannel(c); }
+ void SendSVSHold(const Anope::string &nick, time_t t) override { hybrid->SendSVSHold(nick, t); }
+ void SendSVSHoldDel(const Anope::string &nick) override { hybrid->SendSVSHoldDel(nick); }
+
+ void SendGlobops(const MessageSource &source, const Anope::string &buf) override
{
- UplinkSocket::Message(source) << "OPERWALL :" << buf;
+ Uplink::Send(source, "OPERWALL", buf);
}
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override
{
- UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :" << user->GetUID();
+ Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), user->GetUID());
if (status)
{
/* First save the channel status incase uc->Status == status */
@@ -69,35 +71,37 @@ class PlexusProto : public IRCDProto
uc->status.Clear();
BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
+ for (auto mode : cs.Modes())
+ c->SetMode(setter, ModeManager::FindChannelModeByChar(mode), user->GetUID(), false);
if (uc != NULL)
uc->status = cs;
}
}
- void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override
+ void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) override
{
- UplinkSocket::Message(Me) << "ENCAP " << u->server->GetName() << " SVSNICK " << u->GetUID() << " " << u->timestamp << " " << newnick << " " << when;
+ Uplink::Send("ENCAP", u->server->GetName(), "SVSNICK", u->GetUID(), u->timestamp, newnick, when);
}
- void SendVhost(User *u, const Anope::string &ident, const Anope::string &host) anope_override
+ void SendVHost(User *u, const Anope::string &ident, const Anope::string &host) override
{
if (!ident.empty())
- UplinkSocket::Message(Me) << "ENCAP * CHGIDENT " << u->GetUID() << " " << ident;
- UplinkSocket::Message(Me) << "ENCAP * CHGHOST " << u->GetUID() << " " << host;
+ Uplink::Send("ENCAP", '*', "CHGIDENT", u->GetUID(), ident);
+
+ Uplink::Send("ENCAP", '*', "CHGHOST", u->GetUID(), host);
u->SetMode(Config->GetClient("HostServ"), "CLOAK");
}
- void SendVhostDel(User *u) anope_override
+ void SendVHostDel(User *u) override
{
u->RemoveMode(Config->GetClient("HostServ"), "CLOAK");
}
- void SendConnect() anope_override
+ void SendConnect() override
{
- UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " TS 6 :" << Me->GetSID();
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS", 6, Me->GetSID());
+
/* CAPAB
* QS - Can handle quit storm removal
* EX - Can do channel +e exemptions
@@ -118,7 +122,8 @@ class PlexusProto : public IRCDProto
* ENCAP - Supports encapsulation of protocol messages
* SVS - Supports services protocol extensions
*/
- UplinkSocket::Message() << "CAPAB :QS EX CHW IE EOB KLN UNKLN GLN HUB KNOCK TBURST PARA ENCAP SVS";
+ Uplink::Send("CAPAB", "QS EX CHW IE EOB KLN UNKLN GLN HUB KNOCK TBURST PARA ENCAP SVS");
+
/* Make myself known to myself in the serverlist */
SendServer(Me);
/*
@@ -129,69 +134,82 @@ class PlexusProto : public IRCDProto
* parv[3] = server is standalone or connected to non-TS only
* parv[4] = server's idea of UTC time
*/
- UplinkSocket::Message() << "SVINFO 6 5 0 :" << Anope::CurTime;
+ Uplink::Send("SVINFO", 6, 5, 0, Anope::CurTime);
}
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " 255.255.255.255 " << u->GetUID() << " 0 " << u->host << " :" << u->realname;
+ Uplink::Send("UID", u->nick, 1, u->timestamp, "+" + u->GetModes(), u->GetIdent(), u->host, "255.255.255.255", u->GetUID(), 0, u->host, u->realname);
}
- void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override
+ void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values) override
{
- UplinkSocket::Message(source) << "ENCAP * SVSMODE " << u->GetUID() << " " << u->timestamp << " " << buf;
+ auto params = values;
+ params.insert(params.begin(), { "*", "SVSMODE", u->GetUID(), Anope::ToString(u->timestamp), modes });
+ Uplink::SendInternal({}, source, "ENCAP", params);
}
- void SendLogin(User *u, NickAlias *na) anope_override
+ void SendLogin(User *u, NickAlias *na) override
{
- UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID() << " " << na->nc->display;
+ Uplink::Send("ENCAP", '*', "SU", u->GetUID(), na->nc->display);
}
- void SendLogout(User *u) anope_override
+ void SendLogout(User *u) override
{
- UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID();
+ Uplink::Send("ENCAP", '*', "SU", u->GetUID());
}
- void SendTopic(const MessageSource &source, Channel *c) anope_override
+ void SendTopic(const MessageSource &source, Channel *c) override
{
- UplinkSocket::Message(source) << "ENCAP * TOPIC " << c->name << " " << c->topic_setter << " " << c->topic_ts << " :" << c->topic;
+ Uplink::Send(source, "ENCAP", '*', "TOPIC", c->name, c->topic_setter, c->topic_ts, c->topic);
}
- void SendSVSJoin(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) anope_override
+ void SendSVSJoin(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &key) override
{
- UplinkSocket::Message(source) << "ENCAP " << user->server->GetName() << " SVSJOIN " << user->GetUID() << " " << chan;
+ Uplink::Send(source, "ENCAP", '*', "SVSJOIN", user->GetUID(), chan);
}
- void SendSVSPart(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) anope_override
+ void SendSVSPart(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) override
{
- UplinkSocket::Message(source) << "ENCAP " << user->server->GetName() << " SVSPART " << user->GetUID() << " " << chan;
+ Uplink::Send(source, "ENCAP", '*', "SVSPART", user->GetUID(), chan);
}
- void SendSASLMessage(const SASL::Message &message) anope_override
+ void SendSASLMessage(const SASL::Message &message) override
{
Server *s = Server::Find(message.target.substr(0, 3));
- UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : message.target.substr(0, 3)) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
+ auto target = s ? s->GetName() : message.target.substr(0, 3);
+
+ auto newparams = message.data;
+ newparams.insert(newparams.begin(), { target, "SASL", message.source, message.target, message.type });
+ Uplink::SendInternal({}, Me, "ENCAP", newparams);
}
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
+ void SendSVSLogin(const Anope::string &uid, NickAlias *na) override
{
Server *s = Server::Find(uid.substr(0, 3));
- UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * * "
- << (vhost.empty() ? "*" : vhost) << " " << acc;
+ Anope::string target = s ? s->GetName() : uid.substr(0, 3);
+ if (na)
+ {
+ Uplink::Send("ENCAP", target, "SVSLOGIN", uid, '*', '*', na->GetVHostHost().empty() ? "*" : na->GetVHostHost(), na->nc->display);
+ }
+ else
+ {
+ Uplink::Send("ENCAP", target, "SU", uid, "");
+ }
}
- void SendSVSNOOP(const Server *server, bool set) anope_override
+ void SendSVSNOOP(const Server *server, bool set) override
{
- UplinkSocket::Message() << "ENCAP " << server->GetName() << " SVSNOOP " << (set ? "+" : "-");
+ Uplink::Send("ENCAP", '*', "SVSNOOP", set ? '+' : '-');
}
};
-struct IRCDMessageEncap : IRCDMessage
+struct IRCDMessageEncap final
+ : IRCDMessage
{
- IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/*
* Received: :dev.anope.de ENCAP * SU DukePyrolator DukePyrolator
@@ -233,9 +251,7 @@ struct IRCDMessageEncap : IRCDMessage
m.source = params[2];
m.target = params[3];
m.type = params[4];
- m.data = params[5];
- m.ext = params.size() > 6 ? params[6] : "";
-
+ m.data.assign(params.begin() + 5, params.end());
SASL::sasl->ProcessMessage(m);
}
@@ -243,23 +259,25 @@ struct IRCDMessageEncap : IRCDMessage
}
};
-struct IRCDMessagePass : IRCDMessage
+struct IRCDMessagePass final
+ : IRCDMessage
{
- IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
UplinkSID = params[3];
}
};
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
/* 0 1 2 */
/* SERVER hades.arpa 1 :ircd-hybrid test server */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/* Servers other than our immediate uplink are introduced via SID */
if (params[1] != "1")
@@ -269,9 +287,10 @@ struct IRCDMessageServer : IRCDMessage
}
};
-struct IRCDMessageUID : IRCDMessage
+struct IRCDMessageUID final
+ : IRCDMessage
{
- IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11) { SetFlag(FLAG_REQUIRE_SERVER); }
/*
params[0] = nick
@@ -287,30 +306,18 @@ struct IRCDMessageUID : IRCDMessage
params[10] = info
*/
// :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB 0 192.168.0.5 :Adam
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/* An IP of 0 means the user is spoofed */
Anope::string ip = params[6];
if (ip == "0")
ip.clear();
- time_t ts;
- try
- {
- ts = convertTo<time_t>(params[2]);
- }
- catch (const ConvertException &)
- {
- ts = Anope::CurTime;
- }
-
+ auto ts = IRCD->ExtractTimestamp(params[2]);
NickAlias *na = NULL;
- try
- {
- if (params[8].is_pos_number_only() && convertTo<time_t>(params[8]) == ts)
- na = NickAlias::Find(params[0]);
- }
- catch (const ConvertException &) { }
+ if (IRCD->ExtractTimestamp(params[8]) == ts)
+ na = NickAlias::Find(params[0]);
+
if (params[8] != "0" && !na)
na = NickAlias::Find(params[8]);
@@ -318,7 +325,8 @@ struct IRCDMessageUID : IRCDMessage
}
};
-class ProtoPlexus : public Module
+class ProtoPlexus final
+ : public Module
{
Module *m_hybrid;
@@ -355,7 +363,7 @@ class ProtoPlexus : public Module
IRCDMessageServer message_server;
IRCDMessageUID message_uid;
- void AddModes()
+ static void AddModes()
{
/* Add user modes */
ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a'));
@@ -413,7 +421,7 @@ class ProtoPlexus : public Module
ModeManager::AddChannelMode(new ChannelMode("PERM", 'z'));
}
- public:
+public:
ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_away(this), message_capab(this), message_error(this), message_invite(this), message_kick(this), message_kill(this),
@@ -441,7 +449,7 @@ class ProtoPlexus : public Module
this->AddModes();
}
- ~ProtoPlexus()
+ ~ProtoPlexus() override
{
m_hybrid = ModuleManager::FindModule("hybrid");
ModuleManager::UnloadModule(m_hybrid, NULL);
diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp
index 27af38a49..1c51f9935 100644
--- a/modules/protocol/ratbox.cpp
+++ b/modules/protocol/ratbox.cpp
@@ -15,24 +15,25 @@ static Anope::string UplinkSID;
static ServiceReference<IRCDProto> hybrid("IRCDProto", "hybrid");
-class RatboxProto : public IRCDProto
+class RatboxProto final
+ : public IRCDProto
{
- BotInfo *FindIntroduced()
+ static BotInfo *FindIntroduced()
{
BotInfo *bi = Config->GetClient("OperServ");
if (bi && bi->introduced)
return bi;
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- if (it->second->introduced)
- return it->second;
+ for (const auto &[_, bi] : *BotListByNick)
+ if (bi->introduced)
+ return bi;
return NULL;
}
- public:
- RatboxProto(Module *creator) : IRCDProto(creator, "Ratbox 3.0+")
+public:
+ RatboxProto(Module *creator) : IRCDProto(creator, "ircd-ratbox 3+")
{
DefaultPseudoclientModes = "+oiS";
CanSNLine = true;
@@ -43,43 +44,40 @@ class RatboxProto : public IRCDProto
MaxModes = 4;
}
- void SendSVSKillInternal(const MessageSource &source, User *targ, const Anope::string &reason) anope_override { hybrid->SendSVSKillInternal(source, targ, reason); }
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalNotice(bi, dest, msg); }
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { hybrid->SendGlobalPrivmsg(bi, dest, msg); }
- void SendSGLine(User *u, const XLine *x) anope_override { hybrid->SendSGLine(u, x); }
- void SendSGLineDel(const XLine *x) anope_override { hybrid->SendSGLineDel(x); }
- void SendAkill(User *u, XLine *x) anope_override { hybrid->SendAkill(u, x); }
- void SendAkillDel(const XLine *x) anope_override { hybrid->SendAkillDel(x); }
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { hybrid->SendJoin(user, c, status); }
- void SendServer(const Server *server) anope_override { hybrid->SendServer(server); }
- void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override { hybrid->SendModeInternal(source, u, buf); }
- void SendChannel(Channel *c) anope_override { hybrid->SendChannel(c); }
- bool IsIdentValid(const Anope::string &ident) anope_override { return hybrid->IsIdentValid(ident); }
-
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
+ void SendSVSKill(const MessageSource &source, User *targ, const Anope::string &reason) override { hybrid->SendSVSKill(source, targ, reason); }
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override { hybrid->SendGlobalNotice(bi, dest, msg); }
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override { hybrid->SendGlobalPrivmsg(bi, dest, msg); }
+ void SendSGLine(User *u, const XLine *x) override { hybrid->SendSGLine(u, x); }
+ void SendSGLineDel(const XLine *x) override { hybrid->SendSGLineDel(x); }
+ void SendAkill(User *u, XLine *x) override { hybrid->SendAkill(u, x); }
+ void SendAkillDel(const XLine *x) override { hybrid->SendAkillDel(x); }
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override { hybrid->SendJoin(user, c, status); }
+ void SendServer(const Server *server) override { hybrid->SendServer(server); }
+ void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values) override { hybrid->SendModeInternal(source, u, modes, values); }
+ void SendChannel(Channel *c) override { hybrid->SendChannel(c); }
+ bool IsIdentValid(const Anope::string &ident) override { return hybrid->IsIdentValid(ident); }
+
+ void SendGlobops(const MessageSource &source, const Anope::string &buf) override
{
- UplinkSocket::Message(source) << "OPERWALL :" << buf;
+ Uplink::Send(source, "OPERWALL", buf);
}
- void SendSQLine(User *, const XLine *x) anope_override
+ void SendSQLine(User *, const XLine *x) override
{
- /* Calculate the time left before this would expire, capping it at 2 days */
- time_t timeleft = x->expires - Anope::CurTime;
-
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
-
- UplinkSocket::Message(FindIntroduced()) << "ENCAP * RESV " << timeleft << " " << x->mask << " 0 :" << x->GetReason();
+ // Calculate the time left before this would expire
+ time_t timeleft = x->expires ? x->expires - Anope::CurTime : x->expires;
+ Uplink::Send(FindIntroduced(), "ENCAP", '*', "RESV", timeleft, x->mask, 0, x->GetReason());
}
- void SendSQLineDel(const XLine *x) anope_override
+ void SendSQLineDel(const XLine *x) override
{
- UplinkSocket::Message(Config->GetClient("OperServ")) << "ENCAP * UNRESV " << x->mask;
+ Uplink::Send(FindIntroduced(), "ENCAP", '*', "UNRESV", x->mask);
}
- void SendConnect() anope_override
+ void SendConnect() override
{
- UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " TS 6 :" << Me->GetSID();
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS", 6, Me->GetSID());
+
/*
QS - Can handle quit storm removal
EX - Can do channel +e exemptions
@@ -90,9 +88,11 @@ class RatboxProto : public IRCDProto
TB - supports topic burst
ENCAP - supports ENCAP
*/
- UplinkSocket::Message() << "CAPAB :QS EX CHW IE GLN TB ENCAP";
+ Uplink::Send("CAPAB", "QS EX CHW IE GLN TB ENCAP");
+
/* Make myself known to myself in the serverlist */
SendServer(Me);
+
/*
* SVINFO
* parv[0] = sender prefix
@@ -101,29 +101,28 @@ class RatboxProto : public IRCDProto
* parv[3] = server is standalone or connected to non-TS only
* parv[4] = server's idea of UTC time
*/
- UplinkSocket::Message() << "SVINFO 6 3 0 :" << Anope::CurTime;
+ Uplink::Send("SVINFO", 6, 3, 0, Anope::CurTime);
}
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " 0 " << u->GetUID() << " :" << u->realname;
+ Uplink::Send("UID", u->nick, 1, u->timestamp, "+" + u->GetModes(), u->GetIdent(), u->host, 0, u->GetUID(), u->realname);
}
- void SendLogin(User *u, NickAlias *na) anope_override
+ void SendLogin(User *u, NickAlias *na) override
{
if (na->nc->HasExt("UNCONFIRMED"))
return;
- UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID() << " " << na->nc->display;
+ Uplink::Send("ENCAP", '*', "SU", u->GetUID(), na->nc->display);
}
- void SendLogout(User *u) anope_override
+ void SendLogout(User *u) override
{
- UplinkSocket::Message(Me) << "ENCAP * SU " << u->GetUID();
+ Uplink::Send("ENCAP", '*', "SU", u->GetUID());
}
- void SendTopic(const MessageSource &source, Channel *c) anope_override
+ void SendTopic(const MessageSource &source, Channel *c) override
{
BotInfo *bi = source.GetBot();
bool needjoin = c->FindUser(bi) == NULL;
@@ -143,12 +142,13 @@ class RatboxProto : public IRCDProto
}
};
-struct IRCDMessageEncap : IRCDMessage
+struct IRCDMessageEncap final
+ : IRCDMessage
{
- IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3) { SetFlag(FLAG_REQUIRE_USER); }
// Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params[1] == "LOGIN" || params[1] == "SU")
{
@@ -168,14 +168,15 @@ struct IRCDMessageEncap : IRCDMessage
}
};
-struct IRCDMessageJoin : Message::Join
+struct IRCDMessageJoin final
+ : Message::Join
{
IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() == 1 && params[0] == "0")
- return Message::Join::Run(source, params);
+ return Message::Join::Run(source, params, tags);
if (params.size() < 2)
return;
@@ -183,26 +184,28 @@ struct IRCDMessageJoin : Message::Join
std::vector<Anope::string> p = params;
p.erase(p.begin());
- return Message::Join::Run(source, p);
+ return Message::Join::Run(source, p, tags);
}
};
-struct IRCDMessagePass : IRCDMessage
+struct IRCDMessagePass final
+ : IRCDMessage
{
- IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
UplinkSID = params[3];
}
};
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
// SERVER hades.arpa 1 :ircd-ratbox test server
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
// Servers other then our immediate uplink are introduced via SID
if (params[1] != "1")
@@ -212,9 +215,10 @@ struct IRCDMessageServer : IRCDMessage
}
};
-struct IRCDMessageTBurst : IRCDMessage
+struct IRCDMessageTBurst final
+ : IRCDMessage
{
- IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TB", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TB", 3) { SetFlag(FLAG_SOFT_LIMIT); }
/*
* params[0] = channel
@@ -222,9 +226,9 @@ struct IRCDMessageTBurst : IRCDMessage
* params[2] = topic OR who set the topic
* params[3] = topic if params[2] isn't the topic
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
+ auto topic_time = IRCD->ExtractTimestamp(params[1]);
Channel *c = Channel::Find(params[0]);
if (!c)
@@ -237,19 +241,21 @@ struct IRCDMessageTBurst : IRCDMessage
}
};
-struct IRCDMessageUID : IRCDMessage
+struct IRCDMessageUID final
+ : IRCDMessage
{
- IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 9) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 9) { SetFlag(FLAG_REQUIRE_SERVER); }
// :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB :Adam
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
/* Source is always the server */
- User::OnIntroduce(params[0], params[4], params[5], "", params[6], source.GetServer(), params[8], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7], NULL);
+ User::OnIntroduce(params[0], params[4], params[5], "", params[6], source.GetServer(), params[8], IRCD->ExtractTimestamp(params[2]), params[3], params[7], NULL);
}
};
-class ProtoRatbox : public Module
+class ProtoRatbox final
+ : public Module
{
Module *m_hybrid;
@@ -288,7 +294,7 @@ class ProtoRatbox : public Module
IRCDMessageTBurst message_tburst;
IRCDMessageUID message_uid;
- void AddModes()
+ static void AddModes()
{
/* user modes */
ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a'));
@@ -337,7 +343,7 @@ class ProtoRatbox : public Module
ModeManager::AddChannelMode(new ChannelMode("SSL", 'S'));
}
- public:
+public:
ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_away(this), message_capab(this), message_error(this), message_invite(this), message_kick(this),
@@ -363,7 +369,7 @@ class ProtoRatbox : public Module
this->AddModes();
}
- ~ProtoRatbox()
+ ~ProtoRatbox() override
{
m_hybrid = ModuleManager::FindModule("hybrid");
ModuleManager::UnloadModule(m_hybrid, NULL);
diff --git a/modules/protocol/charybdis.cpp b/modules/protocol/solanum.cpp
index e1f317295..fa05daf46 100644
--- a/modules/protocol/charybdis.cpp
+++ b/modules/protocol/solanum.cpp
@@ -1,4 +1,4 @@
-/* Charybdis IRCD functions
+/* Solanum functions
*
* (C) 2003-2025 Anope Team
* Contact us at team@anope.org
@@ -17,23 +17,25 @@ static Anope::string UplinkSID;
static ServiceReference<IRCDProto> ratbox("IRCDProto", "ratbox");
-class ChannelModeLargeBan : public ChannelMode
+class ChannelModeLargeBan final
+ : public ChannelMode
{
- public:
+public:
ChannelModeLargeBan(const Anope::string &mname, char modeChar) : ChannelMode(mname, modeChar) { }
- bool CanSet(User *u) const anope_override
+ bool CanSet(User *u) const override
{
return u && u->HasMode("OPER");
}
};
-class CharybdisProto : public IRCDProto
+class SolanumProto final
+ : public IRCDProto
{
- public:
+public:
- CharybdisProto(Module *creator) : IRCDProto(creator, "Charybdis 3.4+")
+ SolanumProto(Module *creator) : IRCDProto(creator, "Solanum")
{
DefaultPseudoclientModes = "+oiS";
CanCertFP = true;
@@ -48,39 +50,37 @@ class CharybdisProto : public IRCDProto
MaxModes = 4;
}
- void SendSVSKillInternal(const MessageSource &source, User *targ, const Anope::string &reason) anope_override { ratbox->SendSVSKillInternal(source, targ, reason); }
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { ratbox->SendGlobalNotice(bi, dest, msg); }
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { ratbox->SendGlobalPrivmsg(bi, dest, msg); }
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override { ratbox->SendGlobopsInternal(source, buf); }
- void SendSGLine(User *u, const XLine *x) anope_override { ratbox->SendSGLine(u, x); }
- void SendSGLineDel(const XLine *x) anope_override { ratbox->SendSGLineDel(x); }
- void SendAkill(User *u, XLine *x) anope_override { ratbox->SendAkill(u, x); }
- void SendAkillDel(const XLine *x) anope_override { ratbox->SendAkillDel(x); }
- void SendSQLine(User *u, const XLine *x) anope_override { ratbox->SendSQLine(u, x); }
- void SendSQLineDel(const XLine *x) anope_override { ratbox->SendSQLineDel(x); }
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override { ratbox->SendJoin(user, c, status); }
- void SendServer(const Server *server) anope_override { ratbox->SendServer(server); }
- void SendChannel(Channel *c) anope_override { ratbox->SendChannel(c); }
- void SendTopic(const MessageSource &source, Channel *c) anope_override { ratbox->SendTopic(source, c); }
- bool IsIdentValid(const Anope::string &ident) anope_override { return ratbox->IsIdentValid(ident); }
- void SendLogin(User *u, NickAlias *na) anope_override { ratbox->SendLogin(u, na); }
- void SendLogout(User *u) anope_override { ratbox->SendLogout(u); }
-
- void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
+ void SendSVSKill(const MessageSource &source, User *targ, const Anope::string &reason) override { ratbox->SendSVSKill(source, targ, reason); }
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override { ratbox->SendGlobalNotice(bi, dest, msg); }
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override { ratbox->SendGlobalPrivmsg(bi, dest, msg); }
+ void SendGlobops(const MessageSource &source, const Anope::string &buf) override { ratbox->SendGlobops(source, buf); }
+ void SendSGLine(User *u, const XLine *x) override { ratbox->SendSGLine(u, x); }
+ void SendSGLineDel(const XLine *x) override { ratbox->SendSGLineDel(x); }
+ void SendAkill(User *u, XLine *x) override { ratbox->SendAkill(u, x); }
+ void SendAkillDel(const XLine *x) override { ratbox->SendAkillDel(x); }
+ void SendSQLine(User *u, const XLine *x) override { ratbox->SendSQLine(u, x); }
+ void SendSQLineDel(const XLine *x) override { ratbox->SendSQLineDel(x); }
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override { ratbox->SendJoin(user, c, status); }
+ void SendServer(const Server *server) override { ratbox->SendServer(server); }
+ void SendChannel(Channel *c) override { ratbox->SendChannel(c); }
+ void SendTopic(const MessageSource &source, Channel *c) override { ratbox->SendTopic(source, c); }
+ bool IsIdentValid(const Anope::string &ident) override { return ratbox->IsIdentValid(ident); }
+ void SendLogin(User *u, NickAlias *na) override { ratbox->SendLogin(u, na); }
+ void SendLogout(User *u) override { ratbox->SendLogout(u); }
+
+ void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) override
{
Anope::string mechlist;
+ for (const auto &mechanism : mechanisms)
+ mechlist += "," + mechanism;
- for (unsigned i = 0; i < mechanisms.size(); ++i)
- {
- mechlist += "," + mechanisms[i];
- }
-
- UplinkSocket::Message(Me) << "ENCAP * MECHLIST :" << (mechanisms.empty() ? "" : mechlist.substr(1));
+ Uplink::Send("ENCAP", '*', "MECHLIST", mechanisms.empty() ? "" : mechlist.substr(1));
}
- void SendConnect() anope_override
+ void SendConnect() override
{
- UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password << " TS 6 :" << Me->GetSID();
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password, "TS", 6, Me->GetSID());
+
/*
* Received: CAPAB :BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN
* KNOCK MLOCK QS RSFNC SAVE SERVICES TB UNKLN
@@ -88,6 +88,7 @@ class CharybdisProto : public IRCDProto
* BAN - Can do BAN message
* CHW - Can do channel wall @#
* CLUSTER - Supports umode +l, can send LOCOPS (encap only)
+ * ECHO - Supports sending echoed messages
* ENCAP - Can do ENCAP message
* EOPMOD - Can do channel wall =# (for cmode +z)
* EUID - Can do EUID (its similar to UID but includes the ENCAP REALHOST and ENCAP LOGIN information)
@@ -104,7 +105,7 @@ class CharybdisProto : public IRCDProto
* UNKLN - Can do UNKLINE (encap only)
* QS - Can handle quit storm removal
*/
- UplinkSocket::Message() << "CAPAB :BAN CHW CLUSTER ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SERVICES TB UNKLN";
+ Uplink::Send("CAPAB", "BAN CHW CLUSTER ECHO ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SERVICES TB UNKLN");
/* Make myself known to myself in the serverlist */
SendServer(Me);
@@ -116,63 +117,70 @@ class CharybdisProto : public IRCDProto
* arg[2] = '0'
* arg[3] = server's idea of UTC time
*/
- UplinkSocket::Message() << "SVINFO 6 6 0 :" << Anope::CurTime;
+ Uplink::Send("SVINFO", 6, 6, 0, Anope::CurTime);
}
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(Me) << "EUID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " << u->host << " 0 " << u->GetUID() << " * * :" << u->realname;
+ Uplink::Send("EUID", u->nick, 1, u->timestamp, "+" + u->GetModes(), u->GetIdent(), u->host, 0, u->GetUID(), '*', '*', u->realname);
}
- void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override
+ void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) override
{
- UplinkSocket::Message(Me) << "ENCAP " << u->server->GetName() << " RSFNC " << u->GetUID()
- << " " << newnick << " " << when << " " << u->timestamp;
+ Uplink::Send("ENCAP", u->server->GetName(), "RSFNC", u->GetUID(), newnick, when, u->timestamp);
}
- void SendSVSHold(const Anope::string &nick, time_t delay) anope_override
+ void SendSVSHold(const Anope::string &nick, time_t delay) override
{
- UplinkSocket::Message(Me) << "ENCAP * NICKDELAY " << delay << " " << nick;
+ Uplink::Send("ENCAP", '*', "NICKDELAY", delay, nick);
}
- void SendSVSHoldDel(const Anope::string &nick) anope_override
+ void SendSVSHoldDel(const Anope::string &nick) override
{
- UplinkSocket::Message(Me) << "ENCAP * NICKDELAY 0 " << nick;
+ Uplink::Send("ENCAP", '*', "NICKDELAY", 0, nick);
}
- void SendVhost(User *u, const Anope::string &ident, const Anope::string &host) anope_override
+ void SendVHost(User *u, const Anope::string &ident, const Anope::string &host) override
{
- UplinkSocket::Message(Me) << "ENCAP * CHGHOST " << u->GetUID() << " :" << host;
+ Uplink::Send("ENCAP", '*', "CHGHOST", u->GetUID(), host);
}
- void SendVhostDel(User *u) anope_override
+ void SendVHostDel(User *u) override
{
- this->SendVhost(u, "", u->host);
+ this->SendVHost(u, "", u->host);
}
- void SendSASLMessage(const SASL::Message &message) anope_override
+ void SendSASLMessage(const SASL::Message &message) override
{
Server *s = Server::Find(message.target.substr(0, 3));
- UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : message.target.substr(0, 3)) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext));
+ auto target = s ? s->GetName() : message.target.substr(0, 3);
+
+ auto newparams = message.data;
+ newparams.insert(newparams.begin(), { target, "SASL", message.source, message.target, message.type });
+ Uplink::SendInternal({}, Me, "ENCAP", newparams);
}
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
+ void SendSVSLogin(const Anope::string &uid, NickAlias *na) override
{
Server *s = Server::Find(uid.substr(0, 3));
- UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * " << (!vident.empty() ? vident : '*') << " " << (!vhost.empty() ? vhost : '*') << " " << acc;
+
+ Uplink::Send("ENCAP", s ? s->GetName() : uid.substr(0, 3), "SVSLOGIN", uid, '*',
+ na && !na->GetVHostIdent().empty() ? na->GetVHostIdent() : '*',
+ na && !na->GetVHostHost().empty() ? na->GetVHostHost() : '*',
+ na ? na->nc->display : "0");
}
};
-struct IRCDMessageEncap : IRCDMessage
+struct IRCDMessageEncap final
+ : IRCDMessage
{
IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 3)
{
- SetFlag(IRCDMESSAGE_SOFT_LIMIT);
+ SetFlag(FLAG_SOFT_LIMIT);
}
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
// In a burst, states that the source user is logged in as the account.
if (params[1] == "LOGIN" || params[1] == "SU")
@@ -205,7 +213,7 @@ struct IRCDMessageEncap : IRCDMessage
* termination: 'A' for abort, 'F' for authentication failure, 'S' for
* authentication success).
*
- * Charybdis only accepts messages from SASL agents; these must have umode +S
+ * Solanum only accepts messages from SASL agents; these must have umode +S
*/
else if (params[1] == "SASL" && SASL::sasl && params.size() >= 6)
{
@@ -213,17 +221,16 @@ struct IRCDMessageEncap : IRCDMessage
m.source = params[2];
m.target = params[3];
m.type = params[4];
- m.data = params[5];
- m.ext = params.size() > 6 ? params[6] : "";
-
+ m.data.assign(params.begin() + 5, params.end());
SASL::sasl->ProcessMessage(m);
}
}
};
-struct IRCDMessageEUID : IRCDMessage
+struct IRCDMessageEUID final
+ : IRCDMessage
{
- IRCDMessageEUID(Module *creator) : IRCDMessage(creator, "EUID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageEUID(Module *creator) : IRCDMessage(creator, "EUID", 11) { SetFlag(FLAG_REQUIRE_SERVER); }
/*
* :42X EUID DukePyrolator 1 1353240577 +Zi ~jens erft-5d80b00b.pool.mediaWays.net 93.128.176.11 42XAAAAAD * * :jens
@@ -238,23 +245,25 @@ struct IRCDMessageEUID : IRCDMessage
* user is not logged in with services). Hence a NICK or UID command received
* from a remote server should not be sent in EUID form to other servers.
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
NickAlias *na = NULL;
if (params[9] != "*")
na = NickAlias::Find(params[9]);
- User::OnIntroduce(params[0], params[4], (params[8] != "*" ? params[8] : params[5]), params[5], params[6], source.GetServer(), params[10], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime, params[3], params[7], na ? *na->nc : NULL);
+ User::OnIntroduce(params[0], params[4], (params[8] != "*" ? params[8] : params[5]), params[5], params[6], source.GetServer(),
+ params[10], IRCD->ExtractTimestamp(params[2]), params[3], params[7], na ? *na->nc : NULL);
}
};
// we can't use this function from ratbox because we set a local variable here
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
- // SERVER dev.anope.de 1 :charybdis test server
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ // SERVER dev.anope.de 1 :solanum test server
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
// Servers other then our immediate uplink are introduced via SID
if (params[1] != "1")
@@ -265,22 +274,52 @@ struct IRCDMessageServer : IRCDMessage
};
// we can't use this function from ratbox because we set a local variable here
-struct IRCDMessagePass : IRCDMessage
+struct IRCDMessagePass final
+ : IRCDMessage
{
- IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 4) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
// UplinkSID is used in IRCDMessageServer
UplinkSID = params[3];
}
};
-class ProtoCharybdis : public Module
+struct IRCDMessageNotice final
+ : Message::Notice
+{
+ IRCDMessageNotice(Module *creator) : Message::Notice(creator) { }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (Servers::Capab.count("ECHO"))
+ Uplink::Send("ECHO", 'N', source.GetSource(), params[1]);
+
+ Message::Notice::Run(source, params, tags);
+ }
+};
+
+struct IRCDMessagePrivmsg final
+ : Message::Privmsg
+{
+ IRCDMessagePrivmsg(Module *creator) : Message::Privmsg(creator) { }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ if (Servers::Capab.count("ECHO"))
+ Uplink::Send("ECHO", 'P', source.GetSource(), params[1]);
+
+ Message::Privmsg::Run(source, params, tags);
+ }
+};
+
+class ProtoSolanum final
+ : public Module
{
Module *m_ratbox;
- CharybdisProto ircd_proto;
+ SolanumProto ircd_proto;
/* Core message handlers */
Message::Away message_away;
@@ -291,10 +330,8 @@ class ProtoCharybdis : public Module
Message::Kill message_kill;
Message::Mode message_mode;
Message::MOTD message_motd;
- Message::Notice message_notice;
Message::Part message_part;
Message::Ping message_ping;
- Message::Privmsg message_privmsg;
Message::Quit message_quit;
Message::SQuit message_squit;
Message::Stats message_stats;
@@ -310,12 +347,12 @@ class ProtoCharybdis : public Module
/* Our message handlers */
IRCDMessageEncap message_encap;
IRCDMessageEUID message_euid;
+ IRCDMessageNotice message_notice;
IRCDMessagePass message_pass;
+ IRCDMessagePrivmsg message_privmsg;
IRCDMessageServer message_server;
- bool use_server_side_mlock;
-
- void AddModes()
+ static void AddModes()
{
/* Add user modes */
ModeManager::AddUserMode(new UserMode("NOFORWARD", 'Q'));
@@ -339,26 +376,26 @@ class ProtoCharybdis : public Module
ModeManager::AddChannelMode(new ChannelMode("OPMODERATED", 'z'));
}
- public:
- ProtoCharybdis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
+public:
+ ProtoSolanum(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
ircd_proto(this),
message_away(this), message_capab(this), message_error(this), message_invite(this), message_kick(this),
- message_kill(this), message_mode(this), message_motd(this), message_notice(this), message_part(this),
- message_ping(this), message_privmsg(this), message_quit(this), message_squit(this), message_stats(this),
- message_time(this), message_topic(this), message_version(this), message_whois(this),
-
- message_bmask("IRCDMessage", "charybdis/bmask", "ratbox/bmask"),
- message_join("IRCDMessage", "charybdis/join", "ratbox/join"),
- message_nick("IRCDMessage", "charybdis/nick", "ratbox/nick"),
- message_pong("IRCDMessage", "charybdis/pong", "ratbox/pong"),
- message_sid("IRCDMessage", "charybdis/sid", "ratbox/sid"),
- message_sjoin("IRCDMessage", "charybdis/sjoin", "ratbox/sjoin"),
- message_tb("IRCDMessage", "charybdis/tb", "ratbox/tb"),
- message_tmode("IRCDMessage", "charybdis/tmode", "ratbox/tmode"),
- message_uid("IRCDMessage", "charybdis/uid", "ratbox/uid"),
-
- message_encap(this), message_euid(this), message_pass(this), message_server(this)
-
+ message_kill(this), message_mode(this), message_motd(this), message_part(this), message_ping(this),
+ message_quit(this), message_squit(this), message_stats(this), message_time(this), message_topic(this),
+ message_version(this), message_whois(this),
+
+ message_bmask("IRCDMessage", "solanum/bmask", "ratbox/bmask"),
+ message_join("IRCDMessage", "solanum/join", "ratbox/join"),
+ message_nick("IRCDMessage", "solanum/nick", "ratbox/nick"),
+ message_pong("IRCDMessage", "solanum/pong", "ratbox/pong"),
+ message_sid("IRCDMessage", "solanum/sid", "ratbox/sid"),
+ message_sjoin("IRCDMessage", "solanum/sjoin", "ratbox/sjoin"),
+ message_tb("IRCDMessage", "solanum/tb", "ratbox/tb"),
+ message_tmode("IRCDMessage", "solanum/tmode", "ratbox/tmode"),
+ message_uid("IRCDMessage", "solanum/uid", "ratbox/uid"),
+
+ message_encap(this), message_euid(this), message_notice(this), message_pass(this),
+ message_privmsg(this), message_server(this)
{
@@ -373,55 +410,74 @@ class ProtoCharybdis : public Module
this->AddModes();
}
- ~ProtoCharybdis()
+ ~ProtoSolanum() override
{
m_ratbox = ModuleManager::FindModule("ratbox");
ModuleManager::UnloadModule(m_ratbox, NULL);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnUserLogin(User *u) override
+ {
+ // If the user has logged into their current nickname then mark them as such.
+ NickAlias *na = NickAlias::Find(u->nick);
+ if (na && na->nc == u->Account())
+ Uplink::Send("ENCAP", '*', "IDENTIFIED", u->GetUID(), u->nick);
+ else
+ Uplink::Send("ENCAP", '*', "IDENTIFIED", u->GetUID(), u->nick, "OFF");
+ }
+
+ void OnNickLogout(User *u) override
+ {
+ // We don't know what account the user was logged into so send in all cases.
+ Uplink::Send("ENCAP", '*', "IDENTIFIED", u->GetUID(), u->nick, "OFF");
+ }
+
+ void OnUserNickChange(User *u, const Anope::string &) override
{
- use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
+ // If the user is logged into an account check if we need to mark them
+ // as not identified to their nick.
+ if (u->Account())
+ OnUserLogin(u);
}
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
if (!c->ci)
return;
ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
- if (use_server_side_mlock && modelocks && Servers::Capab.count("MLOCK") > 0)
+ if (modelocks && Servers::Capab.count("MLOCK") > 0)
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(c->creation_time) << " " << c->ci->name << " " << modes;
+ Uplink::Send("MLOCK", c->creation_time, c->ci->name, modes);
}
}
- EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
+ EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, modes);
}
return EVENT_CONTINUE;
}
- EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
+ EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, modes);
}
return EVENT_CONTINUE;
}
};
-MODULE_INIT(ProtoCharybdis)
+MODULE_INIT(ProtoSolanum)
diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp
deleted file mode 100644
index e5436c9a2..000000000
--- a/modules/protocol/unreal.cpp
+++ /dev/null
@@ -1,1340 +0,0 @@
-/* Unreal IRCD 3.2.x functions
- *
- * (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/cs_mode.h"
-#include "modules/sasl.h"
-
-class UnrealIRCdProto : public IRCDProto
-{
- public:
- UnrealIRCdProto(Module *creator) : IRCDProto(creator, "UnrealIRCd 3.2.x")
- {
- DefaultPseudoclientModes = "+Soiq";
- CanSVSNick = true;
- CanSVSJoin = true;
- CanSetVHost = true;
- CanSetVIdent = true;
- CanSNLine = true;
- CanSQLine = true;
- CanSZLine = true;
- CanSVSHold = true;
- CanSVSO = true;
- MaxModes = 12;
- }
-
- private:
- /* SVSNOOP */
- void SendSVSNOOP(const Server *server, bool set) anope_override
- {
- UplinkSocket::Message() << "SVSNOOP " << server->GetName() << " " << (set ? "+" : "-");
- }
-
- void SendAkillDel(const XLine *x) anope_override
- {
- if (x->IsRegex() || x->HasNickOrReal())
- return;
-
- /* ZLine if we can instead */
- if (x->GetUser() == "*")
- {
- cidr a(x->GetHost());
- if (a.valid())
- {
- IRCD->SendSZLineDel(x);
- return;
- }
- }
-
- UplinkSocket::Message() << "TKL - G " << x->GetUser() << " " << x->GetHost() << " " << x->by;
- }
-
- void SendTopic(const MessageSource &source, Channel *c) anope_override
- {
- UplinkSocket::Message(source) << "TOPIC " << c->name << " " << c->topic_setter << " " << c->topic_ts << " :" << c->topic;
- }
-
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
- {
- UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
- }
-
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
- {
- UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
- }
-
- void SendVhostDel(User *u) anope_override
- {
- BotInfo *HostServ = Config->GetClient("HostServ");
- u->RemoveMode(HostServ, "CLOAK");
- u->RemoveMode(HostServ, "VHOST");
- ModeManager::ProcessModes();
- u->SetMode(HostServ, "CLOAK");
- }
-
- void SendAkill(User *u, XLine *x) anope_override
- {
- if (x->IsRegex() || x->HasNickOrReal())
- {
- if (!u)
- {
- /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (x->manager->Check(it->second, x))
- this->SendAkill(it->second, x);
- return;
- }
-
- const XLine *old = x;
-
- if (old->manager->HasEntry("*@" + u->host))
- return;
-
- /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
- XLine *xline = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
- old->manager->AddXLine(xline);
- x = xline;
-
- Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
- }
-
- /* ZLine if we can instead */
- if (x->GetUser() == "*")
- {
- cidr a(x->GetHost());
- if (a.valid())
- {
- IRCD->SendSZLine(u, x);
- return;
- }
- }
-
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- UplinkSocket::Message() << "TKL + G " << x->GetUser() << " " << x->GetHost() << " " << x->by << " " << Anope::CurTime + timeleft << " " << x->created << " :" << x->GetReason();
- }
-
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override
- {
- UplinkSocket::Message(source) << "SVSKILL " << user->nick << " :" << buf;
- user->KillInternal(source, buf);
- }
-
- void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override
- {
- UplinkSocket::Message(source) << "SVS2MODE " << u->nick <<" " << buf;
- }
-
- void SendClientIntroduction(User *u) anope_override
- {
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message() << "NICK " << u->nick << " 1 " << u->timestamp << " " << u->GetIdent() << " " << u->host << " " << u->server->GetName() << " 0 " << modes << " " << u->host << " * :" << u->realname;
- }
-
- /* SERVER name hop descript */
- /* Unreal 3.2 actually sends some info about itself in the descript area */
- void SendServer(const Server *server) anope_override
- {
- if (!server->GetSID().empty() && server == Me)
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :U0-*-" << server->GetSID() << " " << server->GetDescription();
- else
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription();
- }
-
- /* JOIN */
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
- {
- UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " :" << user->nick;
- if (status)
- {
- /* First save the channel status incase uc->Status == status */
- ChannelStatus cs = *status;
- /* If the user is internally on the channel with flags, kill them so that
- * the stacker will allow this.
- */
- ChanUserContainer *uc = c->FindUser(user);
- if (uc != NULL)
- uc->status.Clear();
-
- BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
-
- if (uc != NULL)
- uc->status = cs;
- }
- }
-
- /* unsqline
- */
- void SendSQLineDel(const XLine *x) anope_override
- {
- UplinkSocket::Message() << "UNSQLINE " << x->mask;
- }
-
- /* SQLINE */
- /*
- ** - Unreal will translate this to TKL for us
- **
- */
- void SendSQLine(User *, const XLine *x) anope_override
- {
- UplinkSocket::Message() << "SQLINE " << x->mask << " :" << x->GetReason();
- }
-
- /*
- ** svso
- ** parv[0] = sender prefix
- ** parv[1] = nick
- ** parv[2] = options
- */
- void SendSVSO(BotInfo *source, const Anope::string &nick, const Anope::string &flag) anope_override
- {
- UplinkSocket::Message(source) << "SVSO " << nick << " " << flag;
- }
-
- /* Functions that use serval cmd functions */
-
- void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
- {
- if (!vIdent.empty())
- UplinkSocket::Message(Me) << "CHGIDENT " << u->nick << " " << vIdent;
- if (!vhost.empty())
- UplinkSocket::Message(Me) << "CHGHOST " << u->nick << " " << vhost;
- }
-
- void SendConnect() anope_override
- {
- /*
- NICKv2 = Nick Version 2
- VHP = Sends hidden host
- UMODE2 = sends UMODE2 on user modes
- NICKIP = Sends IP on NICK
- TOKEN = Use tokens to talk
- SJ3 = Supports SJOIN
- NOQUIT = No Quit
- TKLEXT = Extended TKL we don't use it but best to have it
- SJB64 = Base64 encoded time stamps
- ESVID = Allows storing account names as services stamp
- MLOCK = Supports the MLOCK server command
- VL = Version Info
- NS = Config->Numeric Server
- */
- Anope::string protoctl = "NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK VL";
- if (!Me->GetSID().empty())
- protoctl += " VL";
- UplinkSocket::Message() << "PROTOCTL " << protoctl;
- UplinkSocket::Message() << "PASS :" << Config->Uplinks[Anope::CurrentUplink].password;
- SendServer(Me);
- }
-
- /* SVSHOLD - set */
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override
- {
- UplinkSocket::Message() << "TKL + Q H " << nick << " " << Me->GetName() << " " << Anope::CurTime + t << " " << Anope::CurTime << " :Being held for registered user";
- }
-
- /* SVSHOLD - release */
- void SendSVSHoldDel(const Anope::string &nick) anope_override
- {
- UplinkSocket::Message() << "TKL - Q * " << nick << " " << Me->GetName();
- }
-
- /* UNSGLINE */
- /*
- * SVSNLINE - :realname mask
- */
- void SendSGLineDel(const XLine *x) anope_override
- {
- UplinkSocket::Message() << "SVSNLINE - :" << x->mask;
- }
-
- /* UNSZLINE */
- void SendSZLineDel(const XLine *x) anope_override
- {
- UplinkSocket::Message() << "TKL - Z * " << x->GetHost() << " " << x->by;
- }
-
- /* SZLINE */
- void SendSZLine(User *, const XLine *x) anope_override
- {
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- UplinkSocket::Message() << "TKL + Z * " << x->GetHost() << " " << x->by << " " << Anope::CurTime + timeleft << " " << x->created << " :" << x->GetReason();
- }
-
- /* SGLINE */
- /*
- * SVSNLINE + reason_where_is_space :realname mask with spaces
- */
- void SendSGLine(User *, const XLine *x) anope_override
- {
- Anope::string edited_reason = x->GetReason();
- edited_reason = edited_reason.replace_all_cs(" ", "_");
- UplinkSocket::Message() << "SVSNLINE + " << edited_reason << " :" << x->mask;
- }
-
- /* svsjoin
- parv[0] - sender
- parv[1] - nick to make join
- parv[2] - channel to join
- parv[3] - (optional) channel key(s)
- */
- /* In older Unreal SVSJOIN and SVSNLINE tokens were mixed so SVSJOIN and SVSNLINE are broken
- when coming from a none TOKEN'd server
- */
- void SendSVSJoin(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) anope_override
- {
- if (!param.empty())
- UplinkSocket::Message(source) << "SVSJOIN " << user->GetUID() << " " << chan << " :" << param;
- else
- UplinkSocket::Message(source) << "SVSJOIN " << user->GetUID() << " " << chan;
- }
-
- void SendSVSPart(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) anope_override
- {
- if (!param.empty())
- UplinkSocket::Message(source) << "SVSPART " << user->GetUID() << " " << chan << " :" << param;
- else
- UplinkSocket::Message(source) << "SVSPART " << user->GetUID() << " " << chan;
- }
-
- void SendSWhois(const MessageSource &source, const Anope::string &who, const Anope::string &mask) anope_override
- {
- UplinkSocket::Message(source) << "SWHOIS " << who << " :" << mask;
- }
-
- void SendEOB() anope_override
- {
- UplinkSocket::Message(Me) << "EOS";
- }
-
- bool IsNickValid(const Anope::string &nick) anope_override
- {
- if (nick.equals_ci("ircd") || nick.equals_ci("irc"))
- return false;
-
- return IRCDProto::IsNickValid(nick);
- }
-
- bool IsChannelValid(const Anope::string &chan) anope_override
- {
- if (chan.find(':') != Anope::string::npos)
- return false;
-
- return IRCDProto::IsChannelValid(chan);
- }
-
- bool IsExtbanValid(const Anope::string &mask) anope_override
- {
- return mask.length() >= 4 && mask[0] == '~' && mask[2] == ':';
- }
-
- void SendLogin(User *u, NickAlias *na) anope_override
- {
- /* 3.2.10.4+ treats users logged in with accounts as fully registered, even if -r, so we can not set this here. Just use the timestamp. */
- if (Servers::Capab.count("ESVID") > 0 && !na->nc->HasExt("UNCONFIRMED"))
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %s", na->nc->display.c_str());
- else
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %d", u->signon);
- }
-
- void SendLogout(User *u) anope_override
- {
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d 0");
- }
-
- void SendChannel(Channel *c) anope_override
- {
- /* Unreal does not support updating a channels TS without actually joining a user,
- * so we will join and part us now
- */
- BotInfo *bi = c->WhoSends();
- if (!bi)
- ;
- else if (c->FindUser(bi) == NULL)
- {
- bi->Join(c);
- bi->Part(c);
- }
- else
- {
- bi->Part(c);
- bi->Join(c);
- }
- }
-
- void SendSASLMessage(const SASL::Message &message) anope_override
- {
- size_t p = message.target.find('!');
- if (p == Anope::string::npos)
- return;
-
- UplinkSocket::Message(BotInfo::Find(message.source)) << "SASL " << message.target.substr(0, p) << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : " " + message.ext);
- }
-
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
- {
- size_t p = uid.find('!');
- if (p == Anope::string::npos)
- return;
- UplinkSocket::Message(Me) << "SVSLOGIN " << uid.substr(0, p) << " " << uid << " " << acc;
- }
-
- bool IsIdentValid(const Anope::string &ident) anope_override
- {
- if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
- return false;
-
- for (unsigned i = 0; i < ident.length(); ++i)
- {
- const char &c = ident[i];
-
- if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
- continue;
-
- if (c == '-' || c == '.' || c == '_')
- continue;
-
- return false;
- }
-
- return true;
- }
-};
-
-class UnrealExtBan : public ChannelModeVirtual<ChannelModeList>
-{
- char ext;
-
- public:
- UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
- , ext(extban)
- {
- }
-
- ChannelMode *Wrap(Anope::string &param) anope_override
- {
- param = "~" + Anope::string(ext) + ":" + param;
- return ChannelModeVirtual<ChannelModeList>::Wrap(param);
- }
-
- ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) anope_override
- {
- if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':')
- return cm;
-
- param = param.substr(3);
- return this;
- }
-};
-
-namespace UnrealExtban
-{
- class ChannelMatcher : public UnrealExtBan
- {
- public:
- ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string channel = mask.substr(3);
-
- ChannelMode *cm = NULL;
- if (channel[0] != '#')
- {
- char modeChar = ModeManager::GetStatusChar(channel[0]);
- channel.erase(channel.begin());
- cm = ModeManager::FindChannelModeByChar(modeChar);
- if (cm != NULL && cm->type != MODE_STATUS)
- cm = NULL;
- }
-
- Channel *c = Channel::Find(channel);
- if (c != NULL)
- {
- ChanUserContainer *uc = c->FindUser(u);
- if (uc != NULL)
- if (cm == NULL || uc->status.HasMode(cm->mchar))
- return true;
- }
-
- return false;
- }
- };
-
- class EntryMatcher : public UnrealExtBan
- {
- public:
- EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
-
- return Entry(this->name, real_mask).Matches(u);
- }
- };
-
- class RealnameMatcher : public UnrealExtBan
- {
- public:
- RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
-
- return Anope::Match(u->realname, real_mask);
- }
- };
-
- class RegisteredMatcher : public UnrealExtBan
- {
- public:
- RegisteredMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- return u->HasMode("REGISTERED") && mask.equals_ci(u->nick);
- }
- };
-
- class AccountMatcher : public UnrealExtBan
- {
- public:
- AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
-
- return u->IsIdentified() && Anope::Match(u->Account()->display, real_mask);
- }
- };
-}
-
-class ChannelModeFlood : public ChannelModeParam
-{
- public:
- ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
-
- /* Borrowed part of this check from UnrealIRCd */
- bool IsValid(Anope::string &value) const anope_override
- {
- if (value.empty())
- return false;
- try
- {
- Anope::string rest;
- if (value[0] != ':' && convertTo<unsigned>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<unsigned>(rest.substr(1), rest, false) > 0 && rest.empty())
- return true;
- }
- catch (const ConvertException &) { }
-
- /* '['<number><1 letter>[optional: '#'+1 letter],[next..]']'':'<number> */
- size_t end_bracket = value.find(']', 1);
- if (end_bracket == Anope::string::npos)
- return false;
- Anope::string xbuf = value.substr(0, end_bracket);
- if (value[end_bracket + 1] != ':')
- return false;
- commasepstream args(xbuf.substr(1));
- Anope::string arg;
- while (args.GetToken(arg))
- {
- /* <number><1 letter>[optional: '#'+1 letter] */
- size_t p = 0;
- while (p < arg.length() && isdigit(arg[p]))
- ++p;
- if (p == arg.length() || !(arg[p] == 'c' || arg[p] == 'j' || arg[p] == 'k' || arg[p] == 'm' || arg[p] == 'n' || arg[p] == 't'))
- continue; /* continue instead of break for forward compatibility. */
- try
- {
- int v = arg.substr(0, p).is_number_only() ? convertTo<int>(arg.substr(0, p)) : 0;
- if (v < 1 || v > 999)
- return false;
- }
- catch (const ConvertException &)
- {
- return false;
- }
- }
-
- return true;
- }
-};
-
-class ChannelModeUnrealSSL : public ChannelMode
-{
- public:
- ChannelModeUnrealSSL(const Anope::string &n, char c) : ChannelMode(n, c)
- {
- }
-
- bool CanSet(User *u) const anope_override
- {
- return false;
- }
-};
-
-struct IRCDMessageCapab : Message::Capab
-{
- IRCDMessageCapab(Module *creator) : Message::Capab(creator, "PROTOCTL") { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- for (unsigned i = 0; i < params.size(); ++i)
- {
- Anope::string capab = params[i];
-
- if (capab.find("CHANMODES") != Anope::string::npos)
- {
- Anope::string modes(capab.begin() + 10, capab.end());
- commasepstream sep(modes);
- Anope::string modebuf;
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'b':
- ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
-
- ModeManager::AddChannelMode(new UnrealExtban::ChannelMatcher("CHANNELBAN", "BAN", 'c'));
- ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("JOINBAN", "BAN", 'j'));
- ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("NONICKBAN", "BAN", 'n'));
- ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("QUIET", "BAN", 'q'));
- ModeManager::AddChannelMode(new UnrealExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
- ModeManager::AddChannelMode(new UnrealExtban::RegisteredMatcher("REGISTEREDBAN", "BAN", 'R'));
- ModeManager::AddChannelMode(new UnrealExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'a'));
- continue;
- case 'e':
- ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
- continue;
- case 'I':
- ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeList("", modebuf[t]));
- }
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'k':
- ModeManager::AddChannelMode(new ChannelModeKey('k'));
- continue;
- case 'f':
- ModeManager::AddChannelMode(new ChannelModeFlood('f', false));
- continue;
- case 'L':
- ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L'));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t]));
- }
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'l':
- ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
- continue;
- case 'j':
- ModeManager::AddChannelMode(new ChannelModeParam("JOINFLOOD", 'j', true));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t], true));
- }
- }
-
- sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
- {
- switch (modebuf[t])
- {
- case 'p':
- ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
- continue;
- case 's':
- ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
- continue;
- case 'm':
- ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm'));
- continue;
- case 'n':
- ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n'));
- continue;
- case 't':
- ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
- continue;
- case 'i':
- ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i'));
- continue;
- case 'r':
- ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r'));
- continue;
- case 'R':
- ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
- continue;
- case 'c':
- ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c'));
- continue;
- case 'O':
- ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O'));
- continue;
- case 'A':
- ModeManager::AddChannelMode(new ChannelModeOperOnly("ADMINONLY", 'A'));
- continue;
- case 'Q':
- ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q'));
- continue;
- case 'K':
- ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K'));
- continue;
- case 'V':
- ModeManager::AddChannelMode(new ChannelMode("NOINVITE", 'V'));
- continue;
- case 'C':
- ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
- continue;
- case 'u':
- ModeManager::AddChannelMode(new ChannelMode("AUDITORIUM", 'u'));
- continue;
- case 'z':
- ModeManager::AddChannelMode(new ChannelMode("SSL", 'z'));
- continue;
- case 'N':
- ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N'));
- continue;
- case 'S':
- ModeManager::AddChannelMode(new ChannelMode("STRIPCOLOR", 'S'));
- continue;
- case 'M':
- ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
- continue;
- case 'T':
- ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'T'));
- continue;
- case 'G':
- ModeManager::AddChannelMode(new ChannelMode("CENSOR", 'G'));
- continue;
- case 'Z':
- ModeManager::AddChannelMode(new ChannelModeUnrealSSL("", 'Z'));
- continue;
- default:
- ModeManager::AddChannelMode(new ChannelMode("", modebuf[t]));
- }
- }
- }
- }
-
- Message::Capab::Run(source, params);
- }
-};
-
-struct IRCDMessageChgHost : IRCDMessage
-{
- IRCDMessageChgHost(Module *creator) : IRCDMessage(creator, "CHGHOST", 2) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = User::Find(params[0]);
- if (u)
- u->SetDisplayedHost(params[1]);
- }
-};
-
-struct IRCDMessageChgIdent : IRCDMessage
-{
- IRCDMessageChgIdent(Module *creator) : IRCDMessage(creator, "CHGIDENT", 2) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = User::Find(params[0]);
- if (u)
- u->SetVIdent(params[1]);
- }
-};
-
-struct IRCDMessageChgName : IRCDMessage
-{
- IRCDMessageChgName(Module *creator) : IRCDMessage(creator, "CHGNAME", 2) { }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = User::Find(params[0]);
- if (u)
- u->SetRealname(params[1]);
- }
-};
-
-struct IRCDMessageMode : IRCDMessage
-{
- IRCDMessageMode(Module *creator, const Anope::string &mname) : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- bool server_source = source.GetServer() != NULL;
- Anope::string modes = params[1];
- for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i)
- modes += " " + params[i];
-
- if (IRCD->IsChannelValid(params[0]))
- {
- Channel *c = Channel::Find(params[0]);
- time_t ts = 0;
-
- try
- {
- if (server_source)
- ts = convertTo<time_t>(params[params.size() - 1]);
- }
- catch (const ConvertException &) { }
-
- if (c)
- c->SetModesInternal(source, modes, ts);
- }
- else
- {
- User *u = User::Find(params[0]);
- if (u)
- u->SetModesInternal(source, "%s", params[1].c_str());
- }
- }
-};
-
-/* netinfo
- * argv[0] = max global count
- * argv[1] = time of end sync
- * argv[2] = unreal protocol using (numeric)
- * argv[3] = cloak-crc (> u2302)
- * argv[4] = free(**)
- * argv[5] = free(**)
- * argv[6] = free(**)
- * argv[7] = ircnet
- */
-struct IRCDMessageNetInfo : IRCDMessage
-{
- IRCDMessageNetInfo(Module *creator) : IRCDMessage(creator, "NETINFO", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- UplinkSocket::Message() << "NETINFO " << MaxUserCount << " " << Anope::CurTime << " " << convertTo<int>(params[2]) << " " << params[3] << " 0 0 0 :" << params[7];
- }
-};
-
-struct IRCDMessageNick : IRCDMessage
-{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- /*
- ** NICK - new
- ** source = NULL
- ** parv[0] = nickname
- ** parv[1] = hopcount
- ** parv[2] = timestamp
- ** parv[3] = username
- ** parv[4] = hostname
- ** parv[5] = servername
- ** parv[6] = servicestamp
- ** parv[7] = umodes
- ** parv[8] = virthost, * if none
- ** parv[9] = ip
- ** parv[10] = info
- **
- ** NICK - change
- ** source = oldnick
- ** parv[0] = new nickname
- ** parv[1] = hopcount
- */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (params.size() == 11)
- {
- Anope::string ip;
- if (params[9] != "*")
- {
- Anope::string decoded_ip;
- Anope::B64Decode(params[9], decoded_ip);
-
- sockaddrs ip_addr;
- ip_addr.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str());
- ip = ip_addr.addr();
- }
-
- Anope::string vhost = params[8];
- if (vhost.equals_cs("*"))
- vhost.clear();
-
- time_t user_ts = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime;
-
- Server *s = Server::Find(params[5]);
- if (s == NULL)
- {
- Log(LOG_DEBUG) << "User " << params[0] << " introduced from nonexistent server " << params[5] << "?";
- return;
- }
-
- NickAlias *na = NULL;
-
- if (params[6] == "0")
- ;
- else if (params[6].is_pos_number_only())
- {
- if (convertTo<time_t>(params[6]) == user_ts)
- na = NickAlias::Find(params[0]);
- }
- else
- {
- na = NickAlias::Find(params[6]);
- }
-
- User::OnIntroduce(params[0], params[3], params[4], vhost, ip, s, params[10], user_ts, params[7], "", na ? *na->nc : NULL);
- }
- else
- {
- User *u = source.GetUser();
- if (u)
- u->ChangeNick(params[0]);
- }
- }
-};
-
-/** This is here because:
- *
- * If we had three servers, A, B & C linked like so: A<->B<->C
- * If Anope is linked to A and B splits from A and then reconnects
- * B introduces itself, introduces C, sends EOS for C, introduces Bs clients
- * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced
- * with their server "not syncing". We now send a PING immediately when receiving a new server
- * and then finish sync once we get a pong back from that server.
- */
-struct IRCDMessagePong : IRCDMessage
-{
- IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!source.GetServer()->IsSynced())
- source.GetServer()->Sync(false);
- }
-};
-
-struct IRCDMessageSASL : IRCDMessage
-{
- IRCDMessageSASL(Module *creator) : IRCDMessage(creator, "SASL", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- size_t p = params[1].find('!');
- if (!SASL::sasl || p == Anope::string::npos)
- return;
-
- SASL::Message m;
- m.source = params[1];
- m.target = params[0];
- m.type = params[2];
- m.data = params[3];
- m.ext = params.size() > 4 ? params[4] : "";
-
- SASL::sasl->ProcessMessage(m);
- }
-};
-
-struct IRCDMessageSDesc : IRCDMessage
-{
- IRCDMessageSDesc(Module *creator) : IRCDMessage(creator, "SDESC", 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetServer()->SetDescription(params[0]);
- }
-};
-
-struct IRCDMessageSetHost : IRCDMessage
-{
- IRCDMessageSetHost(Module *creator) : IRCDMessage(creator, "SETHOST", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = source.GetUser();
-
- /* When a user sets +x we receive the new host and then the mode change */
- if (u->HasMode("CLOAK"))
- u->SetDisplayedHost(params[0]);
- else
- u->SetCloakedHost(params[0]);
- }
-};
-
-struct IRCDMessageSetIdent : IRCDMessage
-{
- IRCDMessageSetIdent(Module *creator) : IRCDMessage(creator, "SETIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = source.GetUser();
- u->SetVIdent(params[0]);
- }
-};
-
-struct IRCDMessageSetName : IRCDMessage
-{
- IRCDMessageSetName(Module *creator) : IRCDMessage(creator, "SETNAME", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- User *u = source.GetUser();
- u->SetRealname(params[0]);
- }
-};
-
-struct IRCDMessageServer : IRCDMessage
-{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
-
- if (params[1].equals_cs("1"))
- {
- Anope::string desc;
- spacesepstream(params[2]).GetTokenRemainder(desc, 1);
-
- new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, desc);
- }
- else
- new Server(source.GetServer(), params[0], hops, params[2]);
-
- IRCD->SendPing(Me->GetName(), params[0]);
- }
-};
-
-struct IRCDMessageSJoin : IRCDMessage
-{
- IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Anope::string modes;
- if (params.size() >= 4)
- for (unsigned i = 2; i < params.size() - 1; ++i)
- modes += " " + params[i];
- if (!modes.empty())
- modes.erase(modes.begin());
-
- std::list<Anope::string> bans, excepts, invites;
- std::list<Message::Join::SJoinUser> users;
-
- spacesepstream sep(params[params.size() - 1]);
- Anope::string buf;
- while (sep.GetToken(buf))
- {
- /* Ban */
- if (buf[0] == '&')
- {
- buf.erase(buf.begin());
- bans.push_back(buf);
- }
- /* Except */
- else if (buf[0] == '"')
- {
- buf.erase(buf.begin());
- excepts.push_back(buf);
- }
- /* Invex */
- else if (buf[0] == '\'')
- {
- buf.erase(buf.begin());
- invites.push_back(buf);
- }
- else
- {
- Message::Join::SJoinUser sju;
-
- /* Get prefixes from the nick */
- for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));)
- {
- sju.first.AddMode(ch);
- buf.erase(buf.begin());
- }
-
- sju.second = User::Find(buf);
- if (!sju.second)
- {
- Log(LOG_DEBUG) << "SJOIN for nonexistent user " << buf << " on " << params[1];
- continue;
- }
-
- users.push_back(sju);
- }
- }
-
- time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime;
- Message::Join::SJoin(source, params[1], ts, modes, users);
-
- if (!bans.empty() || !excepts.empty() || !invites.empty())
- {
- Channel *c = Channel::Find(params[1]);
-
- if (!c || c->creation_time != ts)
- return;
-
- ChannelMode *ban = ModeManager::FindChannelModeByName("BAN"),
- *except = ModeManager::FindChannelModeByName("EXCEPT"),
- *invex = ModeManager::FindChannelModeByName("INVITEOVERRIDE");
-
- if (ban)
- for (std::list<Anope::string>::iterator it = bans.begin(), it_end = bans.end(); it != it_end; ++it)
- c->SetModeInternal(source, ban, *it);
- if (except)
- for (std::list<Anope::string>::iterator it = excepts.begin(), it_end = excepts.end(); it != it_end; ++it)
- c->SetModeInternal(source, except, *it);
- if (invex)
- for (std::list<Anope::string>::iterator it = invites.begin(), it_end = invites.end(); it != it_end; ++it)
- c->SetModeInternal(source, invex, *it);
- }
- }
-};
-
-struct IRCDMessageTopic : IRCDMessage
-{
- IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 4) { }
-
- /*
- ** source = sender prefix
- ** parv[0] = channel name
- ** parv[1] = topic nickname
- ** parv[2] = topic time
- ** parv[3] = topic text
- */
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- Channel *c = Channel::Find(params[0]);
- if (c)
- c->ChangeTopicInternal(source.GetUser(), params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime);
- }
-};
-
-
-struct IRCDMessageUmode2 : IRCDMessage
-{
- IRCDMessageUmode2(Module *creator) : IRCDMessage(creator, "UMODE2", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
-
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
- {
- source.GetUser()->SetModesInternal(source, "%s", params[0].c_str());
- }
-};
-
-class ProtoUnreal : public Module
-{
- UnrealIRCdProto ircd_proto;
-
- /* Core message handlers */
- Message::Away message_away;
- Message::Error message_error;
- Message::Invite message_invite;
- Message::Join message_join;
- Message::Kick message_kick;
- Message::Kill message_kill, message_svskill;
- Message::MOTD message_motd;
- Message::Notice message_notice;
- Message::Part message_part;
- Message::Ping message_ping;
- Message::Privmsg message_privmsg;
- Message::Quit message_quit;
- Message::SQuit message_squit;
- Message::Stats message_stats;
- Message::Time message_time;
- Message::Version message_version;
- Message::Whois message_whois;
-
- /* Our message handlers */
- IRCDMessageCapab message_capab;
- IRCDMessageChgHost message_chghost;
- IRCDMessageChgIdent message_chgident;
- IRCDMessageChgName message_chgname;
- IRCDMessageMode message_mode, message_svsmode, message_svs2mode;
- IRCDMessageNetInfo message_netinfo;
- IRCDMessageNick message_nick;
- IRCDMessagePong message_pong;
- IRCDMessageSASL message_sasl;
- IRCDMessageSDesc message_sdesc;
- IRCDMessageSetHost message_sethost;
- IRCDMessageSetIdent message_setident;
- IRCDMessageSetName message_setname;
- IRCDMessageServer message_server;
- IRCDMessageSJoin message_sjoin;
- IRCDMessageTopic message_topic;
- IRCDMessageUmode2 message_umode2;
-
- bool use_server_side_mlock;
-
- void AddModes()
- {
- ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0));
- ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1));
- ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 2));
- /* Unreal sends +q as * and +a as ~ */
- ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '~', 3));
- ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '*', 4));
-
- /* Add user modes */
- ModeManager::AddUserMode(new UserModeOperOnly("SERV_ADMIN", 'A'));
- ModeManager::AddUserMode(new UserMode("BOT", 'B'));
- ModeManager::AddUserMode(new UserModeOperOnly("CO_ADMIN", 'C'));
- ModeManager::AddUserMode(new UserMode("CENSOR", 'G'));
- ModeManager::AddUserMode(new UserModeOperOnly("HIDEOPER", 'H'));
- ModeManager::AddUserMode(new UserModeOperOnly("HIDEIDLE", 'I'));
- ModeManager::AddUserMode(new UserModeOperOnly("NETADMIN", 'N'));
- ModeManager::AddUserMode(new UserMode("REGPRIV", 'R'));
- ModeManager::AddUserMode(new UserModeOperOnly("PROTECTED", 'S'));
- ModeManager::AddUserMode(new UserMode("NOCTCP", 'T'));
- ModeManager::AddUserMode(new UserMode("WEBTV", 'V'));
- ModeManager::AddUserMode(new UserModeOperOnly("WHOIS", 'W'));
- ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a'));
- ModeManager::AddUserMode(new UserMode("DEAF", 'd'));
- ModeManager::AddUserMode(new UserModeOperOnly("GLOBOPS", 'g'));
- ModeManager::AddUserMode(new UserModeOperOnly("HELPOP", 'h'));
- ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
- ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o'));
- ModeManager::AddUserMode(new UserMode("PRIV", 'p'));
- ModeManager::AddUserMode(new UserModeOperOnly("GOD", 'q'));
- ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r'));
- ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's'));
- ModeManager::AddUserMode(new UserModeNoone("VHOST", 't'));
- ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
- ModeManager::AddUserMode(new UserMode("CLOAK", 'x'));
- ModeManager::AddUserMode(new UserModeNoone("SSL", 'z'));
- }
-
- public:
- ProtoUnreal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
- ircd_proto(this),
- message_away(this), message_error(this), message_invite(this), message_join(this), message_kick(this),
- message_kill(this), message_svskill(this, "SVSKILL"), message_motd(this), message_notice(this), message_part(this), message_ping(this),
- message_privmsg(this), message_quit(this), message_squit(this), message_stats(this), message_time(this),
- message_version(this), message_whois(this),
-
- message_capab(this), message_chghost(this), message_chgident(this), message_chgname(this), message_mode(this, "MODE"),
- message_svsmode(this, "SVSMODE"), message_svs2mode(this, "SVS2MODE"), message_netinfo(this), message_nick(this), message_pong(this),
- message_sasl(this), message_sdesc(this), message_sethost(this), message_setident(this), message_setname(this), message_server(this),
- message_sjoin(this), message_topic(this), message_umode2(this)
- {
-
- this->AddModes();
- }
-
- void Prioritize() anope_override
- {
- ModuleManager::SetPriority(this, PRIORITY_FIRST);
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- }
-
- void OnUserNickChange(User *u, const Anope::string &) anope_override
- {
- u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
- if (Servers::Capab.count("ESVID") == 0)
- IRCD->SendLogout(u);
- }
-
- void OnChannelSync(Channel *c) anope_override
- {
- if (!c->ci)
- return;
-
- ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
- if (use_server_side_mlock && Servers::Capab.count("MLOCK") > 0 && modelocks)
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(c->creation_time) << " " << c->ci->name << " " << modes;
- }
- }
-
- void OnChanRegistered(ChannelInfo *ci) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- if (!ci->c || !use_server_side_mlock || !modelocks || !Servers::Capab.count("MLOCK"))
- return;
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
- }
-
- void OnDelChan(ChannelInfo *ci) anope_override
- {
- if (!ci->c || !use_server_side_mlock || !Servers::Capab.count("MLOCK"))
- return;
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " :";
- }
-
- EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
- }
-
- return EVENT_CONTINUE;
- }
-
- EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
- {
- ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
- {
- Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
- }
-
- return EVENT_CONTINUE;
- }
-};
-
-MODULE_INIT(ProtoUnreal)
diff --git a/modules/protocol/unreal4.cpp b/modules/protocol/unrealircd.cpp
index e3b235f97..aed578c3e 100644
--- a/modules/protocol/unreal4.cpp
+++ b/modules/protocol/unrealircd.cpp
@@ -1,4 +1,4 @@
-/* Unreal IRCD 4 functions
+/* UnrealIRCd functions
*
* (C) 2003-2025 Anope Team
* Contact us at team@anope.org
@@ -14,19 +14,42 @@
#include "modules/sasl.h"
typedef Anope::map<Anope::string> ModData;
-static Anope::string UplinkSID;
-class UnrealIRCdProto : public IRCDProto
+namespace
{
- public:
+ Anope::string UplinkSID;
+
+ bool IsExtBan(const Anope::string &str, Anope::string &name, Anope::string &value)
+ {
+ if (str[0] != '~')
+ return false;
+
+ auto endpos = str.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 1);
+ if (endpos == Anope::string::npos || str[endpos] != ':' || endpos+1 == str.length())
+ return false;
+
+ name = str.substr(1, endpos - 1);
+ value = str.substr(endpos + 1);
+ return true;
+ }
+}
+
+class UnrealIRCdProto final
+ : public IRCDProto
+{
+public:
PrimitiveExtensibleItem<ModData> ClientModData;
PrimitiveExtensibleItem<ModData> ChannelModData;
- UnrealIRCdProto(Module *creator) : IRCDProto(creator, "UnrealIRCd 4+"), ClientModData(creator, "ClientModData"), ChannelModData(creator, "ChannelModData")
+ UnrealIRCdProto(Module *creator)
+ : IRCDProto(creator, "UnrealIRCd 6+")
+ , ClientModData(creator, "ClientModData")
+ , ChannelModData(creator, "ChannelModData")
{
DefaultPseudoclientModes = "+BioqS";
CanSVSNick = true;
CanSVSJoin = true;
+ CanSVSNOOP = true;
CanSetVHost = true;
CanSetVIdent = true;
CanSNLine = true;
@@ -34,19 +57,21 @@ class UnrealIRCdProto : public IRCDProto
CanSQLineChannel = true;
CanSZLine = true;
CanSVSHold = true;
+ CanClearBans = true;
CanCertFP = true;
+ CanTagMessage = true;
RequiresID = true;
MaxModes = 12;
}
- private:
+private:
/* SVSNOOP */
- void SendSVSNOOP(const Server *server, bool set) anope_override
+ void SendSVSNOOP(const Server *server, bool set) override
{
- UplinkSocket::Message() << "SVSNOOP " << server->GetSID() << " " << (set ? "+" : "-");
+ Uplink::Send("SVSNOOP", server->GetSID(), set ? '+' : '-');
}
- void SendAkillDel(const XLine *x) anope_override
+ void SendAkillDel(const XLine *x) override
{
if (x->IsRegex() || x->HasNickOrReal())
return;
@@ -62,40 +87,40 @@ class UnrealIRCdProto : public IRCDProto
}
}
- UplinkSocket::Message() << "TKL - G " << x->GetUser() << " " << x->GetHost() << " " << x->by;
+ Uplink::Send("TKL", '-', 'G', x->GetUser(), x->GetHost(), x->by);
}
- void SendTopic(const MessageSource &source, Channel *c) anope_override
+ void SendTopic(const MessageSource &source, Channel *c) override
{
- UplinkSocket::Message(source) << "TOPIC " << c->name << " " << c->topic_setter << " " << c->topic_ts << " :" << c->topic;
+ Uplink::Send(source, "TOPIC", c->name, c->topic_setter, c->topic_ts, c->topic);
}
- void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "NOTICE", "$" + dest->GetName(), msg);
}
- void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
+ void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) override
{
- UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
+ Uplink::Send(bi, "PRIVMSG", "$" + dest->GetName(), msg);
}
- void SendVhostDel(User *u) anope_override
+ void SendVHostDel(User *u) override
{
BotInfo *HostServ = Config->GetClient("HostServ");
u->RemoveMode(HostServ, "VHOST");
}
- void SendAkill(User *u, XLine *x) anope_override
+ void SendAkill(User *u, XLine *x) override
{
if (x->IsRegex() || x->HasNickOrReal())
{
if (!u)
{
/* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- if (x->manager->Check(it->second, x))
- this->SendAkill(it->second, x);
+ for (const auto &[_, user] : UserListByNick)
+ if (x->manager->Check(user, x))
+ this->SendAkill(user, x);
return;
}
@@ -105,7 +130,7 @@ class UnrealIRCdProto : public IRCDProto
return;
/* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
- XLine *xline = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
+ auto *xline = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
old->manager->AddXLine(xline);
x = xline;
@@ -123,45 +148,40 @@ class UnrealIRCdProto : public IRCDProto
}
}
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- UplinkSocket::Message() << "TKL + G " << x->GetUser() << " " << x->GetHost() << " " << x->by << " " << Anope::CurTime + timeleft << " " << x->created << " :" << x->GetReason();
+ Uplink::Send("TKL", '+', 'G', x->GetUser(), x->GetHost(), x->by, x->expires, x->created, x->GetReason());
}
- void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override
+ void SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf) override
{
- UplinkSocket::Message(source) << "SVSKILL " << user->GetUID() << " :" << buf;
+ Uplink::Send(source, "SVSKILL", user->GetUID(), buf);
user->KillInternal(source, buf);
}
- void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override
+ void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values) override
{
- UplinkSocket::Message(source) << "SVS2MODE " << u->GetUID() <<" " << buf;
- }
+ auto params = values;
+ params.insert(params.begin(), { u->GetUID(), modes });
+ Uplink::SendInternal({}, source, "SVS2MODE", params);
+}
- void SendClientIntroduction(User *u) anope_override
+ void SendClientIntroduction(User *u) override
{
- Anope::string modes = "+" + u->GetModes();
- UplinkSocket::Message(u->server) << "UID " << u->nick << " 1 " << u->timestamp << " " << u->GetIdent() << " " << u->host << " "
- << u->GetUID() << " * " << modes << " " << (!u->vhost.empty() ? u->vhost : "*") << " "
- << (!u->chost.empty() ? u->chost : "*") << " " << "*" << " :" << u->realname;
+ Uplink::Send(u->server, "UID", u->nick, 1, u->timestamp, u->GetIdent(), u->host, u->GetUID(), '*', "+" + u->GetModes(),
+ u->vhost.empty() ? "*" : u->vhost, u->chost.empty() ? "*" : u->chost, "*", u->realname);
}
- void SendServer(const Server *server) anope_override
+ void SendServer(const Server *server) override
{
if (server == Me)
- UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() + 1 << " :" << server->GetDescription();
+ Uplink::Send("SERVER", server->GetName(), server->GetHops() + 1, server->GetDescription());
else
- UplinkSocket::Message(Me) << "SID " << server->GetName() << " " << server->GetHops() + 1 << " " << server->GetSID() << " :" << server->GetDescription();
+ Uplink::Send("SID", server->GetName(), server->GetHops() + 1, server->GetSID(), server->GetDescription());
}
/* JOIN */
- void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) override
{
- UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name
- << " +" << c->GetModes(true, true) << " :" << user->GetUID();
+ Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), user->GetUID());
if (status)
{
/* First save the channel status incase uc->Status == status */
@@ -174,8 +194,8 @@ class UnrealIRCdProto : public IRCDProto
uc->status.Clear();
BotInfo *setter = BotInfo::Find(user->GetUID());
- for (size_t i = 0; i < cs.Modes().length(); ++i)
- c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false);
+ for (auto mode : cs.Modes())
+ c->SetMode(setter, ModeManager::FindChannelModeByChar(mode), user->GetUID(), false);
if (uc != NULL)
uc->status = cs;
@@ -184,9 +204,9 @@ class UnrealIRCdProto : public IRCDProto
/* unsqline
*/
- void SendSQLineDel(const XLine *x) anope_override
+ void SendSQLineDel(const XLine *x) override
{
- UplinkSocket::Message() << "UNSQLINE " << x->mask;
+ Uplink::Send("UNSQLINE", x->mask);
}
/* SQLINE */
@@ -194,101 +214,96 @@ class UnrealIRCdProto : public IRCDProto
** - Unreal will translate this to TKL for us
**
*/
- void SendSQLine(User *, const XLine *x) anope_override
+ void SendSQLine(User *, const XLine *x) override
{
- UplinkSocket::Message() << "TKL + Q * " << x->mask << " " << x->by << " " << x->expires << " " << x->created << " :" << x->GetReason();
+ Uplink::Send("TKL", '+', 'Q', "*", x->mask, x->by, x->expires, x->created, x->GetReason());
}
/* Functions that use serval cmd functions */
- void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
+ void SendVHost(User *u, const Anope::string &vident, const Anope::string &vhost) override
{
- if (!vIdent.empty())
- UplinkSocket::Message(Me) << "CHGIDENT " << u->GetUID() << " " << vIdent;
+ if (!vident.empty())
+ Uplink::Send("CHGIDENT", u->GetUID(), vident);
+
if (!vhost.empty())
- UplinkSocket::Message(Me) << "CHGHOST " << u->GetUID() << " " << vhost;
+ Uplink::Send("CHGHOST", u->GetUID(), vhost);
+
// Internally unreal sets +xt on chghost
BotInfo *bi = Config->GetClient("HostServ");
u->SetMode(bi, "CLOAK");
u->SetMode(bi, "VHOST");
}
- void SendConnect() anope_override
- {
- /*
- NICKv2 = Nick Version 2
- VHP = Sends hidden host
- UMODE2 = sends UMODE2 on user modes
- NICKIP = Sends IP on NICK
- SJ3 = Supports SJOIN
- NOQUIT = No Quit
- TKLEXT = Extended TKL we don't use it but best to have it
- MLOCK = Supports the MLOCK server command
- VL = Version Info
- SID = SID/UID mode
- */
- UplinkSocket::Message() << "PASS :" << Config->Uplinks[Anope::CurrentUplink].password;
- UplinkSocket::Message() << "PROTOCTL " << "NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT MLOCK SID MTAGS";
- UplinkSocket::Message() << "PROTOCTL " << "EAUTH=" << Me->GetName() << ",,,Anope-" << Anope::VersionShort();
- UplinkSocket::Message() << "PROTOCTL " << "SID=" << Me->GetSID();
+ void SendConnect() override
+ {
+ Uplink::Send("PASS", Config->Uplinks[Anope::CurrentUplink].password);
+
+ // BIGLINES: enable sending lines up to 16384 characters in length.
+ // EAUTH: communicates information about the local server.
+ // MLOCK: enable receiving the MLOCK message when a mode lock changes.
+ // MTAGS: enable receiving IRCv3 message tags.
+ // NEXTBANS: enables receiving named extended bans.
+ // SID: communicates the unique identifier of the local server.
+ // VHP: enable receiving the vhost in UID.
+ Uplink::Send("PROTOCTL", "BIGLINES", "MLOCK", "MTAGS", "NEXTBANS", "VHP");
+ Uplink::Send("PROTOCTL", "EAUTH=" + Me->GetName() + ",,,Anope-" + Anope::VersionShort());
+ Uplink::Send("PROTOCTL", "SID=" + Me->GetSID());
+
SendServer(Me);
}
- void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) anope_override
+ void SendSASLMechanisms(std::vector<Anope::string> &mechanisms) override
{
Anope::string mechlist;
- for (unsigned i = 0; i < mechanisms.size(); ++i)
- mechlist += "," + mechanisms[i];
+ for (const auto &mechanism : mechanisms)
+ mechlist += "," + mechanism;
- UplinkSocket::Message() << "MD client " << Me->GetName() << " saslmechlist :" << (mechanisms.empty() ? "" : mechlist.substr(1));
+ Uplink::Send("MD", "client", Me->GetName(), "saslmechlist", mechanisms.empty() ? "" : mechlist.substr(1));
}
/* SVSHOLD - set */
- void SendSVSHold(const Anope::string &nick, time_t t) anope_override
+ void SendSVSHold(const Anope::string &nick, time_t t) override
{
- UplinkSocket::Message() << "TKL + Q H " << nick << " " << Me->GetName() << " " << Anope::CurTime + t << " " << Anope::CurTime << " :Being held for registered user";
+ Uplink::Send("TKL", '+', 'Q', 'H', nick, Me->GetName(), Anope::CurTime + t, Anope::CurTime, "Being held for a registered user");
}
/* SVSHOLD - release */
- void SendSVSHoldDel(const Anope::string &nick) anope_override
+ void SendSVSHoldDel(const Anope::string &nick) override
{
- UplinkSocket::Message() << "TKL - Q * " << nick << " " << Me->GetName();
+ Uplink::Send("TKL", '-', 'Q', '*', nick, Me->GetName());
}
/* UNSGLINE */
/*
* SVSNLINE - :realname mask
*/
- void SendSGLineDel(const XLine *x) anope_override
+ void SendSGLineDel(const XLine *x) override
{
- UplinkSocket::Message() << "SVSNLINE - :" << x->mask;
+ Uplink::Send("SVSNLINE", '-', x->mask);
}
/* UNSZLINE */
- void SendSZLineDel(const XLine *x) anope_override
+ void SendSZLineDel(const XLine *x) override
{
- UplinkSocket::Message() << "TKL - Z * " << x->GetHost() << " " << x->by;
+ Uplink::Send("TKL", '-', 'Z', '*', x->GetHost(), x->by);
}
/* SZLINE */
- void SendSZLine(User *, const XLine *x) anope_override
+ void SendSZLine(User *, const XLine *x) override
{
- // Calculate the time left before this would expire, capping it at 2 days
- time_t timeleft = x->expires - Anope::CurTime;
- if (timeleft > 172800 || !x->expires)
- timeleft = 172800;
- UplinkSocket::Message() << "TKL + Z * " << x->GetHost() << " " << x->by << " " << Anope::CurTime + timeleft << " " << x->created << " :" << x->GetReason();
+ Uplink::Send("TKL", '+', 'Z', '*', x->GetHost(), x->by, x->expires, x->created, x->GetReason());
}
/* SGLINE */
/*
* SVSNLINE + reason_where_is_space :realname mask with spaces
*/
- void SendSGLine(User *, const XLine *x) anope_override
+ void SendSGLine(User *, const XLine *x) override
{
Anope::string edited_reason = x->GetReason();
edited_reason = edited_reason.replace_all_cs(" ", "_");
- UplinkSocket::Message() << "SVSNLINE + " << edited_reason << " :" << x->mask;
+ Uplink::Send("SVSNLINE", '+', edited_reason, x->mask);
}
/* svsjoin
@@ -300,38 +315,38 @@ class UnrealIRCdProto : public IRCDProto
/* In older Unreal SVSJOIN and SVSNLINE tokens were mixed so SVSJOIN and SVSNLINE are broken
when coming from a none TOKEN'd server
*/
- void SendSVSJoin(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) anope_override
+ void SendSVSJoin(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &key) override
{
- if (!param.empty())
- UplinkSocket::Message() << "SVSJOIN " << user->GetUID() << " " << chan << " :" << param;
+ if (key.empty())
+ Uplink::Send("SVSJOIN", user->GetUID(), chan);
else
- UplinkSocket::Message() << "SVSJOIN " << user->GetUID() << " " << chan;
+ Uplink::Send("SVSJOIN", user->GetUID(), chan, key);
}
- void SendSVSPart(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) anope_override
+ void SendSVSPart(const MessageSource &source, User *user, const Anope::string &chan, const Anope::string &param) override
{
if (!param.empty())
- UplinkSocket::Message() << "SVSPART " << user->GetUID() << " " << chan << " :" << param;
+ Uplink::Send("SVSPART", user->GetUID(), chan, param);
else
- UplinkSocket::Message() << "SVSPART " << user->GetUID() << " " << chan;
+ Uplink::Send("SVSPART", user->GetUID(), chan);
}
- void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override
+ void SendGlobops(const MessageSource &source, const Anope::string &buf) override
{
- UplinkSocket::Message(Me) << "SENDUMODE o :from " << source.GetName() << ": " << buf;
+ Uplink::Send("SENDUMODE", 'o', "From " + source.GetName() + ": " + buf);
}
- void SendSWhois(const MessageSource &source, const Anope::string &who, const Anope::string &mask) anope_override
+ void SendSWhois(const MessageSource &source, const Anope::string &who, const Anope::string &mask) override
{
- UplinkSocket::Message() << "SWHOIS " << who << " :" << mask;
+ Uplink::Send("SWHOIS", who, mask);
}
- void SendEOB() anope_override
+ void SendEOB() override
{
- UplinkSocket::Message(Me) << "EOS";
+ Uplink::Send("EOS");
}
- bool IsNickValid(const Anope::string &nick) anope_override
+ bool IsNickValid(const Anope::string &nick) override
{
if (nick.equals_ci("ircd") || nick.equals_ci("irc"))
return false;
@@ -339,7 +354,7 @@ class UnrealIRCdProto : public IRCDProto
return IRCDProto::IsNickValid(nick);
}
- bool IsChannelValid(const Anope::string &chan) anope_override
+ bool IsChannelValid(const Anope::string &chan) override
{
if (chan.find(':') != Anope::string::npos)
return false;
@@ -347,32 +362,29 @@ class UnrealIRCdProto : public IRCDProto
return IRCDProto::IsChannelValid(chan);
}
- bool IsExtbanValid(const Anope::string &mask) anope_override
+ bool IsExtbanValid(const Anope::string &mask) override
{
- return mask.length() >= 4 && mask[0] == '~' && mask[2] == ':';
+ Anope::string name, value;
+ return IsExtBan(mask, name, value);
}
- void SendLogin(User *u, NickAlias *na) anope_override
+ void SendLogin(User *u, NickAlias *na) override
{
- /* 3.2.10.4+ treats users logged in with accounts as fully registered, even if -r, so we can not set this here. Just use the timestamp. */
- if (Servers::Capab.count("ESVID") > 0 && !na->nc->HasExt("UNCONFIRMED"))
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %s", na->nc->display.c_str());
- else
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %d", u->signon);
+ if (!na->nc->HasExt("UNCONFIRMED"))
+ IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", na->nc->display);
}
- void SendLogout(User *u) anope_override
+ void SendLogout(User *u) override
{
- IRCD->SendMode(Config->GetClient("NickServ"), u, "+d 0");
+ IRCD->SendMode(Config->GetClient("NickServ"), u, "+d", 0);
}
- void SendChannel(Channel *c) anope_override
+ void SendChannel(Channel *c) override
{
- UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name
- << " +" << c->GetModes(true, true) << " :";
+ Uplink::Send("SJOIN", c->creation_time, c->name, "+" + c->GetModes(true, true), "");
}
- void SendSASLMessage(const SASL::Message &message) anope_override
+ void SendSASLMessage(const SASL::Message &message) override
{
size_t p = message.target.find('!');
Anope::string distmask;
@@ -389,10 +401,12 @@ class UnrealIRCdProto : public IRCDProto
distmask = message.target.substr(0, p);
}
- UplinkSocket::Message(BotInfo::Find(message.source)) << "SASL " << distmask << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : " " + message.ext);
+ auto newparams = message.data;
+ newparams.insert(newparams.begin(), { distmask, message.target, message.type });
+ Uplink::SendInternal({}, BotInfo::Find(message.source), "SASL", newparams);
}
- void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override
+ void SendSVSLogin(const Anope::string &uid, NickAlias *na) override
{
size_t p = uid.find('!');
Anope::string distmask;
@@ -409,22 +423,25 @@ class UnrealIRCdProto : public IRCDProto
distmask = uid.substr(0, p);
}
- if (!vident.empty())
- UplinkSocket::Message(Me) << "CHGIDENT " << uid << " " << vident;
- if (!vhost.empty())
- UplinkSocket::Message(Me) << "CHGHOST " << uid << " " << vhost;
- UplinkSocket::Message(Me) << "SVSLOGIN " << distmask << " " << uid << " " << acc;
+ if (na)
+ {
+ if (!na->GetVHostIdent().empty())
+ Uplink::Send("CHGIDENT", uid, na->GetVHostIdent());
+
+ if (!na->GetVHostHost().empty())
+ Uplink::Send("CHGHOST", uid, na->GetVHostHost());
+ }
+
+ Uplink::Send("SVSLOGIN", distmask, uid, na ? na->nc->display : "0");
}
- bool IsIdentValid(const Anope::string &ident) anope_override
+ bool IsIdentValid(const Anope::string &ident) override
{
- if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
+ if (ident.empty() || ident.length() > IRCD->MaxUser)
return false;
- for (unsigned i = 0; i < ident.length(); ++i)
+ for (auto c : ident)
{
- const char &c = ident[i];
-
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
continue;
@@ -436,48 +453,73 @@ class UnrealIRCdProto : public IRCDProto
return true;
}
-};
-
-class UnrealExtBan : public ChannelModeVirtual<ChannelModeList>
-{
- char ext;
-
- public:
- UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
- , ext(extban)
- {
- }
- ChannelMode *Wrap(Anope::string &param) anope_override
+ void SendClearBans(const MessageSource &user, Channel *c, User* u) override
{
- param = "~" + Anope::string(ext) + ":" + param;
- return ChannelModeVirtual<ChannelModeList>::Wrap(param);
+ Uplink::Send(user, "SVS2MODE", c->name, "-b", u->GetUID());
}
- ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) anope_override
+ bool IsTagValid(const Anope::string &tname, const Anope::string &tvalue) override
{
- if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':')
- return cm;
-
- param = param.substr(3);
- return this;
+ return !!Servers::Capab.count("MTAGS");
}
};
-namespace UnrealExtban
+namespace UnrealExtBan
{
- class ChannelMatcher : public UnrealExtBan
- {
- public:
- ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ class Base
+ : public ChannelModeVirtual<ChannelModeList>
+ {
+ private:
+ char xbchar;
+ Anope::string xbname;
+
+ public:
+ Base(const Anope::string &mname, const Anope::string& uname, char uchar)
+ : ChannelModeVirtual<ChannelModeList>(mname, "BAN")
+ , xbchar(uchar)
+ , xbname(uname)
{
}
- bool Matches(User *u, const Entry *e) anope_override
+ ChannelMode *Wrap(Anope::string &param) override
{
- const Anope::string &mask = e->GetMask();
- Anope::string channel = mask.substr(3);
+ auto prefix = Servers::Capab.count("NEXTBANS") ? xbname : Anope::string(xbchar);
+ param = Anope::printf("~%s:%s", prefix.c_str(), param.c_str());
+ return ChannelModeVirtual<ChannelModeList>::Wrap(param);
+ }
+
+ ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) override
+ {
+ // The mask must be in the format ~<letter>:<value> or ~<name>:<value>.
+ if (cm->type != MODE_LIST)
+ return cm;
+
+ Anope::string name, value;
+ if (!IsExtBan(param, name, value))
+ return cm;
+ if (name.length() == 1 ? name[0] != xbchar : name != xbname)
+ return cm;
+
+ param = value;
+ return this;
+
+ }
+ };
+
+ class ChannelMatcher final
+ : public Base
+ {
+ public:
+ ChannelMatcher()
+ : Base("CHANNELBAN", "channel", 'c')
+ {
+ }
+
+ bool Matches(User *u, const Entry *e) override
+ {
+ auto channel = e->GetMask();
ChannelMode *cm = NULL;
if (channel[0] != '#')
{
@@ -501,130 +543,114 @@ namespace UnrealExtban
}
};
- class EntryMatcher : public UnrealExtBan
- {
- public:
- EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
- {
- }
-
- bool Matches(User *u, const Entry *e) anope_override
- {
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
-
- return Entry(this->name, real_mask).Matches(u);
- }
- };
-
- class RealnameMatcher : public UnrealExtBan
+ class EntryMatcher final
+ : public Base
{
- public:
- RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ EntryMatcher(const Anope::string &mname, const Anope::string &uname, char uchar)
+ : Base(mname, uname, uchar)
{
}
- bool Matches(User *u, const Entry *e) anope_override
+ bool Matches(User *u, const Entry *e) override
{
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
-
- return Anope::Match(u->realname, real_mask);
+ return Entry(this->base, e->GetMask()).Matches(u);
}
};
- class RegisteredMatcher : public UnrealExtBan
+ class RealnameMatcher final
+ : public Base
{
- public:
- RegisteredMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ RealnameMatcher()
+ : Base("REALNAMEBAN", "realname", 'r')
{
}
- bool Matches(User *u, const Entry *e) anope_override
+ bool Matches(User *u, const Entry *e) override
{
- const Anope::string &mask = e->GetMask();
- return u->HasMode("REGISTERED") && mask.equals_ci(u->nick);
+ return Anope::Match(u->realname, e->GetMask());
}
};
- class AccountMatcher : public UnrealExtBan
+ class AccountMatcher final
+ : public Base
{
- public:
- AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ AccountMatcher()
+ : Base("ACCOUNTBAN", "account", 'a')
{
}
- bool Matches(User *u, const Entry *e) anope_override
+ bool Matches(User *u, const Entry *e) override
{
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
-
- if (real_mask == "0" && !u->IsIdentified()) /* ~a:0 is special and matches all unauthenticated users */
+ if (e->GetMask() == "0" && !u->Account()) /* ~a:0 is special and matches all unauthenticated users */
return true;
- return u->IsIdentified() && Anope::Match(u->Account()->display, real_mask);
+ return u->IsIdentified() && Anope::Match(u->Account()->display, e->GetMask());
}
};
- class FingerprintMatcher : public UnrealExtBan
+ class FingerprintMatcher final
+ : public Base
{
- public:
- FingerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ FingerprintMatcher()
+ : Base("SSLBAN", "certfp", 'S')
{
}
- bool Matches(User *u, const Entry *e) anope_override
+ bool Matches(User *u, const Entry *e) override
{
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
- return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
+ return !u->fingerprint.empty() && Anope::Match(u->fingerprint, e->GetMask());
}
};
-
- class OperclassMatcher : public UnrealExtBan
+
+ class OperclassMatcher final
+ : public Base
{
- public:
- OperclassMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ OperclassMatcher()
+ : Base("OPERCLASSBAN", "operclass", 'O')
{
}
-
- bool Matches(User *u, const Entry *e) anope_override
+
+ bool Matches(User *u, const Entry *e) override
{
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
ModData *moddata = u->GetExt<ModData>("ClientModData");
- return moddata != NULL && moddata->find("operclass") != moddata->end() && Anope::Match((*moddata)["operclass"], real_mask);
+ return moddata != NULL && moddata->find("operclass") != moddata->end() && Anope::Match((*moddata)["operclass"], e->GetMask());
}
};
-
- class TimedBanMatcher : public UnrealExtBan
+
+ class TimedBanMatcher final
+ : public Base
{
- public:
- TimedBanMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ TimedBanMatcher()
+ : Base("TIMEDBAN", "time", 't')
{
}
-
- bool Matches(User *u, const Entry *e) anope_override
+
+ bool Matches(User *u, const Entry *e) override
{
/* strip down the time (~t:1234:) and call other matchers */
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
+ auto real_mask = e->GetMask();
real_mask = real_mask.substr(real_mask.find(":") + 1);
return Entry("BAN", real_mask).Matches(u);
}
};
- class CountryMatcher : public UnrealExtBan
+ class CountryMatcher final
+ : public Base
{
- public:
- CountryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
+ public:
+ CountryMatcher()
+ : Base("COUNTRYBAN", "country", 'C')
{
}
-
- bool Matches(User *u, const Entry *e) anope_override
+
+ bool Matches(User *u, const Entry *e) override
{
- const Anope::string &mask = e->GetMask();
- Anope::string real_mask = mask.substr(3);
ModData *moddata = u->GetExt<ModData>("ClientModData");
if (moddata == NULL || moddata->find("geoip") == moddata->end())
return false;
@@ -634,39 +660,34 @@ namespace UnrealExtban
while (sep.GetToken(tokenbuf))
{
if (tokenbuf.rfind("cc=", 0) == 0)
- return (tokenbuf.substr(3, 2) == real_mask);
+ return (tokenbuf.substr(3, 2) == e->GetMask());
}
return false;
}
};
-
}
-class ChannelModeFlood : public ChannelModeParam
+class ChannelModeFlood final
+ : public ChannelModeParam
{
- public:
+public:
ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
/* Borrowed part of this check from UnrealIRCd */
- bool IsValid(Anope::string &value) const anope_override
+ bool IsValid(Anope::string &value) const override
{
- if (value.empty())
+ if (value.empty() || value[0] != '[')
return false;
- try
- {
- Anope::string rest;
- if (value[0] != ':' && convertTo<unsigned>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<unsigned>(rest.substr(1), rest, false) > 0 && rest.empty())
- return true;
- }
- catch (const ConvertException &) { }
/* '['<number><1 letter>[optional: '#'+1 letter],[next..]']'':'<number> */
size_t end_bracket = value.find(']', 1);
if (end_bracket == Anope::string::npos)
return false;
+
Anope::string xbuf = value.substr(0, end_bracket);
if (value[end_bracket + 1] != ':')
return false;
+
commasepstream args(xbuf.substr(1));
Anope::string arg;
while (args.GetToken(arg))
@@ -675,30 +696,25 @@ class ChannelModeFlood : public ChannelModeParam
size_t p = 0;
while (p < arg.length() && isdigit(arg[p]))
++p;
- if (p == arg.length() || !(arg[p] == 'c' || arg[p] == 'j' || arg[p] == 'k' || arg[p] == 'm' || arg[p] == 'n' || arg[p] == 't'))
+ if (p == arg.length() || (arg[p] != 'c' && arg[p] != 'j' && arg[p] != 'k' && arg[p] != 'm' && arg[p] != 'n' && arg[p] != 't'))
continue; /* continue instead of break for forward compatibility. */
- try
- {
- int v = arg.substr(0, p).is_number_only() ? convertTo<int>(arg.substr(0, p)) : 0;
- if (v < 1 || v > 999)
- return false;
- }
- catch (const ConvertException &)
- {
+
+ auto v = Anope::Convert<int>(arg.substr(0, p), 0);
+ if (v < 1 || v > 999)
return false;
- }
}
return true;
}
};
-class ChannelModeHistory : public ChannelModeParam /* stolen from inspircd3's ColonDelimitedParamMode */
+class ChannelModeHistory final
+ : public ChannelModeParam
{
- public:
+public:
ChannelModeHistory(char modeChar) : ChannelModeParam("HISTORY", modeChar, true) { }
- bool IsValid(Anope::string &value) const anope_override
+ bool IsValid(Anope::string &value) const override
{
if (value.empty())
return false; // empty param is never valid
@@ -708,59 +724,45 @@ class ChannelModeHistory : public ChannelModeParam /* stolen from inspircd3's Co
return false; // no ':' or it's the first char, both are invalid
Anope::string rest;
- try
- {
- if (convertTo<int>(value, rest, false) <= 0)
- return false; // negative numbers and zero are invalid
+ if (Anope::Convert<int>(value, 0, &rest) <= 0)
+ return false; // negative numbers and zero are invalid
- rest = rest.substr(1);
- int n;
- // The part after the ':' is a duration and it
- // can be in the user friendly "1d3h20m" format, make sure we accept that
- n = Anope::DoTime(rest);
-
- if (n <= 0)
- return false;
- }
- catch (const ConvertException &e)
- {
- // conversion error, invalid
- return false;
- }
-
- return true;
+ // The part after the ':' is a duration and it
+ // can be in the user friendly "1d3h20m" format, make sure we accept that
+ auto n = Anope::DoTime(rest.substr(1));
+ return n > 0;
}
};
-class ChannelModeUnrealSSL : public ChannelMode
+class ChannelModeUnrealSSL final
+ : public ChannelMode
{
- public:
+public:
ChannelModeUnrealSSL(const Anope::string &n, char c) : ChannelMode(n, c)
{
}
- bool CanSet(User *u) const anope_override
+ bool CanSet(User *u) const override
{
return false;
}
};
-struct IRCDMessageCapab : Message::Capab
+struct IRCDMessageCapab final
+ : Message::Capab
{
IRCDMessageCapab(Module *creator) : Message::Capab(creator, "PROTOCTL") { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- for (unsigned i = 0; i < params.size(); ++i)
+ for (const auto &capab : params)
{
- Anope::string capab = params[i];
-
if (capab.find("USERMODES=") != Anope::string::npos)
{
Anope::string modebuf(capab.begin() + 10, capab.end());
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
+ for (auto mode : modebuf)
{
- switch (modebuf[t])
+ switch (mode)
{
case 'B':
ModeManager::AddUserMode(new UserMode("BOT", 'B'));
@@ -826,7 +828,7 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddUserMode(new UserMode("SSLPRIV", 'Z'));
continue;
default:
- ModeManager::AddUserMode(new UserMode("", modebuf[t]));
+ ModeManager::AddUserMode(new UserMode("", mode));
}
}
}
@@ -837,24 +839,23 @@ struct IRCDMessageCapab : Message::Capab
Anope::string modebuf;
sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
+ for (auto mode : modebuf)
{
- switch (modebuf[t])
+ switch (mode)
{
case 'b':
ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
- ModeManager::AddChannelMode(new UnrealExtban::ChannelMatcher("CHANNELBAN", "BAN", 'c'));
- ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("JOINBAN", "BAN", 'j'));
- ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("NONICKBAN", "BAN", 'n'));
- ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("QUIET", "BAN", 'q'));
- ModeManager::AddChannelMode(new UnrealExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
- ModeManager::AddChannelMode(new UnrealExtban::RegisteredMatcher("REGISTEREDBAN", "BAN", 'R'));
- ModeManager::AddChannelMode(new UnrealExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'a'));
- ModeManager::AddChannelMode(new UnrealExtban::FingerprintMatcher("SSLBAN", "BAN", 'S'));
- ModeManager::AddChannelMode(new UnrealExtban::TimedBanMatcher("TIMEDBAN", "BAN", 't'));
- ModeManager::AddChannelMode(new UnrealExtban::OperclassMatcher("OPERCLASSBAN", "BAN", 'O'));
- ModeManager::AddChannelMode(new UnrealExtban::CountryMatcher("COUNTRYBAN", "BAN", 'C'));
+ ModeManager::AddChannelMode(new UnrealExtBan::ChannelMatcher());
+ ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("JOINBAN", "join", 'j'));
+ ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("NONICKBAN", "nickchange", 'n'));
+ ModeManager::AddChannelMode(new UnrealExtBan::EntryMatcher("QUIET", "quiet", 'q'));
+ ModeManager::AddChannelMode(new UnrealExtBan::RealnameMatcher());
+ ModeManager::AddChannelMode(new UnrealExtBan::AccountMatcher());
+ ModeManager::AddChannelMode(new UnrealExtBan::FingerprintMatcher());
+ ModeManager::AddChannelMode(new UnrealExtBan::TimedBanMatcher());
+ ModeManager::AddChannelMode(new UnrealExtBan::OperclassMatcher());
+ ModeManager::AddChannelMode(new UnrealExtBan::CountryMatcher());
continue;
case 'e':
ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
@@ -863,14 +864,14 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
continue;
default:
- ModeManager::AddChannelMode(new ChannelModeList("", modebuf[t]));
+ ModeManager::AddChannelMode(new ChannelModeList("", mode));
}
}
sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
+ for (auto mode : modebuf)
{
- switch (modebuf[t])
+ switch (mode)
{
case 'k':
ModeManager::AddChannelMode(new ChannelModeKey('k'));
@@ -882,14 +883,14 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L'));
continue;
default:
- ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t]));
+ ModeManager::AddChannelMode(new ChannelModeParam("", mode));
}
}
sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
+ for (auto mode : modebuf)
{
- switch (modebuf[t])
+ switch (mode)
{
case 'l':
ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
@@ -898,14 +899,14 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddChannelMode(new ChannelModeHistory('H'));
continue;
default:
- ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t], true));
+ ModeManager::AddChannelMode(new ChannelModeParam("", mode, true));
}
}
sep.GetToken(modebuf);
- for (size_t t = 0, end = modebuf.length(); t < end; ++t)
+ for (auto mode : modebuf)
{
- switch (modebuf[t])
+ switch (mode)
{
case 'p':
ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
@@ -980,7 +981,7 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddChannelMode(new ChannelModeOperOnly("PERM", 'P'));
continue;
default:
- ModeManager::AddChannelMode(new ChannelMode("", modebuf[t]));
+ ModeManager::AddChannelMode(new ChannelMode("", mode));
}
}
}
@@ -995,7 +996,7 @@ struct IRCDMessageCapab : Message::Capab
std::size_t mode_count = modes.find(')');
Anope::string mode_prefixes = modes.substr(0, mode_count);
Anope::string mode_chars = modes.substr(mode_count+1, mode_count);
-
+
for (size_t t = 0, end = mode_chars.length(); t < end; ++t)
{
Anope::string mode_name;
@@ -1024,17 +1025,20 @@ struct IRCDMessageCapab : Message::Capab
ModeManager::AddChannelMode(new ChannelModeStatus(mode_name, mode_chars[t], mode_prefixes[t], t));
}
}
+ else if (capab.equals_ci("BIGLINES"))
+ IRCD->MaxLine = 16384;
}
- Message::Capab::Run(source, params);
+ Message::Capab::Run(source, params, tags);
}
};
-struct IRCDMessageChgHost : IRCDMessage
+struct IRCDMessageChgHost final
+ : IRCDMessage
{
IRCDMessageChgHost(Module *creator) : IRCDMessage(creator, "CHGHOST", 2) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = User::Find(params[0]);
if (u)
@@ -1042,11 +1046,12 @@ struct IRCDMessageChgHost : IRCDMessage
}
};
-struct IRCDMessageChgIdent : IRCDMessage
+struct IRCDMessageChgIdent final
+ : IRCDMessage
{
IRCDMessageChgIdent(Module *creator) : IRCDMessage(creator, "CHGIDENT", 2) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = User::Find(params[0]);
if (u)
@@ -1054,11 +1059,12 @@ struct IRCDMessageChgIdent : IRCDMessage
}
};
-struct IRCDMessageChgName : IRCDMessage
+struct IRCDMessageChgName final
+ : IRCDMessage
{
IRCDMessageChgName(Module *creator) : IRCDMessage(creator, "CHGNAME", 2) { }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = User::Find(params[0]);
if (u)
@@ -1066,17 +1072,18 @@ struct IRCDMessageChgName : IRCDMessage
}
};
-struct IRCDMessageMD : IRCDMessage
+struct IRCDMessageMD final
+ : IRCDMessage
{
PrimitiveExtensibleItem<ModData> &ClientModData;
PrimitiveExtensibleItem<ModData> &ChannelModData;
IRCDMessageMD(Module *creator, PrimitiveExtensibleItem<ModData> &clmoddata, PrimitiveExtensibleItem<ModData> &chmoddata) : IRCDMessage(creator, "MD", 3), ClientModData(clmoddata), ChannelModData(chmoddata)
{
- SetFlag(IRCDMESSAGE_SOFT_LIMIT);
+ SetFlag(FLAG_SOFT_LIMIT);
}
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
const Anope::string &mdtype = params[0],
&obj = params[1],
@@ -1089,9 +1096,9 @@ struct IRCDMessageMD : IRCDMessage
if (u == NULL)
return;
-
+
ModData &clientmd = *ClientModData.Require(u);
-
+
if (value.empty())
{
clientmd.erase(var);
@@ -1115,9 +1122,9 @@ struct IRCDMessageMD : IRCDMessage
if (c == NULL)
return;
-
+
ModData &channelmd = *ChannelModData.Require(c);
-
+
if (value.empty())
{
channelmd.erase(var);
@@ -1132,37 +1139,36 @@ struct IRCDMessageMD : IRCDMessage
}
};
-struct IRCDMessageMode : IRCDMessage
+struct IRCDMessageMode final
+ : IRCDMessage
{
- IRCDMessageMode(Module *creator, const Anope::string &mname) : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ bool server_ts;
+
+ IRCDMessageMode(Module *creator, const Anope::string &mname, bool sts)
+ : IRCDMessage(creator, mname, 2)
+ , server_ts(sts)
+ {
+ SetFlag(FLAG_SOFT_LIMIT);
+ }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- bool server_source = source.GetServer() != NULL;
- Anope::string modes = params[1];
- for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i)
- modes += " " + params[i];
+ auto final_is_ts = server_ts && source.GetServer() != NULL;
+ auto last_param = params.end() - (params.size() > 3 && final_is_ts ? 1 : 0);
if (IRCD->IsChannelValid(params[0]))
{
Channel *c = Channel::Find(params[0]);
- time_t ts = 0;
-
- try
- {
- if (server_source)
- ts = convertTo<time_t>(params[params.size() - 1]);
- }
- catch (const ConvertException &) { }
+ auto ts = final_is_ts ? IRCD->ExtractTimestamp(params.back()) : 0;
if (c)
- c->SetModesInternal(source, modes, ts);
+ c->SetModesInternal(source, params[1], { params.begin() + 2, last_param }, ts);
}
else
{
User *u = User::Find(params[0]);
if (u)
- u->SetModesInternal(source, "%s", params[1].c_str());
+ u->SetModesInternal(source, params[1]);
}
}
};
@@ -1177,19 +1183,21 @@ struct IRCDMessageMode : IRCDMessage
* argv[6] = free(**)
* argv[7] = ircnet
*/
-struct IRCDMessageNetInfo : IRCDMessage
+struct IRCDMessageNetInfo final
+ : IRCDMessage
{
- IRCDMessageNetInfo(Module *creator) : IRCDMessage(creator, "NETINFO", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageNetInfo(Module *creator) : IRCDMessage(creator, "NETINFO", 8) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- UplinkSocket::Message() << "NETINFO " << MaxUserCount << " " << Anope::CurTime << " " << convertTo<int>(params[2]) << " " << params[3] << " 0 0 0 :" << params[7];
+ Uplink::Send("NETINFO", MaxUserCount, Anope::CurTime, params[2], params[3], 0, 0, 0, params[7]);
}
};
-struct IRCDMessageNick : IRCDMessage
+struct IRCDMessageNick final
+ : IRCDMessage
{
- IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(FLAG_SOFT_LIMIT); }
/*
** NICK - new
@@ -1211,7 +1219,7 @@ struct IRCDMessageNick : IRCDMessage
** parv[0] = new nickname
** parv[1] = hopcount
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (params.size() == 11)
{
@@ -1230,8 +1238,7 @@ struct IRCDMessageNick : IRCDMessage
if (vhost.equals_cs("*"))
vhost.clear();
- time_t user_ts = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime;
-
+ auto user_ts = IRCD->ExtractTimestamp(params[2]);
Server *s = Server::Find(params[5]);
if (s == NULL)
{
@@ -1245,7 +1252,7 @@ struct IRCDMessageNick : IRCDMessage
;
else if (params[6].is_pos_number_only())
{
- if (convertTo<time_t>(params[6]) == user_ts)
+ if (IRCD->ExtractTimestamp(params[6]) == user_ts)
na = NickAlias::Find(params[0]);
}
else
@@ -1273,22 +1280,24 @@ struct IRCDMessageNick : IRCDMessage
* with their server "not syncing". We now send a PING immediately when receiving a new server
* and then finish sync once we get a pong back from that server.
*/
-struct IRCDMessagePong : IRCDMessage
+struct IRCDMessagePong final
+ : IRCDMessage
{
- IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(FLAG_SOFT_LIMIT); SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (!source.GetServer()->IsSynced())
source.GetServer()->Sync(false);
}
};
-struct IRCDMessageSASL : IRCDMessage
+struct IRCDMessageSASL final
+ : IRCDMessage
{
- IRCDMessageSASL(Module *creator) : IRCDMessage(creator, "SASL", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageSASL(Module *creator) : IRCDMessage(creator, "SASL", 4) { SetFlag(FLAG_SOFT_LIMIT); SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
if (!SASL::sasl)
return;
@@ -1297,28 +1306,28 @@ struct IRCDMessageSASL : IRCDMessage
m.source = params[1];
m.target = params[0];
m.type = params[2];
- m.data = params[3];
- m.ext = params.size() > 4 ? params[4] : "";
-
+ m.data.assign(params.begin() + 3, params.end());
SASL::sasl->ProcessMessage(m);
}
};
-struct IRCDMessageSDesc : IRCDMessage
+struct IRCDMessageSDesc final
+ : IRCDMessage
{
- IRCDMessageSDesc(Module *creator) : IRCDMessage(creator, "SDESC", 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageSDesc(Module *creator) : IRCDMessage(creator, "SDESC", 1) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
source.GetServer()->SetDescription(params[0]);
}
};
-struct IRCDMessageSetHost : IRCDMessage
+struct IRCDMessageSetHost final
+ : IRCDMessage
{
- IRCDMessageSetHost(Module *creator) : IRCDMessage(creator, "SETHOST", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageSetHost(Module *creator) : IRCDMessage(creator, "SETHOST", 1) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = source.GetUser();
@@ -1330,35 +1339,38 @@ struct IRCDMessageSetHost : IRCDMessage
}
};
-struct IRCDMessageSetIdent : IRCDMessage
+struct IRCDMessageSetIdent final
+ : IRCDMessage
{
- IRCDMessageSetIdent(Module *creator) : IRCDMessage(creator, "SETIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageSetIdent(Module *creator) : IRCDMessage(creator, "SETIDENT", 1) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = source.GetUser();
u->SetVIdent(params[0]);
}
};
-struct IRCDMessageSetName : IRCDMessage
+struct IRCDMessageSetName final
+ : IRCDMessage
{
- IRCDMessageSetName(Module *creator) : IRCDMessage(creator, "SETNAME", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageSetName(Module *creator) : IRCDMessage(creator, "SETNAME", 1) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
User *u = source.GetUser();
u->SetRealname(params[0]);
}
};
-struct IRCDMessageServer : IRCDMessage
+struct IRCDMessageServer final
+ : IRCDMessage
{
- IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
+ auto hops = Anope::Convert<unsigned>(params[1], 0);
if (params[1].equals_cs("1"))
{
@@ -1374,13 +1386,14 @@ struct IRCDMessageServer : IRCDMessage
}
};
-struct IRCDMessageSID : IRCDMessage
+struct IRCDMessageSID final
+ : IRCDMessage
{
- IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 4) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
+ auto hops = Anope::Convert<unsigned>(params[1], 0);
new Server(source.GetServer(), params[0], hops, params[3], params[2]);
@@ -1401,18 +1414,20 @@ static char UnrealSjoinPrefixToModeChar(char sjoin_prefix)
}
}
-struct IRCDMessageSJoin : IRCDMessage
+struct IRCDMessageSJoin final
+ : IRCDMessage
{
- IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
+ IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 3) { SetFlag(FLAG_REQUIRE_SERVER); SetFlag(FLAG_SOFT_LIMIT); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string modes;
+ std::vector<Anope::string> modeparams;
if (params.size() >= 4)
- for (unsigned i = 2; i < params.size() - 1; ++i)
- modes += " " + params[i];
- if (!modes.empty())
- modes.erase(modes.begin());
+ {
+ modes = params[2];
+ modeparams = { params.begin() + 3, params.end() };
+ }
std::list<Anope::string> bans, excepts, invites;
std::list<Message::Join::SJoinUser> users;
@@ -1461,8 +1476,8 @@ struct IRCDMessageSJoin : IRCDMessage
}
}
- time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime;
- Message::Join::SJoin(source, params[1], ts, modes, users);
+ auto ts = IRCD->ExtractTimestamp(params[0]);
+ Message::Join::SJoin(source, params[1], ts, modes, modeparams, users);
if (!bans.empty() || !excepts.empty() || !invites.empty())
{
@@ -1476,19 +1491,56 @@ struct IRCDMessageSJoin : IRCDMessage
*invex = ModeManager::FindChannelModeByName("INVITEOVERRIDE");
if (ban)
- for (std::list<Anope::string>::iterator it = bans.begin(), it_end = bans.end(); it != it_end; ++it)
- c->SetModeInternal(source, ban, *it);
+ {
+ for (const auto &entry : bans)
+ c->SetModeInternal(source, ban, entry);
+ }
if (except)
- for (std::list<Anope::string>::iterator it = excepts.begin(), it_end = excepts.end(); it != it_end; ++it)
- c->SetModeInternal(source, except, *it);
+ {
+ for (const auto &entry : excepts)
+ c->SetModeInternal(source, except, entry);
+ }
if (invex)
- for (std::list<Anope::string>::iterator it = invites.begin(), it_end = invites.end(); it != it_end; ++it)
- c->SetModeInternal(source, invex, *it);
+ {
+ for (const auto &entry : invites)
+ c->SetModeInternal(source, invex, entry);
+ }
+ }
+ }
+};
+
+class IRCDMessageSVSLogin final
+ : IRCDMessage
+{
+public:
+ IRCDMessageSVSLogin(Module *creator) : IRCDMessage(creator, "SVSLOGIN", 3) { SetFlag(FLAG_REQUIRE_SERVER); }
+
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
+ {
+ // :irc.example.com SVSLOGIN <mask> <nick> <account>
+ // :irc.example.com SVSLOGIN <mask> <nick> 0
+ User *u = User::Find(params[1]);
+ if (!u)
+ return; // Should never happen.
+
+ if (params[2] == "0")
+ {
+ // The user has been logged out by the IRC server.
+ u->Logout();
+ }
+ else
+ {
+ // If we're bursting then then the user was probably logged
+ // in during a previous connection.
+ NickCore *nc = NickCore::Find(params[2]);
+ if (nc)
+ u->Login(nc);
}
}
};
-struct IRCDMessageTopic : IRCDMessage
+struct IRCDMessageTopic final
+ : IRCDMessage
{
IRCDMessageTopic(Module *creator) : IRCDMessage(creator, "TOPIC", 4) { }
@@ -1499,11 +1551,11 @@ struct IRCDMessageTopic : IRCDMessage
** parv[2] = topic time
** parv[3] = topic text
*/
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Channel *c = Channel::Find(params[0]);
if (c)
- c->ChangeTopicInternal(source.GetUser(), params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime);
+ c->ChangeTopicInternal(source.GetUser(), params[1], params[3], IRCD->ExtractTimestamp(params[2]));
}
};
@@ -1521,11 +1573,12 @@ struct IRCDMessageTopic : IRCDMessage
* parv[10] = ip
* parv[11] = info
*/
-struct IRCDMessageUID : IRCDMessage
+struct IRCDMessageUID final
+ : IRCDMessage
{
- IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 12) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
+ IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 12) { SetFlag(FLAG_REQUIRE_SERVER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
Anope::string
nickname = params[0],
@@ -1557,16 +1610,7 @@ struct IRCDMessageUID : IRCDMessage
if (chost == "*")
chost.clear();
- time_t user_ts;
- try
- {
- user_ts = convertTo<time_t>(timestamp);
- }
- catch (const ConvertException &)
- {
- user_ts = Anope::CurTime;
- }
-
+ auto user_ts = IRCD->ExtractTimestamp(timestamp);
NickAlias *na = NULL;
if (account == "0")
@@ -1575,7 +1619,7 @@ struct IRCDMessageUID : IRCDMessage
}
else if (account.is_pos_number_only())
{
- if (convertTo<time_t>(account) == user_ts)
+ if (IRCD->ExtractTimestamp(account) == user_ts)
na = NickAlias::Find(nickname);
}
else
@@ -1590,17 +1634,19 @@ struct IRCDMessageUID : IRCDMessage
}
};
-struct IRCDMessageUmode2 : IRCDMessage
+struct IRCDMessageUmode2 final
+ : IRCDMessage
{
- IRCDMessageUmode2(Module *creator) : IRCDMessage(creator, "UMODE2", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
+ IRCDMessageUmode2(Module *creator) : IRCDMessage(creator, "UMODE2", 1) { SetFlag(FLAG_REQUIRE_USER); }
- void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
+ void Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags) override
{
- source.GetUser()->SetModesInternal(source, "%s", params[0].c_str());
+ source.GetUser()->SetModesInternal(source, params[0]);
}
};
-class ProtoUnreal : public Module
+class ProtoUnreal final
+ : public Module
{
UnrealIRCdProto ircd_proto;
@@ -1641,107 +1687,123 @@ class ProtoUnreal : public Module
IRCDMessageServer message_server;
IRCDMessageSID message_sid;
IRCDMessageSJoin message_sjoin;
+ IRCDMessageSVSLogin message_svslogin;
IRCDMessageTopic message_topic;
IRCDMessageUID message_uid;
IRCDMessageUmode2 message_umode2;
- bool use_server_side_mlock;
-
- public:
- ProtoUnreal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
- ircd_proto(this),
- message_away(this), message_error(this), message_invite(this), message_join(this), message_kick(this),
- message_kill(this), message_svskill(this, "SVSKILL"), message_motd(this), message_notice(this), message_part(this), message_ping(this),
- message_privmsg(this), message_quit(this), message_squit(this), message_stats(this), message_time(this),
- message_version(this), message_whois(this),
-
- message_capab(this), message_chghost(this), message_chgident(this), message_chgname(this),
- message_md(this, ircd_proto.ClientModData, ircd_proto.ChannelModData),message_mode(this, "MODE"),
- message_svsmode(this, "SVSMODE"), message_svs2mode(this, "SVS2MODE"), message_netinfo(this), message_nick(this), message_pong(this),
- message_sasl(this), message_sdesc(this), message_sethost(this), message_setident(this), message_setname(this), message_server(this),
- message_sid(this), message_sjoin(this), message_topic(this), message_uid(this), message_umode2(this)
- {
-
- }
-
- void Prioritize() anope_override
+public:
+ ProtoUnreal(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, PROTOCOL | VENDOR)
+ , ircd_proto(this)
+ , message_away(this)
+ , message_error(this)
+ , message_invite(this)
+ , message_join(this)
+ , message_kick(this)
+ , message_kill(this)
+ , message_svskill(this, "SVSKILL")
+ , message_motd(this)
+ , message_notice(this)
+ , message_part(this)
+ , message_ping(this)
+ , message_privmsg(this)
+ , message_quit(this)
+ , message_squit(this)
+ , message_stats(this)
+ , message_time(this)
+ , message_version(this)
+ , message_whois(this)
+ , message_capab(this)
+ , message_chghost(this)
+ , message_chgident(this)
+ , message_chgname(this)
+ , message_md(this, ircd_proto.ClientModData, ircd_proto.ChannelModData)
+ , message_mode(this, "MODE", true)
+ , message_svsmode(this, "SVSMODE", false)
+ , message_svs2mode(this, "SVS2MODE", false)
+ , message_netinfo(this)
+ , message_nick(this)
+ , message_pong(this)
+ , message_sasl(this)
+ , message_sdesc(this)
+ , message_sethost(this)
+ , message_setident(this)
+ , message_setname(this)
+ , message_server(this)
+ , message_sid(this)
+ , message_sjoin(this)
+ , message_svslogin(this)
+ , message_topic(this)
+ , message_uid(this)
+ , message_umode2(this)
+ {
+ }
+
+ void Prioritize() override
{
ModuleManager::SetPriority(this, PRIORITY_FIRST);
}
- void OnReload(Configuration::Conf *conf) anope_override
- {
- use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock");
- }
-
- void OnUserNickChange(User *u, const Anope::string &) anope_override
+ void OnUserNickChange(User *u, const Anope::string &) override
{
u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED"));
- if (Servers::Capab.count("ESVID") == 0)
- IRCD->SendLogout(u);
}
- void OnChannelSync(Channel *c) anope_override
+ void OnChannelSync(Channel *c) override
{
if (!c->ci)
return;
ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
- if (use_server_side_mlock && Servers::Capab.count("MLOCK") > 0 && modelocks)
+ if (Servers::Capab.count("MLOCK") > 0 && modelocks)
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(c->creation_time) << " " << c->ci->name << " " << modes;
+ Uplink::Send("MLOCK", c->creation_time, c->ci->name, modes);
}
}
- void OnChanRegistered(ChannelInfo *ci) anope_override
+ void OnChanRegistered(ChannelInfo *ci) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
- if (!ci->c || !use_server_side_mlock || !modelocks || !Servers::Capab.count("MLOCK"))
+ if (!ci->c || !modelocks || !Servers::Capab.count("MLOCK"))
return;
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, modes);
}
- void OnDelChan(ChannelInfo *ci) anope_override
+ void OnDelChan(ChannelInfo *ci) override
{
- if (!ci->c || !use_server_side_mlock || !Servers::Capab.count("MLOCK"))
+ if (!ci->c || !Servers::Capab.count("MLOCK"))
return;
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " :";
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, "");
}
- EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
+ EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, modes);
}
return EVENT_CONTINUE;
}
- EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
+ EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) override
{
ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
- UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
+ Uplink::Send("MLOCK", ci->c->creation_time, ci->name, modes);
}
return EVENT_CONTINUE;
}
-
- void OnChannelUnban(User *u, ChannelInfo *ci) anope_override
- {
- UplinkSocket::Message(ci->WhoSends()) << "SVS2MODE " << ci->c->name << " -b " << u->GetUID();
- /* Unreal will remove all matching bans for us regardless of our internal matching.
- Don't use Message(Me) here as certain Unreal versions will always respond with TS-less MODE message. */
- }
};
MODULE_INIT(ProtoUnreal)
diff --git a/modules/m_proxyscan.cpp b/modules/proxyscan.cpp
index c6d6dbcd1..846095abc 100644
--- a/modules/m_proxyscan.cpp
+++ b/modules/proxyscan.cpp
@@ -8,7 +8,7 @@
#include "module.h"
-struct ProxyCheck
+struct ProxyCheck final
{
std::set<Anope::string, ci::less> types;
std::vector<unsigned short> ports;
@@ -21,42 +21,46 @@ static Anope::string target_ip;
static unsigned short target_port;
static bool add_to_akill;
-class ProxyCallbackListener : public ListenSocket
+class ProxyCallbackListener final
+ : public ListenSocket
{
- class ProxyCallbackClient : public ClientSocket, public BufferedSocket
+ class ProxyCallbackClient final
+ : public ClientSocket
+ , public BufferedSocket
{
- public:
- ProxyCallbackClient(ListenSocket *l, int f, const sockaddrs &a) : Socket(f, l->IsIPv6()), ClientSocket(l, a), BufferedSocket()
+ public:
+ ProxyCallbackClient(ListenSocket *l, int f, const sockaddrs &a) : Socket(f, l->GetFamily()), ClientSocket(l, a), BufferedSocket()
{
}
- void OnAccept() anope_override
+ void OnAccept() override
{
this->Write(ProxyCheckString);
}
- bool ProcessWrite() anope_override
+ bool ProcessWrite() override
{
- return !BufferedSocket::ProcessWrite() || this->write_buffer.empty() ? false : true;
+ return !(!BufferedSocket::ProcessWrite() || this->write_buffer.empty());
}
};
- public:
- ProxyCallbackListener(const Anope::string &b, int p) : Socket(-1, b.find(':') != Anope::string::npos), ListenSocket(b, p, false)
+public:
+ ProxyCallbackListener(const Anope::string &b, int p) : Socket(-1, b.find(':') == Anope::string::npos ? AF_INET : AF_INET6), ListenSocket(b, p, false)
{
}
- ClientSocket *OnAccept(int fd, const sockaddrs &addr) anope_override
+ ClientSocket *OnAccept(int fd, const sockaddrs &addr) override
{
return new ProxyCallbackClient(this, fd, addr);
}
};
-class ProxyConnect : public ConnectionSocket
+class ProxyConnect
+ : public ConnectionSocket
{
static ServiceReference<XLineManager> akills;
- public:
+public:
static std::set<ProxyConnect *> proxies;
ProxyCheck proxy;
@@ -69,26 +73,26 @@ class ProxyConnect : public ConnectionSocket
proxies.insert(this);
}
- ~ProxyConnect()
+ ~ProxyConnect() override
{
proxies.erase(this);
}
- virtual void OnConnect() anope_override = 0;
+ void OnConnect() override = 0;
virtual const Anope::string GetType() const = 0;
- protected:
+protected:
void Ban()
{
Anope::string reason = this->proxy.reason;
reason = reason.replace_all_cs("%t", this->GetType());
reason = reason.replace_all_cs("%i", this->conaddr.addr());
- reason = reason.replace_all_cs("%p", stringify(this->conaddr.port()));
+ reason = reason.replace_all_cs("%p", Anope::ToString(this->conaddr.port()));
BotInfo *OperServ = Config->GetClient("OperServ");
- Log(OperServ) << "PROXYSCAN: Open " << this->GetType() << " proxy found on " << this->conaddr.addr() << ":" << this->conaddr.port() << " (" << reason << ")";
- XLine *x = new XLine("*@" + this->conaddr.addr(), OperServ ? OperServ->nick : "", Anope::CurTime + this->proxy.duration, reason, XLineManager::GenerateUID());
+ Log(OperServ) << "PROXYSCAN: Open " << this->GetType() << " proxy found on " << this->conaddr.str() << " (" << reason << ")";
+ auto *x = new XLine("*@" + this->conaddr.addr(), OperServ ? OperServ->nick : "", Anope::CurTime + this->proxy.duration, reason, XLineManager::GenerateUID());
if (add_to_akill && akills)
{
akills->AddXLine(x);
@@ -107,14 +111,16 @@ class ProxyConnect : public ConnectionSocket
ServiceReference<XLineManager> ProxyConnect::akills("XLineManager", "xlinemanager/sgline");
std::set<ProxyConnect *> ProxyConnect::proxies;
-class HTTPProxyConnect : public ProxyConnect, public BufferedSocket
+class HTTPProxyConnect final
+ : public ProxyConnect
+ , public BufferedSocket
{
- public:
+public:
HTTPProxyConnect(ProxyCheck &p, unsigned short po) : Socket(-1), ProxyConnect(p, po), BufferedSocket()
{
}
- void OnConnect() anope_override
+ void OnConnect() override
{
this->Write("CONNECT %s:%d HTTP/1.0", target_ip.c_str(), target_port);
this->Write("Content-Length: 0");
@@ -122,12 +128,12 @@ class HTTPProxyConnect : public ProxyConnect, public BufferedSocket
this->Write("");
}
- const Anope::string GetType() const anope_override
+ const Anope::string GetType() const override
{
return "HTTP";
}
- bool ProcessRead() anope_override
+ bool ProcessRead() override
{
bool b = BufferedSocket::ProcessRead();
if (this->GetLine() == ProxyCheckString)
@@ -139,14 +145,16 @@ class HTTPProxyConnect : public ProxyConnect, public BufferedSocket
}
};
-class SOCKS5ProxyConnect : public ProxyConnect, public BinarySocket
+class SOCKS5ProxyConnect final
+ : public ProxyConnect
+ , public BinarySocket
{
- public:
+public:
SOCKS5ProxyConnect(ProxyCheck &p, unsigned short po) : Socket(-1), ProxyConnect(p, po), BinarySocket()
{
}
- void OnConnect() anope_override
+ void OnConnect() override
{
sockaddrs target_addr;
char buf[4 + sizeof(target_addr.sa4.sin_addr.s_addr) + sizeof(target_addr.sa4.sin_port)];
@@ -173,12 +181,12 @@ class SOCKS5ProxyConnect : public ProxyConnect, public BinarySocket
this->Write(buf, ptr);
}
- const Anope::string GetType() const anope_override
+ const Anope::string GetType() const override
{
return "SOCKS5";
}
- bool Read(const char *buffer, size_t l) anope_override
+ bool Read(const char *buffer, size_t l) override
{
if (l >= ProxyCheckString.length() && !strncmp(buffer, ProxyCheckString.c_str(), ProxyCheckString.length()))
{
@@ -189,7 +197,8 @@ class SOCKS5ProxyConnect : public ProxyConnect, public BinarySocket
}
};
-class ModuleProxyScan : public Module
+class ModuleProxyScan final
+ : public Module
{
Anope::string listen_ip;
unsigned short listen_port;
@@ -198,14 +207,16 @@ class ModuleProxyScan : public Module
ProxyCallbackListener *listener;
- class ConnectionTimeout : public Timer
+ class ConnectionTimeout final
+ : public Timer
{
- public:
- ConnectionTimeout(Module *c, long timeout) : Timer(c, timeout, Anope::CurTime, true)
+ public:
+ ConnectionTimeout(Module *c, time_t timeout)
+ : Timer(c, timeout, true)
{
}
- void Tick(time_t) anope_override
+ void Tick() override
{
for (std::set<ProxyConnect *>::iterator it = ProxyConnect::proxies.begin(), it_end = ProxyConnect::proxies.end(); it != it_end;)
{
@@ -218,7 +229,7 @@ class ModuleProxyScan : public Module
}
} connectionTimeout;
- public:
+public:
ModuleProxyScan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
connectionTimeout(this, 5)
{
@@ -227,7 +238,7 @@ class ModuleProxyScan : public Module
this->listener = NULL;
}
- ~ModuleProxyScan()
+ ~ModuleProxyScan() override
{
for (std::set<ProxyConnect *>::iterator it = ProxyConnect::proxies.begin(), it_end = ProxyConnect::proxies.end(); it != it_end;)
{
@@ -249,7 +260,7 @@ class ModuleProxyScan : public Module
delete this->listener;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = Config->GetModule(this);
@@ -287,7 +298,7 @@ class ModuleProxyScan : public Module
}
catch (const SocketException &ex)
{
- throw ConfigException("m_proxyscan: " + ex.GetReason());
+ throw ConfigException("proxyscan: " + ex.GetReason());
}
this->proxyscans.clear();
@@ -310,12 +321,8 @@ class ModuleProxyScan : public Module
commasepstream sep2(block->Get<const Anope::string>("port"));
while (sep2.GetToken(token))
{
- try
- {
- unsigned short port = convertTo<unsigned short>(token);
- p.ports.push_back(port);
- }
- catch (const ConvertException &) { }
+ if (auto port = Anope::TryConvert<unsigned short>(token))
+ p.ports.push_back(port.value());
}
if (p.ports.empty())
continue;
@@ -329,7 +336,7 @@ class ModuleProxyScan : public Module
}
}
- void OnUserConnect(User *user, bool &exempt) anope_override
+ void OnUserConnect(User *user, bool &exempt) override
{
if (exempt || user->Quitting() || !Me->IsSynced() || !user->server->IsSynced())
return;
@@ -350,24 +357,24 @@ class ModuleProxyScan : public Module
{
ProxyCheck &p = this->proxyscans[i - 1];
- for (std::set<Anope::string, ci::less>::iterator it = p.types.begin(), it_end = p.types.end(); it != it_end; ++it)
+ for (const auto &type : p.types)
{
- for (unsigned k = 0; k < p.ports.size(); ++k)
+ for (const auto port : p.ports)
{
try
{
ProxyConnect *con = NULL;
- if (it->equals_ci("HTTP"))
- con = new HTTPProxyConnect(p, p.ports[k]);
- else if (it->equals_ci("SOCKS5"))
- con = new SOCKS5ProxyConnect(p, p.ports[k]);
+ if (type.equals_ci("HTTP"))
+ con = new HTTPProxyConnect(p, port);
+ else if (type.equals_ci("SOCKS5"))
+ con = new SOCKS5ProxyConnect(p, port);
else
continue;
- con->Connect(user->ip.addr(), p.ports[k]);
+ con->Connect(user->ip.addr(), port);
}
catch (const SocketException &ex)
{
- Log(LOG_DEBUG) << "m_proxyscan: " << ex.GetReason();
+ Log(LOG_DEBUG) << "proxyscan: " << ex.GetReason();
}
}
}
diff --git a/modules/pseudoclients/global.cpp b/modules/pseudoclients/global.cpp
deleted file mode 100644
index f17af5ca9..000000000
--- a/modules/pseudoclients/global.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/* Global core functions
- *
- * (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"
-
-class GlobalCore : public Module, public GlobalService
-{
- Reference<BotInfo> Global;
-
- void ServerGlobal(BotInfo *sender, Server *s, const Anope::string &message)
- {
- if (s != Me && !s->IsJuped())
- s->Notice(sender, message);
- for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i)
- this->ServerGlobal(sender, s->GetLinks()[i], message);
- }
-
- public:
- GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- GlobalService(this)
- {
- }
-
- Reference<BotInfo> GetDefaultSender() anope_override
- {
- return Global;
- }
-
- void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) anope_override
- {
- if (Me->GetLinks().empty())
- return;
- if (!sender)
- sender = Global;
- if (!sender)
- return;
-
- Anope::string rmessage;
-
- if (!source.empty() && !Config->GetModule("global")->Get<bool>("anonymousglobal"))
- rmessage = "[" + source + "] " + message;
- else
- rmessage = message;
-
- this->ServerGlobal(sender, Servers::GetUplink(), rmessage);
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- const Anope::string &glnick = conf->GetModule(this)->Get<const Anope::string>("client");
-
- if (glnick.empty())
- throw ConfigException(Module::name + ": <client> must be defined");
-
- BotInfo *bi = BotInfo::Find(glnick, true);
- if (!bi)
- throw ConfigException(Module::name + ": no bot named " + glnick);
-
- Global = bi;
- }
-
- void OnRestart() anope_override
- {
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
- if (!gl.empty())
- this->SendGlobal(Global, "", gl);
- }
-
- void OnShutdown() anope_override
- {
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
- if (!gl.empty())
- this->SendGlobal(Global, "", gl);
- }
-
- void OnNewServer(Server *s) anope_override
- {
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycleup");
- if (!gl.empty() && !Me->IsSynced())
- s->Notice(Global, gl);
- }
-
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!params.empty() || source.c || source.service != *Global)
- return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), Global->nick.c_str());
- return EVENT_CONTINUE;
- }
-};
-
-MODULE_INIT(GlobalCore)
diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp
deleted file mode 100644
index 95c2f37b7..000000000
--- a/modules/pseudoclients/hostserv.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/* HostServ core functions
- *
- * (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"
-
-class HostServCore : public Module
-{
- Reference<BotInfo> HostServ;
- public:
- HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
- {
- if (!IRCD || !IRCD->CanSetVHost)
- throw ModuleException("Your IRCd does not support vhosts");
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- const Anope::string &hsnick = conf->GetModule(this)->Get<const Anope::string>("client");
-
- if (hsnick.empty())
- throw ConfigException(Module::name + ": <client> must be defined");
-
- BotInfo *bi = BotInfo::Find(hsnick, true);
- if (!bi)
- throw ConfigException(Module::name + ": no bot named " + hsnick);
-
- HostServ = bi;
- }
-
- void OnUserLogin(User *u) anope_override
- {
- if (!IRCD->CanSetVHost)
- return;
-
- const NickAlias *na = NickAlias::Find(u->nick);
- if (!na || na->nc != u->Account() || !na->HasVhost())
- na = NickAlias::Find(u->Account()->display);
- if (!na || !na->HasVhost())
- return;
-
- if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVhostHost()) || (!na->GetVhostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVhostIdent())))
- {
- IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
-
- u->vhost = na->GetVhostHost();
- u->UpdateHost();
-
- if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
- u->SetVIdent(na->GetVhostIdent());
-
- if (HostServ)
- {
- if (!na->GetVhostIdent().empty())
- u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
- else
- u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str());
- }
- }
- }
-
- void OnNickDrop(CommandSource &source, NickAlias *na) anope_override
- {
- if (na->HasVhost())
- {
- FOREACH_MOD(OnDeleteVhost, (na));
- na->RemoveVhost();
- }
- }
-
- void OnNickUpdate(User *u) anope_override
- {
- this->OnUserLogin(u);
- }
-
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- if (!params.empty() || source.c || source.service != *HostServ)
- return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), HostServ->nick.c_str());
- return EVENT_CONTINUE;
- }
-
- void OnSetVhost(NickAlias *na) anope_override
- {
- if (Config->GetModule(this)->Get<bool>("activate_on_set"))
- {
- User *u = User::Find(na->nick);
-
- if (u && u->Account() == na->nc)
- {
- IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
-
- u->vhost = na->GetVhostHost();
- u->UpdateHost();
-
- if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
- u->SetVIdent(na->GetVhostIdent());
-
- if (HostServ)
- {
- if (!na->GetVhostIdent().empty())
- u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
- else
- u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str());
- }
- }
- }
- }
-
- void OnDeleteVhost(NickAlias *na) anope_override
- {
- if (Config->GetModule(this)->Get<bool>("activate_on_set"))
- {
- User *u = User::Find(na->nick);
-
- if (u && u->Account() == na->nc)
- IRCD->SendVhostDel(u);
- }
- }
-};
-
-MODULE_INIT(HostServCore)
diff --git a/modules/m_redis.cpp b/modules/redis.cpp
index f7264d67c..25ecf0678 100644
--- a/modules/m_redis.cpp
+++ b/modules/redis.cpp
@@ -13,45 +13,46 @@ using namespace Redis;
class MyRedisService;
-class RedisSocket : public BinarySocket, public ConnectionSocket
+class RedisSocket final
+ : public BinarySocket
+ , public ConnectionSocket
{
size_t ParseReply(Reply &r, const char *buf, size_t l);
- public:
+public:
MyRedisService *provider;
std::deque<Interface *> interfaces;
std::map<Anope::string, Interface *> subinterfaces;
- RedisSocket(MyRedisService *pro, bool v6) : Socket(-1, v6), provider(pro) { }
+ RedisSocket(MyRedisService *pro, bool v6) : Socket(-1, v6 ? AF_INET6 : AF_INET), provider(pro) { }
- ~RedisSocket();
+ ~RedisSocket() override;
- void OnConnect() anope_override;
- void OnError(const Anope::string &error) anope_override;
+ void OnConnect() override;
+ void OnError(const Anope::string &error) override;
- bool Read(const char *buffer, size_t l) anope_override;
+ bool Read(const char *buffer, size_t l) override;
};
-class Transaction : public Interface
+class Transaction final
+ : public Interface
{
- public:
+public:
std::deque<Interface *> interfaces;
Transaction(Module *creator) : Interface(creator) { }
- ~Transaction()
+ ~Transaction() override
{
- for (unsigned i = 0; i < interfaces.size(); ++i)
+ for (auto *iface : interfaces)
{
- Interface *inter = interfaces[i];
-
- if (!inter)
+ if (!iface)
continue;
- inter->OnError("Interface going away");
+ iface->OnError("Interface going away");
}
}
- void OnResult(const Reply &r) anope_override
+ void OnResult(const Reply &r) override
{
/* This is a multi bulk reply of the results of the queued commands
* in this transaction
@@ -59,10 +60,8 @@ class Transaction : public Interface
Log(LOG_DEBUG_2) << "redis: transaction complete with " << r.multi_bulk.size() << " results";
- for (unsigned i = 0; i < r.multi_bulk.size(); ++i)
+ for (auto *result : r.multi_bulk)
{
- const Reply *reply = r.multi_bulk[i];
-
if (interfaces.empty())
break;
@@ -70,25 +69,25 @@ class Transaction : public Interface
interfaces.pop_front();
if (inter)
- inter->OnResult(*reply);
+ inter->OnResult(*result);
}
}
};
-class MyRedisService : public Provider
+class MyRedisService final
+ : public Provider
{
- public:
+public:
Anope::string host;
int port;
unsigned db;
- RedisSocket *sock, *sub;
+ RedisSocket *sock = nullptr, *sub = nullptr;
Transaction ti;
- bool in_transaction;
+ bool in_transaction = false;
- MyRedisService(Module *c, const Anope::string &n, const Anope::string &h, int p, unsigned d) : Provider(c, n), host(h), port(p), db(d), sock(NULL), sub(NULL),
- ti(c), in_transaction(false)
+ MyRedisService(Module *c, const Anope::string &n, const Anope::string &h, int p, unsigned d) : Provider(c, n), host(h), port(p), db(d), ti(c)
{
sock = new RedisSocket(this, host.find(':') != Anope::string::npos);
sock->Connect(host, port);
@@ -97,7 +96,7 @@ class MyRedisService : public Provider
sub->Connect(host, port);
}
- ~MyRedisService()
+ ~MyRedisService() override
{
if (sock)
{
@@ -112,8 +111,8 @@ class MyRedisService : public Provider
}
}
- private:
- inline void Pack(std::vector<char> &buffer, const char *buf, size_t sz = 0)
+private:
+ static inline void Pack(std::vector<char> &buffer, const char *buf, size_t sz = 0)
{
if (!sz)
sz = strlen(buf);
@@ -128,18 +127,16 @@ class MyRedisService : public Provider
std::vector<char> buffer;
Pack(buffer, "*");
- Pack(buffer, stringify(args.size()).c_str());
+ Pack(buffer, Anope::ToString(args.size()).c_str());
Pack(buffer, "\r\n");
- for (unsigned j = 0; j < args.size(); ++j)
+ for (const auto &[key, value] : args)
{
- const std::pair<const char *, size_t> &pair = args[j];
-
Pack(buffer, "$");
- Pack(buffer, stringify(pair.second).c_str());
+ Pack(buffer, Anope::ToString(value).c_str());
Pack(buffer, "\r\n");
- Pack(buffer, pair.first, pair.second);
+ Pack(buffer, key, value);
Pack(buffer, "\r\n");
}
@@ -156,8 +153,8 @@ class MyRedisService : public Provider
s->interfaces.push_back(i);
}
- public:
- bool IsSocketDead() anope_override
+public:
+ bool IsSocketDead() override
{
return this->sock && this->sock->flags[SF_DEAD];
}
@@ -165,8 +162,8 @@ class MyRedisService : public Provider
void SendCommand(RedisSocket *s, Interface *i, const std::vector<Anope::string> &cmds)
{
std::vector<std::pair<const char *, size_t> > args;
- for (unsigned j = 0; j < cmds.size(); ++j)
- args.push_back(std::make_pair(cmds[j].c_str(), cmds[j].length()));
+ for (const auto &cmd : cmds)
+ args.emplace_back(cmd.c_str(), cmd.length());
this->Send(s, i, args);
}
@@ -188,23 +185,23 @@ class MyRedisService : public Provider
this->Send(sock, i, args);
}
- void SendCommand(Interface *i, const std::vector<Anope::string> &cmds) anope_override
+ void SendCommand(Interface *i, const std::vector<Anope::string> &cmds) override
{
std::vector<std::pair<const char *, size_t> > args;
- for (unsigned j = 0; j < cmds.size(); ++j)
- args.push_back(std::make_pair(cmds[j].c_str(), cmds[j].length()));
+ for (const auto &cmd : cmds)
+ args.emplace_back(cmd.c_str(), cmd.length());
this->Send(i, args);
}
- void SendCommand(Interface *i, const Anope::string &str) anope_override
+ void SendCommand(Interface *i, const Anope::string &str) override
{
std::vector<Anope::string> args;
spacesepstream(str).GetTokens(args);
this->SendCommand(i, args);
}
- public:
- bool BlockAndProcess() anope_override
+public:
+ bool BlockAndProcess() override
{
if (!this->sock->ProcessWrite())
this->sock->flags[SF_DEAD] = true;
@@ -215,7 +212,7 @@ class MyRedisService : public Provider
return !this->sock->interfaces.empty();
}
- void Subscribe(Interface *i, const Anope::string &pattern) anope_override
+ void Subscribe(Interface *i, const Anope::string &pattern) override
{
if (sub == NULL)
{
@@ -224,29 +221,29 @@ class MyRedisService : public Provider
}
std::vector<Anope::string> args;
- args.push_back("PSUBSCRIBE");
+ args.emplace_back("PSUBSCRIBE");
args.push_back(pattern);
this->SendCommand(sub, NULL, args);
sub->subinterfaces[pattern] = i;
}
- void Unsubscribe(const Anope::string &pattern) anope_override
+ void Unsubscribe(const Anope::string &pattern) override
{
if (sub)
sub->subinterfaces.erase(pattern);
}
- void StartTransaction() anope_override
+ void StartTransaction() override
{
if (in_transaction)
- throw CoreException();
+ throw ModuleException("Tried to start a transaction while one was already in progress");
this->SendCommand(NULL, "MULTI");
in_transaction = true;
}
- void CommitTransaction() anope_override
+ void CommitTransaction() override
{
/* The result of the transaction comes back to the reply of EXEC as a multi bulk.
* The reply to the individual commands that make up the transaction when executed
@@ -267,14 +264,12 @@ RedisSocket::~RedisSocket()
provider->sub = NULL;
}
- for (unsigned i = 0; i < interfaces.size(); ++i)
+ for (auto *iface : interfaces)
{
- Interface *inter = interfaces[i];
-
- if (!inter)
+ if (!iface)
continue;
- inter->OnError("Interface going away");
+ iface->OnError("Interface going away");
}
}
@@ -283,7 +278,7 @@ void RedisSocket::OnConnect()
Log() << "redis: Successfully connected to " << provider->name << (this == this->provider->sub ? " (sub)" : "");
this->provider->SendCommand(NULL, "CLIENT SETNAME Anope");
- this->provider->SendCommand(NULL, "SELECT " + stringify(provider->db));
+ this->provider->SendCommand(NULL, "SELECT " + Anope::ToString(provider->db));
if (this != this->provider->sub)
{
@@ -338,11 +333,8 @@ size_t RedisSocket::ParseReply(Reply &r, const char *buffer, size_t l)
size_t nl = ibuf.find("\r\n");
if (nl != Anope::string::npos)
{
- try
- {
- r.i = convertTo<int64_t>(ibuf.substr(0, nl));
- }
- catch (const ConvertException &) { }
+ if (auto i = Anope::TryConvert<int64_t>(ibuf.substr(0, nl)))
+ r.i = i.value();
r.type = Reply::INT;
used = 1 + nl + 2;
@@ -356,10 +348,9 @@ size_t RedisSocket::ParseReply(Reply &r, const char *buffer, size_t l)
size_t nl = reply.find("\r\n");
if (nl != Anope::string::npos)
{
- int len;
- try
+ if (auto l = Anope::TryConvert<int>(reply.substr(0, nl)))
{
- len = convertTo<int>(reply.substr(0, nl));
+ int len = l.value();
if (len >= 0)
{
if (1 + nl + 2 + len + 2 <= l)
@@ -375,7 +366,6 @@ size_t RedisSocket::ParseReply(Reply &r, const char *buffer, size_t l)
r.type = Reply::BULK;
}
}
- catch (const ConvertException &) { }
}
break;
}
@@ -389,12 +379,8 @@ size_t RedisSocket::ParseReply(Reply &r, const char *buffer, size_t l)
if (nl != Anope::string::npos)
{
r.type = Reply::MULTI_BULK;
- try
- {
- r.multi_bulk_size = convertTo<int>(reply.substr(0, nl));
- }
- catch (const ConvertException &) { }
-
+ if (auto size = Anope::TryConvert<int>(reply.substr(0, nl)))
+ r.multi_bulk_size = size.value();
used = 1 + nl + 2;
}
else
@@ -403,15 +389,15 @@ size_t RedisSocket::ParseReply(Reply &r, const char *buffer, size_t l)
else if (r.multi_bulk_size >= 0 && r.multi_bulk.size() == static_cast<unsigned>(r.multi_bulk_size))
{
/* This multi bulk is already complete, so check the sub bulks */
- for (unsigned i = 0; i < r.multi_bulk.size(); ++i)
- if (r.multi_bulk[i]->type == Reply::MULTI_BULK)
- ParseReply(*r.multi_bulk[i], buffer + used, l - used);
+ for (auto &bulk : r.multi_bulk)
+ if (bulk->type == Reply::MULTI_BULK)
+ ParseReply(*bulk, buffer + used, l - used);
break;
}
for (int i = r.multi_bulk.size(); i < r.multi_bulk_size; ++i)
{
- Reply *reply = new Reply();
+ auto *reply = new Reply();
size_t u = ParseReply(*reply, buffer + used, l - used);
if (!u)
{
@@ -525,23 +511,23 @@ bool RedisSocket::Read(const char *buffer, size_t l)
}
-class ModuleRedis : public Module
+class ModuleRedis final
+ : public Module
{
std::map<Anope::string, MyRedisService *> services;
- public:
+public:
ModuleRedis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
}
- ~ModuleRedis()
+ ~ModuleRedis() override
{
- for (std::map<Anope::string, MyRedisService *>::iterator it = services.begin(); it != services.end(); ++it)
+ for (auto &[_, p] : services)
{
- MyRedisService *p = it->second;
-
delete p->sock;
p->sock = NULL;
+
delete p->sub;
p->sub = NULL;
@@ -549,7 +535,7 @@ class ModuleRedis : public Module
}
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
std::vector<Anope::string> new_services;
@@ -578,12 +564,10 @@ class ModuleRedis : public Module
}
}
- void OnModuleUnload(User *, Module *m) anope_override
+ void OnModuleUnload(User *, Module *m) override
{
- for (std::map<Anope::string, MyRedisService *>::iterator it = services.begin(); it != services.end(); ++it)
+ for (auto &[_, p] : services)
{
- MyRedisService *p = it->second;
-
if (p->sock)
for (unsigned i = p->sock->interfaces.size(); i > 0; --i)
{
diff --git a/modules/regex_stdlib.cpp b/modules/regex_stdlib.cpp
new file mode 100644
index 000000000..0e932c02a
--- /dev/null
+++ b/modules/regex_stdlib.cpp
@@ -0,0 +1,107 @@
+/*
+ *
+ * (C) 2012-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+
+#include <regex>
+
+class StdLibRegex final
+ : public Regex
+{
+private:
+ std::regex regex;
+
+public:
+ StdLibRegex(const Anope::string &expr, std::regex::flag_type type)
+ : Regex(expr)
+ {
+ try
+ {
+ regex.assign(expr.str(), type | std::regex::optimize);
+ }
+ catch (const std::regex_error &error)
+ {
+ throw RegexException("Error in regex " + expr + ": " + error.what());
+ }
+ }
+
+ bool Matches(const Anope::string &str)
+ {
+ return std::regex_search(str.str(), regex);
+ }
+};
+
+class StdLibRegexProvider final
+ : public RegexProvider
+{
+public:
+ std::regex_constants::syntax_option_type type;
+
+ StdLibRegexProvider(Module *creator)
+ : RegexProvider(creator, "regex/stdlib")
+ {
+ }
+
+ Regex *Compile(const Anope::string &expression) override
+ {
+ return new StdLibRegex(expression, type);
+ }
+};
+
+class ModuleRegexStdLib final
+ : public Module
+{
+private:
+ StdLibRegexProvider stdlib_regex_provider;
+
+public:
+ ModuleRegexStdLib(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, EXTRA | VENDOR)
+ , stdlib_regex_provider(this)
+ {
+ this->SetPermanent(true);
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ Configuration::Block *block = conf->GetModule(this);
+
+ const Anope::string syntax = block->Get<const Anope::string>("syntax", "ecmascript");
+ if (syntax == "awk")
+ stdlib_regex_provider.type = std::regex::awk;
+ else if (syntax == "basic")
+ stdlib_regex_provider.type = std::regex::basic;
+ else if (syntax == "ecmascript")
+ stdlib_regex_provider.type = std::regex::ECMAScript;
+ else if (syntax == "egrep")
+ stdlib_regex_provider.type = std::regex::egrep;
+ else if (syntax == "extended")
+ stdlib_regex_provider.type = std::regex::extended;
+ else if (syntax == "grep")
+ stdlib_regex_provider.type = std::regex::grep;
+ else
+ throw ConfigException(this->name + ": syntax must be set to awk, basic, ecmascript, egrep, extended, or grep.");
+ }
+
+ ~ModuleRegexStdLib()
+ {
+ for (auto *xlm : XLineManager::XLineManagers)
+ {
+ for (auto *x : xlm->GetList())
+ {
+ if (x->regex && dynamic_cast<StdLibRegex *>(x->regex))
+ {
+ delete x->regex;
+ x->regex = NULL;
+ }
+ }
+ }
+ }
+};
+
+MODULE_INIT(ModuleRegexStdLib)
diff --git a/modules/m_rewrite.cpp b/modules/rewrite.cpp
index 32e99788f..0a9b22dcb 100644
--- a/modules/m_rewrite.cpp
+++ b/modules/rewrite.cpp
@@ -8,7 +8,7 @@
#include "module.h"
-struct Rewrite
+struct Rewrite final
{
Anope::string client, source_message, target_message, desc;
@@ -38,28 +38,35 @@ struct Rewrite
else
{
int num = -1, end = -1;
- try
+ Anope::string num_str = token.substr(1);
+ size_t hy = num_str.find('-');
+ if (hy == Anope::string::npos)
{
- Anope::string num_str = token.substr(1);
- size_t hy = num_str.find('-');
- if (hy == Anope::string::npos)
- {
- num = convertTo<int>(num_str);
- end = num + 1;
- }
+ auto n = Anope::TryConvert<int>(num_str);
+ if (!n.has_value())
+ continue;
+
+ num = n.value();
+ end = num + 1;
+ }
+ else
+ {
+ auto n = Anope::TryConvert<int>(num_str.substr(0, hy));
+ if (!n.has_value())
+ continue;
+
+ num = n.value();
+ if (hy == num_str.length() - 1)
+ end = params.size();
else
{
- num = convertTo<int>(num_str.substr(0, hy));
- if (hy == num_str.length() - 1)
- end = params.size();
- else
- end = convertTo<int>(num_str.substr(hy + 1)) + 1;
+ n = Anope::TryConvert<int>(num_str.substr(hy + 1));
+ if (!n.has_value())
+ continue;
+
+ end = n.value() + 1;
}
}
- catch (const ConvertException &)
- {
- continue;
- }
for (int i = num; i < end && static_cast<unsigned>(i) < params.size(); ++i)
message += " " + params[i];
@@ -74,10 +81,8 @@ struct Rewrite
static Rewrite *Find(const Anope::string &client, const Anope::string &cmd)
{
- for (unsigned i = 0; i < rewrites.size(); ++i)
+ for (auto &r : rewrites)
{
- Rewrite &r = rewrites[i];
-
if ((client.empty() || r.client.equals_ci(client)) && (r.source_message.equals_ci(cmd) || r.source_message.find_ci(cmd + " ") == 0))
return &r;
}
@@ -87,10 +92,8 @@ struct Rewrite
static Rewrite *Match(const Anope::string &client, const std::vector<Anope::string> &params)
{
- for (unsigned i = 0; i < rewrites.size(); ++i)
+ for (auto &r : rewrites)
{
- Rewrite &r = rewrites[i];
-
if ((client.empty() || r.client.equals_ci(client)) && r.Matches(params))
return &r;
}
@@ -101,12 +104,13 @@ struct Rewrite
std::vector<Rewrite> Rewrite::rewrites;
-class RewriteCommand : public Command
+class RewriteCommand final
+ : public Command
{
- public:
+public:
RewriteCommand(Module *creator) : Command(creator, "rewrite", 0, 0) { }
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
std::vector<Anope::string> full_params = params;
full_params.insert(full_params.begin(), source.command);
@@ -115,17 +119,17 @@ class RewriteCommand : public Command
if (r != NULL)
{
Anope::string new_message = r->Process(source, full_params);
- Log(LOG_DEBUG) << "m_rewrite: Rewrote '" << source.command << (!params.empty() ? " " + params[0] : "") << "' to '" << new_message << "' using '" << r->source_message << "'";
+ Log(LOG_DEBUG) << "rewrite: Rewrote '" << source.command << (!params.empty() ? " " + params[0] : "") << "' to '" << new_message << "' using '" << r->source_message << "'";
source.service = BotInfo::Find(r->client, true);
if (!source.service)
return;
Command::Run(source, new_message);
}
else
- Log() << "m_rewrite: Unable to rewrite '" << source.command << (!params.empty() ? " " + params[0] : "") << "'";
+ Log() << "rewrite: Unable to rewrite '" << source.command << (!params.empty() ? " " + params[0] : "") << "'";
}
- void OnServHelp(CommandSource &source) anope_override
+ void OnServHelp(CommandSource &source) override
{
Rewrite *r = Rewrite::Find(!source.c ? source.service->nick : "", source.command);
if (r != NULL && !r->desc.empty())
@@ -135,7 +139,7 @@ class RewriteCommand : public Command
}
}
- bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
+ bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
Rewrite *r = Rewrite::Find(!source.c ? source.service->nick : "", source.command);
if (r != NULL && !r->desc.empty())
@@ -149,16 +153,17 @@ class RewriteCommand : public Command
}
};
-class ModuleRewrite : public Module
+class ModuleRewrite final
+ : public Module
{
RewriteCommand cmdrewrite;
- public:
+public:
ModuleRewrite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA), cmdrewrite(this)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Rewrite::rewrites.clear();
diff --git a/modules/rpc/jsonrpc.cpp b/modules/rpc/jsonrpc.cpp
new file mode 100644
index 000000000..92a4765e9
--- /dev/null
+++ b/modules/rpc/jsonrpc.cpp
@@ -0,0 +1,209 @@
+/*
+ *
+ * (C) 2010-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+#include "modules/rpc.h"
+#include "modules/httpd.h"
+
+#include "yyjson/yyjson.c"
+
+inline Anope::string yyjson_get_astr(yyjson_val *val, const char *key)
+{
+ const auto *str = yyjson_get_str(yyjson_obj_get(val, key));
+ return str ? str : "";
+}
+
+class MyJSONRPCServiceInterface final
+ : public RPCServiceInterface
+ , public HTTPPage
+{
+private:
+ std::deque<RPCEvent *> events;
+
+ void SendError(HTTPReply &reply, int64_t code, const Anope::string &message, const Anope::string &id)
+ {
+ Log(LOG_DEBUG) << "JSON-RPC error " << code << ": " << message;
+
+ // {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": "1"}
+ auto* doc = yyjson_mut_doc_new(nullptr);
+
+ auto* root = yyjson_mut_obj(doc);
+ yyjson_mut_doc_set_root(doc, root);
+
+ auto *error = yyjson_mut_obj(doc);
+ yyjson_mut_obj_add_sint(doc, error, "code", code);
+ yyjson_mut_obj_add_strn(doc, error, "message", message.c_str(), message.length());
+
+ yyjson_mut_obj_add_val(doc, root, "error", error);
+ yyjson_mut_obj_add_str(doc, root, "jsonrpc", "2.0");
+
+ if (id.empty())
+ yyjson_mut_obj_add_null(doc, root, "id");
+ else
+ yyjson_mut_obj_add_strn(doc, root, "id", id.c_str(), id.length());
+
+ auto *json = yyjson_mut_write(doc, YYJSON_WRITE_ALLOW_INVALID_UNICODE | YYJSON_WRITE_NEWLINE_AT_END, nullptr);
+ if (json)
+ {
+ reply.Write(json);
+ free(json);
+ }
+ yyjson_mut_doc_free(doc);
+ }
+
+public:
+ MyJSONRPCServiceInterface(Module *creator, const Anope::string &sname)
+ : RPCServiceInterface(creator, sname)
+ , HTTPPage("/jsonrpc", "application/json")
+ {
+ }
+
+ void Register(RPCEvent *event) override
+ {
+ this->events.push_back(event);
+ }
+
+ void Unregister(RPCEvent *event) override
+ {
+ auto it = std::find(this->events.begin(), this->events.end(), event);
+ if (it != this->events.end())
+ this->events.erase(it);
+ }
+
+ bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) override
+ {
+ auto *doc = yyjson_read(message.content.c_str(), message.content.length(), YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INVALID_UNICODE);
+ if (!doc)
+ {
+ SendError(reply, -32700, "JSON parse error", "");
+ return true;
+ }
+
+ auto *root = yyjson_doc_get_root(doc);
+ if (!yyjson_is_obj(root))
+ {
+ // TODO: handle an array of JSON-RPC requests
+ yyjson_doc_free(doc);
+ SendError(reply, -32600, "Wrong JSON root element", "");
+ return true;
+ }
+
+ const auto id = yyjson_get_astr(root, "id");
+ const auto jsonrpc = yyjson_get_astr(root, "jsonrpc");
+ if (!jsonrpc.empty() && jsonrpc != "2.0")
+ {
+ yyjson_doc_free(doc);
+ SendError(reply, -32600, "Unsupported JSON-RPC version", id);
+ return true;
+ }
+
+ RPCRequest request(reply);
+ request.id = id;
+ request.name = yyjson_get_astr(root, "method");
+
+ auto *params = yyjson_obj_get(root, "params");
+ size_t idx, max;
+ yyjson_val *val;
+ yyjson_arr_foreach(params, idx, max, val)
+ {
+ const auto *str = yyjson_get_str(val);
+ request.data.push_back(str ? str : "");
+ }
+
+ yyjson_doc_free(doc);
+
+ for (auto *e : this->events)
+ {
+ if (!e->Run(this, client, request))
+ return false;
+
+ else if (request.GetError())
+ {
+ SendError(reply, request.GetError()->first, request.GetError()->second, id);
+ return true;
+ }
+
+ else if (!request.GetReplies().empty())
+ {
+ this->Reply(request);
+ return true;
+ }
+ }
+
+ // If we reached this point nobody handled the event.
+ SendError(reply, -32601, "Method not found", id);
+ return true;
+ }
+
+ void Reply(RPCRequest &request) override
+ {
+ // {"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]}
+ auto* doc = yyjson_mut_doc_new(nullptr);
+
+ auto* root = yyjson_mut_obj(doc);
+ yyjson_mut_doc_set_root(doc, root);
+
+ if (request.id.empty())
+ yyjson_mut_obj_add_null(doc, root, "id");
+ else
+ yyjson_mut_obj_add_strn(doc, root, "id", request.id.c_str(), request.id.length());
+
+ if (!request.GetReplies().empty())
+ {
+ auto *result = yyjson_mut_obj(doc);
+ for (const auto &[k, v] : request.GetReplies())
+ yyjson_mut_obj_add_strn(doc, result, k.c_str(), v.c_str(), v.length());
+ yyjson_mut_obj_add_val(doc, root, "result", result);
+ }
+
+ yyjson_mut_obj_add_str(doc, root, "jsonrpc", "2.0");
+
+ auto *json = yyjson_mut_write(doc, YYJSON_WRITE_ALLOW_INVALID_UNICODE | YYJSON_WRITE_NEWLINE_AT_END, nullptr);
+ if (json)
+ {
+ request.reply.Write(json);
+ free(json);
+ }
+ yyjson_mut_doc_free(doc);
+ }
+};
+
+class ModuleJSONRPC final
+ : public Module
+{
+private:
+ ServiceReference<HTTPProvider> httpref;
+ MyJSONRPCServiceInterface jsonrpcinterface;
+
+public:
+ ModuleJSONRPC(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, EXTRA | VENDOR)
+ , jsonrpcinterface(this, "rpc")
+ {
+ }
+
+ ~ModuleJSONRPC() override
+ {
+ if (httpref)
+ httpref->UnregisterPage(&jsonrpcinterface);
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ if (httpref)
+ httpref->UnregisterPage(&jsonrpcinterface);
+
+ this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", conf->GetModule(this)->Get<const Anope::string>("server", "httpd/main"));
+ if (!httpref)
+ throw ConfigException("Unable to find http reference, is httpd loaded?");
+
+ httpref->RegisterPage(&jsonrpcinterface);
+ }
+};
+
+MODULE_INIT(ModuleJSONRPC)
diff --git a/modules/rpc/rpc_main.cpp b/modules/rpc/rpc_main.cpp
new file mode 100644
index 000000000..5e33447ff
--- /dev/null
+++ b/modules/rpc/rpc_main.cpp
@@ -0,0 +1,309 @@
+/*
+ *
+ * (C) 2010-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+#include "modules/rpc.h"
+
+static Module *me;
+
+class RPCIdentifyRequest final
+ : public IdentifyRequest
+{
+ RPCRequest request;
+ HTTPReply repl; /* Request holds a reference to the HTTPReply, because we might exist long enough to invalidate it
+ we'll copy it here then reset the reference before we use it */
+ Reference<HTTPClient> client;
+ Reference<RPCServiceInterface> xinterface;
+
+public:
+ RPCIdentifyRequest(Module *m, RPCRequest &req, HTTPClient *c, RPCServiceInterface *iface, const Anope::string &acc, const Anope::string &pass)
+ : IdentifyRequest(m, acc, pass)
+ , request(req)
+ , repl(request.reply)
+ , client(c)
+ , xinterface(iface)
+ {
+ }
+
+ void OnSuccess() override
+ {
+ if (!xinterface || !client)
+ return;
+
+ request.reply = this->repl;
+
+ request.Reply("account", GetAccount());
+
+ xinterface->Reply(request);
+ client->SendReply(&request.reply);
+ }
+
+ void OnFail() override
+ {
+ if (!xinterface || !client)
+ return;
+
+ request.reply = this->repl;
+
+ request.Error(-32000, "Invalid password");
+
+ xinterface->Reply(request);
+ client->SendReply(&request.reply);
+ }
+};
+
+class MyRPCEvent final
+ : public RPCEvent
+{
+public:
+ bool Run(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request) override
+ {
+ if (request.name == "command")
+ this->DoCommand(iface, client, request);
+ else if (request.name == "checkAuthentication")
+ return this->DoCheckAuthentication(iface, client, request);
+ else if (request.name == "stats")
+ this->DoStats(iface, client, request);
+ else if (request.name == "channel")
+ this->DoChannel(iface, client, request);
+ else if (request.name == "user")
+ this->DoUser(iface, client, request);
+ else if (request.name == "opers")
+ this->DoOperType(iface, client, request);
+ else if (request.name == "notice")
+ this->DoNotice(iface, client, request);
+
+ return true;
+ }
+
+private:
+ void DoCommand(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ Anope::string service = request.data.size() > 0 ? request.data[0] : "";
+ Anope::string user = request.data.size() > 1 ? request.data[1] : "";
+ Anope::string command = request.data.size() > 2 ? request.data[2] : "";
+
+ if (service.empty() || user.empty() || command.empty())
+ {
+ request.Error(-32602, "Invalid parameters");
+ return;
+ }
+
+ BotInfo *bi = BotInfo::Find(service, true);
+ if (!bi)
+ {
+ request.Error(-32000, "Invalid service");
+ return;
+ }
+
+ NickAlias *na = NickAlias::Find(user);
+
+ Anope::string out;
+
+ struct RPCommandReply final
+ : CommandReply
+ {
+ Anope::string &str;
+
+ RPCommandReply(Anope::string &s) : str(s) { }
+
+ void SendMessage(BotInfo *source, const Anope::string &msg) override
+ {
+ str += msg + "\n";
+ };
+ }
+ reply(out);
+
+ User *u = User::Find(user, true);
+ CommandSource source(user, u, na ? *na->nc : NULL, &reply, bi);
+ Command::Run(source, command);
+
+ if (!out.empty())
+ request.Reply("return", out);
+ }
+
+ static bool DoCheckAuthentication(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ Anope::string username = request.data.size() > 0 ? request.data[0] : "";
+ Anope::string password = request.data.size() > 1 ? request.data[1] : "";
+
+ if (username.empty() || password.empty())
+ {
+ request.Error(-32602, "Invalid parameters");
+ return true;
+ }
+
+ auto *req = new RPCIdentifyRequest(me, request, client, iface, username, password);
+ FOREACH_MOD(OnCheckAuthentication, (NULL, req));
+ req->Dispatch();
+ return false;
+ }
+
+ static void DoStats(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ request.Reply("uptime", Anope::ToString(Anope::CurTime - Anope::StartTime));
+ request.Reply("uplinkname", Me->GetLinks().front()->GetName());
+ {
+ Anope::string buf;
+ for (const auto &capab : Servers::Capab)
+ buf += " " + capab;
+ if (!buf.empty())
+ buf.erase(buf.begin());
+ request.Reply("uplinkcapab", buf);
+ }
+ request.Reply("usercount", Anope::ToString(UserListByNick.size()));
+ request.Reply("maxusercount", Anope::ToString(MaxUserCount));
+ request.Reply("channelcount", Anope::ToString(ChannelList.size()));
+ }
+
+ static void DoChannel(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ if (request.data.empty())
+ return;
+
+ Channel *c = Channel::Find(request.data[0]);
+
+ request.Reply("name", c ? c->name : request.data[0]);
+
+ if (c)
+ {
+ request.Reply("bancount", Anope::ToString(c->HasMode("BAN")));
+ int count = 0;
+ for (auto &ban : c->GetModeList("BAN"))
+ request.Reply("ban" + Anope::ToString(++count), ban);
+
+ request.Reply("exceptcount", Anope::ToString(c->HasMode("EXCEPT")));
+ count = 0;
+ for (auto &except : c->GetModeList("EXCEPT"))
+ request.Reply("except" + Anope::ToString(++count), except);
+
+ request.Reply("invitecount", Anope::ToString(c->HasMode("INVITEOVERRIDE")));
+ count = 0;
+ for (auto &invite : c->GetModeList("INVITEOVERRIDE"))
+ request.Reply("invite" + Anope::ToString(++count), invite);
+
+ Anope::string users;
+ for (Channel::ChanUserList::const_iterator it = c->users.begin(); it != c->users.end(); ++it)
+ {
+ ChanUserContainer *uc = it->second;
+ users += uc->status.BuildModePrefixList() + uc->user->nick + " ";
+ }
+ if (!users.empty())
+ {
+ users.erase(users.length() - 1);
+ request.Reply("users", users);
+ }
+
+ if (!c->topic.empty())
+ request.Reply("topic", c->topic);
+
+ if (!c->topic_setter.empty())
+ request.Reply("topicsetter", c->topic_setter);
+
+ request.Reply("topictime", Anope::ToString(c->topic_time));
+ request.Reply("topicts", Anope::ToString(c->topic_ts));
+ }
+ }
+
+ static void DoUser(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ if (request.data.empty())
+ return;
+
+ User *u = User::Find(request.data[0]);
+
+ request.Reply("nick", u ? u->nick : request.data[0]);
+
+ if (u)
+ {
+ request.Reply("ident", u->GetIdent());
+ request.Reply("vident", u->GetVIdent());
+ request.Reply("host", u->host);
+ if (!u->vhost.empty())
+ request.Reply("vhost", u->vhost);
+ if (!u->chost.empty())
+ request.Reply("chost", u->chost);
+ request.Reply("ip", u->ip.addr());
+ request.Reply("timestamp", Anope::ToString(u->timestamp));
+ request.Reply("signon", Anope::ToString(u->signon));
+ if (u->IsIdentified())
+ {
+ request.Reply("account", u->Account()->display);
+ if (u->Account()->o)
+ request.Reply("opertype", u->Account()->o->ot->GetName());
+ }
+
+ Anope::string channels;
+ for (User::ChanUserList::const_iterator it = u->chans.begin(); it != u->chans.end(); ++it)
+ {
+ ChanUserContainer *cc = it->second;
+ channels += cc->status.BuildModePrefixList() + cc->chan->name + " ";
+ }
+ if (!channels.empty())
+ {
+ channels.erase(channels.length() - 1);
+ request.Reply("channels", channels);
+ }
+ }
+ }
+
+ static void DoOperType(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ for (auto *ot : Config->MyOperTypes)
+ {
+ Anope::string perms;
+ for (const auto &priv : ot->GetPrivs())
+ perms += " " + priv;
+ for (const auto &command : ot->GetCommands())
+ perms += " " + command;
+ request.Reply(ot->GetName(), perms);
+ }
+ }
+
+ static void DoNotice(RPCServiceInterface *iface, HTTPClient *client, RPCRequest &request)
+ {
+ Anope::string from = request.data.size() > 0 ? request.data[0] : "";
+ Anope::string to = request.data.size() > 1 ? request.data[1] : "";
+ Anope::string message = request.data.size() > 2 ? request.data[2] : "";
+
+ BotInfo *bi = BotInfo::Find(from, true);
+ User *u = User::Find(to, true);
+
+ if (!bi || !u || message.empty())
+ return;
+
+ u->SendMessage(bi, message);
+ }
+};
+
+class ModuleRPCMain final
+ : public Module
+{
+ ServiceReference<RPCServiceInterface> rpc;
+
+ MyRPCEvent stats;
+
+public:
+ ModuleRPCMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), rpc("RPCServiceInterface", "rpc")
+ {
+ me = this;
+
+ if (!rpc)
+ throw ModuleException("Unable to find RPC interface, is jsonrpc/xmlrpc loaded?");
+
+ rpc->Register(&stats);
+ }
+
+ ~ModuleRPCMain() override
+ {
+ if (rpc)
+ rpc->Unregister(&stats);
+ }
+};
+
+MODULE_INIT(ModuleRPCMain)
diff --git a/modules/m_xmlrpc.cpp b/modules/rpc/xmlrpc.cpp
index 0088d778e..2ecf00410 100644
--- a/modules/m_xmlrpc.cpp
+++ b/modules/rpc/xmlrpc.cpp
@@ -7,10 +7,10 @@
*/
#include "module.h"
-#include "modules/xmlrpc.h"
+#include "modules/rpc.h"
#include "modules/httpd.h"
-static struct special_chars
+static struct special_chars final
{
Anope::string character;
Anope::string replace;
@@ -32,30 +32,32 @@ special[] = {
special_chars("", "")
};
-class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
+class MyXMLRPCServiceInterface final
+ : public RPCServiceInterface
+ , public HTTPPage
{
- std::deque<XMLRPCEvent *> events;
+ std::deque<RPCEvent *> events;
- public:
- MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : XMLRPCServiceInterface(creator, sname), HTTPPage("/xmlrpc", "text/xml") { }
+public:
+ MyXMLRPCServiceInterface(Module *creator, const Anope::string &sname) : RPCServiceInterface(creator, sname), HTTPPage("/xmlrpc", "text/xml") { }
- void Register(XMLRPCEvent *event) anope_override
+ void Register(RPCEvent *event) override
{
this->events.push_back(event);
}
- void Unregister(XMLRPCEvent *event) anope_override
+ void Unregister(RPCEvent *event) override
{
- std::deque<XMLRPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
+ std::deque<RPCEvent *>::iterator it = std::find(this->events.begin(), this->events.end(), event);
if (it != this->events.end())
this->events.erase(it);
}
- Anope::string Sanitize(const Anope::string &string) anope_override
+ static Anope::string Sanitize(const Anope::string &string)
{
Anope::string ret = string;
- for (int i = 0; special[i].character.empty() == false; ++i)
+ for (int i = 0; !special[i].character.empty(); ++i)
ret = ret.replace_all_cs(special[i].character, special[i].replace);
return ret;
}
@@ -63,7 +65,7 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
static Anope::string Unescape(const Anope::string &string)
{
Anope::string ret = string;
- for (int i = 0; special[i].character.empty() == false; ++i)
+ for (int i = 0; !special[i].character.empty(); ++i)
if (!special[i].replace.empty())
ret = ret.replace_all_cs(special[i].replace, special[i].character);
@@ -93,7 +95,7 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
return ret;
}
- private:
+private:
static bool GetData(Anope::string &content, Anope::string &tag, Anope::string &data)
{
if (content.empty())
@@ -144,15 +146,15 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
return !istag && !data.empty();
}
- public:
- bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override
+public:
+ bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) override
{
Anope::string content = message.content, tname, data;
- XMLRPCRequest request(reply);
+ RPCRequest request(reply);
while (GetData(content, tname, data))
{
- Log(LOG_DEBUG) << "m_xmlrpc: Tag name: " << tname << ", data: " << data;
+ Log(LOG_DEBUG) << "xmlrpc: Tag name: " << tname << ", data: " << data;
if (tname == "methodName")
request.name = data;
else if (tname == "name" && data == "id")
@@ -164,13 +166,11 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
request.data.push_back(data);
}
- for (unsigned i = 0; i < this->events.size(); ++i)
+ for (auto *e : this->events)
{
- XMLRPCEvent *e = this->events[i];
-
if (!e->Run(this, client, request))
return false;
- else if (!request.get_replies().empty())
+ else if (!request.GetReplies().empty())
{
this->Reply(request);
return true;
@@ -182,45 +182,92 @@ class MyXMLRPCServiceInterface : public XMLRPCServiceInterface, public HTTPPage
return true;
}
- void Reply(XMLRPCRequest &request) anope_override
+ void Reply(RPCRequest &request) override
{
if (!request.id.empty())
- request.reply("id", request.id);
+ request.Reply("id", request.id);
+
+ Anope::string xml =
+ "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
+ "<methodResponse>\n";
- Anope::string r = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<methodResponse>\n<params>\n<param>\n<value>\n<struct>\n";
- for (std::map<Anope::string, Anope::string>::const_iterator it = request.get_replies().begin(); it != request.get_replies().end(); ++it)
- r += "<member>\n<name>" + it->first + "</name>\n<value>\n<string>" + this->Sanitize(it->second) + "</string>\n</value>\n</member>\n";
- r += "</struct>\n</value>\n</param>\n</params>\n</methodResponse>";
+ if (request.GetError())
+ {
+ xml +=
+ "<fault>\n"
+ " <value>\n"
+ " <struct>\n"
+ " <member>\n"
+ " <name>faultCode</name>\n"
+ " <value>\n"
+ " <int>" + Anope::ToString(request.GetError()->first) + "</int>\n"
+ " </value>\n"
+ " </member>\n"
+ " <member>\n"
+ " <name>faultString</name>\n"
+ " <value>\n"
+ " <string>" + this->Sanitize(request.GetError()->second) + "</string>\n"
+ " </value>\n"
+ " </member>\n"
+ " </struct>\n"
+ " </value>\n"
+ "</fault>\n";
+ }
+ else
+ {
+ xml +=
+ "<params>\n"
+ " <param>\n"
+ " <value>\n"
+ " <struct>\n";
+ for (const auto &[name, value] : request.GetReplies())
+ {
+ xml +=
+ "<member>\n"
+ " <name>" + this->Sanitize(name) + "</name>\n"
+ " <value>\n"
+ " <string>" + this->Sanitize(value) + "</string>\n"
+ " </value>\n"
+ "</member>\n";
+ }
+ xml +=
+ " </struct>\n"
+ " </value>\n"
+ " </param>\n"
+ "</params>\n";
+ }
+ xml += "</methodResponse>";
- request.r.Write(r);
+ request.reply.Write(xml);
}
};
-class ModuleXMLRPC : public Module
+class ModuleXMLRPC final
+ : public Module
{
ServiceReference<HTTPProvider> httpref;
- public:
+public:
MyXMLRPCServiceInterface xmlrpcinterface;
ModuleXMLRPC(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
- xmlrpcinterface(this, "xmlrpc")
+ xmlrpcinterface(this, "rpc")
{
}
- ~ModuleXMLRPC()
+ ~ModuleXMLRPC() override
{
if (httpref)
httpref->UnregisterPage(&xmlrpcinterface);
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
if (httpref)
httpref->UnregisterPage(&xmlrpcinterface);
this->httpref = ServiceReference<HTTPProvider>("HTTPProvider", conf->GetModule(this)->Get<const Anope::string>("server", "httpd/main"));
if (!httpref)
- throw ConfigException("Unable to find http reference, is m_httpd loaded?");
+ throw ConfigException("Unable to find http reference, is httpd loaded?");
httpref->RegisterPage(&xmlrpcinterface);
}
};
diff --git a/modules/m_sasl.cpp b/modules/sasl.cpp
index 6c03e82d3..1c3fe717e 100644
--- a/modules/m_sasl.cpp
+++ b/modules/sasl.cpp
@@ -12,12 +12,13 @@
using namespace SASL;
-class Plain : public Mechanism
+class Plain final
+ : public Mechanism
{
- public:
+public:
Plain(Module *o) : Mechanism(o, "PLAIN") { }
- void ProcessMessage(Session *sess, const SASL::Message &m) anope_override
+ bool ProcessMessage(Session *sess, const SASL::Message &m) override
{
if (m.type == "S")
{
@@ -27,128 +28,162 @@ class Plain : public Mechanism
{
// message = [authzid] UTF8NUL authcid UTF8NUL passwd
Anope::string message;
- Anope::B64Decode(m.data, message);
+ Anope::B64Decode(m.data[0], message);
size_t zcsep = message.find('\0');
if (zcsep == Anope::string::npos)
- {
- sasl->Fail(sess);
- delete sess;
- return;
- }
+ return false;
size_t cpsep = message.find('\0', zcsep + 1);
if (cpsep == Anope::string::npos)
- {
- sasl->Fail(sess);
- delete sess;
- return;
- }
+ return false;
Anope::string authzid = message.substr(0, zcsep);
Anope::string authcid = message.substr(zcsep + 1, cpsep - zcsep - 1);
// We don't support having an authcid that is different to the authzid.
if (!authzid.empty() && authzid != authcid)
- {
- sasl->Fail(sess);
- delete sess;
- return;
- }
+ return false;
Anope::string passwd = message.substr(cpsep + 1);
if (authcid.empty() || passwd.empty() || !IRCD->IsNickValid(authcid) || passwd.find_first_of("\r\n\0") != Anope::string::npos)
- {
- sasl->Fail(sess);
- delete sess;
- return;
- }
+ return false;
SASL::IdentifyRequest *req = new SASL::IdentifyRequest(this->owner, m.source, authcid, passwd, sess->hostname, sess->ip);
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
req->Dispatch();
}
+ return true;
}
};
-class External : public Mechanism
+class External final
+ : public Mechanism
{
ServiceReference<CertService> certs;
- struct Session : SASL::Session
+ struct Session final
+ : SASL::Session
{
- Anope::string cert;
+ std::vector<Anope::string> certs;
Session(Mechanism *m, const Anope::string &u) : SASL::Session(m, u) { }
};
- public:
+public:
External(Module *o) : Mechanism(o, "EXTERNAL"), certs("CertService", "certs")
{
if (!IRCD || !IRCD->CanCertFP)
throw ModuleException("No CertFP");
}
- Session* CreateSession(const Anope::string &uid) anope_override
+ Session *CreateSession(const Anope::string &uid) override
{
return new Session(this, uid);
}
- void ProcessMessage(SASL::Session *sess, const SASL::Message &m) anope_override
+ bool ProcessMessage(SASL::Session *sess, const SASL::Message &m) override
{
Session *mysess = anope_dynamic_static_cast<Session *>(sess);
if (m.type == "S")
{
- mysess->cert = m.ext;
+ mysess->certs.assign(m.data.begin() + 1, m.data.end());
sasl->SendMessage(sess, "C", "+");
}
else if (m.type == "C")
{
- if (!certs || mysess->cert.empty())
- {
- sasl->Fail(sess);
- delete sess;
- return;
- }
+ if (!certs || mysess->certs.empty())
+ return false;
Anope::string user = "A user";
if (!mysess->hostname.empty() && !mysess->ip.empty())
user = mysess->hostname + " (" + mysess->ip + ")";
- NickCore *nc = certs->FindAccountFromCert(mysess->cert);
- if (!nc || nc->HasExt("NS_SUSPENDED") || nc->HasExt("UNCONFIRMED"))
+
+ for (auto it = mysess->certs.begin(); it != mysess->certs.end(); ++it)
{
- Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " failed to identify using certificate " << mysess->cert << " using SASL EXTERNAL";
- sasl->Fail(sess);
- delete sess;
- return;
+ auto *nc = certs->FindAccountFromCert(*it);
+ if (nc && !nc->HasExt("NS_SUSPENDED") && !nc->HasExt("UNCONFIRMED"))
+ {
+ // If we are using a fallback cert then upgrade it.
+ if (it != mysess->certs.begin())
+ {
+ auto *cl = nc->GetExt<NSCertList>("certificates");
+ if (cl)
+ cl->ReplaceCert(*it, mysess->certs[0]);
+ }
+
+ Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " identified to account " << nc->display << " using SASL EXTERNAL";
+ sasl->Succeed(sess, nc);
+ delete sess;
+ return true;
+ }
}
- Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " identified to account " << nc->display << " using SASL EXTERNAL";
- sasl->Succeed(sess, nc);
- delete sess;
+ Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " failed to identify using certificate " << mysess->certs.front() << " using SASL EXTERNAL";
+ return false;
+ }
+ return true;
+ }
+};
+
+class Anonymous final
+ : public Mechanism
+{
+public:
+ Anonymous(Module *o) : Mechanism(o, "ANONYMOUS") { }
+
+ bool ProcessMessage(Session *sess, const SASL::Message &m) override
+ {
+ if (m.type == "S")
+ {
+ sasl->SendMessage(sess, "C", "+");
}
+ else if (m.type == "C")
+ {
+ Anope::string decoded;
+ Anope::B64Decode(m.data[0], decoded);
+
+ Anope::string user = "A user";
+ if (!sess->hostname.empty() && !sess->ip.empty())
+ user = sess->hostname + " (" + sess->ip + ")";
+ if (!decoded.empty())
+ user += " [" + decoded + "]";
+
+ Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " unidentified using SASL ANONYMOUS";
+ sasl->Succeed(sess, nullptr);
+ }
+ return true;
}
};
-class SASLService : public SASL::Service, public Timer
+class SASLService final
+ : public SASL::Service
+ , public Timer
{
std::map<Anope::string, SASL::Session *> sessions;
- public:
- SASLService(Module *o) : SASL::Service(o), Timer(o, 60, Anope::CurTime, true) { }
+public:
+ SASLService(Module *o)
+ : SASL::Service(o)
+ , Timer(o, 60, true)
+ {
+ }
- ~SASLService()
+ ~SASLService() override
{
- for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end(); it++)
- delete it->second;
+ for (const auto &[_, session] : sessions)
+ delete session;
}
- void ProcessMessage(const SASL::Message &m) anope_override
+ void ProcessMessage(const SASL::Message &m) override
{
+ if (m.data.empty())
+ return; // Malformed.
+
if (m.target != "*")
{
Server *s = Server::Find(m.target);
@@ -160,11 +195,11 @@ class SASLService : public SASL::Service, public Timer
}
}
- Session* session = GetSession(m.source);
+ Session *session = GetSession(m.source);
if (m.type == "S")
{
- ServiceReference<Mechanism> mech("SASL::Mechanism", m.data);
+ ServiceReference<Mechanism> mech("SASL::Mechanism", m.data[0]);
if (!mech)
{
Session tmp(NULL, m.source);
@@ -204,15 +239,21 @@ class SASLService : public SASL::Service, public Timer
session = new Session(NULL, m.source);
sessions[m.source] = session;
}
- session->hostname = m.data;
- session->ip = m.ext;
+ session->hostname = m.data[0];
+ session->ip = m.data.size() > 1 ? m.data[1] : "";
}
if (session && session->mech)
- session->mech->ProcessMessage(session, m);
+ {
+ if (!session->mech->ProcessMessage(session, m))
+ {
+ Fail(session);
+ delete session;
+ }
+ }
}
- Anope::string GetAgent() anope_override
+ Anope::string GetAgent() override
{
Anope::string agent = Config->GetModule(Service::owner)->Get<Anope::string>("agent", "NickServ");
BotInfo *bi = Config->GetClient(agent);
@@ -221,7 +262,7 @@ class SASLService : public SASL::Service, public Timer
return agent;
}
- Session* GetSession(const Anope::string &uid) anope_override
+ Session *GetSession(const Anope::string &uid) override
{
std::map<Anope::string, Session *>::iterator it = sessions.find(uid);
if (it != sessions.end())
@@ -229,12 +270,12 @@ class SASLService : public SASL::Service, public Timer
return NULL;
}
- void RemoveSession(Session *sess) anope_override
+ void RemoveSession(Session *sess) override
{
sessions.erase(sess->uid);
}
- void DeleteSessions(Mechanism *mech, bool da) anope_override
+ void DeleteSessions(Mechanism *mech, bool da) override
{
for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end();)
{
@@ -248,50 +289,53 @@ class SASLService : public SASL::Service, public Timer
}
}
- void SendMessage(Session *session, const Anope::string &mtype, const Anope::string &data) anope_override
+ void SendMessage(Session *session, const Anope::string &mtype, const Anope::string &data) override
{
SASL::Message msg;
msg.source = this->GetAgent();
msg.target = session->uid;
msg.type = mtype;
- msg.data = data;
+ msg.data.push_back(data);
IRCD->SendSASLMessage(msg);
}
- void Succeed(Session *session, NickCore *nc) anope_override
+ void Succeed(Session *session, NickCore *nc) override
{
// If the user is already introduced then we log them in now.
// Otherwise, we send an SVSLOGIN to log them in later.
User *user = User::Find(session->uid);
- NickAlias *na = NickAlias::Find(nc->display);
+ NickAlias *na = nc ? nc->na : nullptr;
if (user)
{
- user->Identify(na);
+ if (na)
+ user->Identify(na);
+ else
+ user->Logout();
}
else
{
- IRCD->SendSVSLogin(session->uid, nc->display, na->GetVhostIdent(), na->GetVhostHost());
+ IRCD->SendSVSLogin(session->uid, na);
}
this->SendMessage(session, "D", "S");
}
- void Fail(Session *session) anope_override
+ void Fail(Session *session) override
{
this->SendMessage(session, "D", "F");
}
- void SendMechs(Session *session) anope_override
+ void SendMechs(Session *session) override
{
std::vector<Anope::string> mechs = Service::GetServiceKeys("SASL::Mechanism");
Anope::string buf;
- for (unsigned j = 0; j < mechs.size(); ++j)
- buf += "," + mechs[j];
+ for (const auto &mech : mechs)
+ buf += "," + mech;
this->SendMessage(session, "M", buf.empty() ? "" : buf.substr(1));
}
- void Tick(time_t) anope_override
+ void Tick() override
{
for (std::map<Anope::string, Session *>::iterator it = sessions.begin(); it != sessions.end();)
{
@@ -308,12 +352,14 @@ class SASLService : public SASL::Service, public Timer
}
};
-class ModuleSASL : public Module
+class ModuleSASL final
+ : public Module
{
SASLService sasl;
+ Anonymous anonymous;
Plain plain;
- External *external;
+ External *external = nullptr;
std::vector<Anope::string> mechs;
@@ -330,9 +376,9 @@ class ModuleSASL : public Module
IRCD->SendSASLMechanisms(mechs);
}
- public:
+public:
ModuleSASL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- sasl(this), plain(this), external(NULL)
+ sasl(this), anonymous(this), plain(this)
{
try
{
@@ -342,22 +388,22 @@ class ModuleSASL : public Module
catch (ModuleException &) { }
}
- ~ModuleSASL()
+ ~ModuleSASL() override
{
delete external;
}
- void OnModuleLoad(User *, Module *) anope_override
+ void OnModuleLoad(User *, Module *) override
{
CheckMechs();
}
- void OnModuleUnload(User *, Module *) anope_override
+ void OnModuleUnload(User *, Module *) override
{
CheckMechs();
}
- void OnPreUplinkSync(Server *) anope_override
+ void OnPreUplinkSync(Server *) override
{
// We have not yet sent a mechanism list so always do it here.
IRCD->SendSASLMechanisms(mechs);
diff --git a/modules/extra/m_sql_authentication.cpp b/modules/sql_authentication.cpp
index 0c7175fa9..9a6e76d05 100644
--- a/modules/extra/m_sql_authentication.cpp
+++ b/modules/sql_authentication.cpp
@@ -11,12 +11,13 @@
static Module *me;
-class SQLAuthenticationResult : public SQL::Interface
+class SQLAuthenticationResult final
+ : public SQL::Interface
{
Reference<User> user;
IdentifyRequest *req;
- public:
+public:
SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQL::Interface(me), user(u), req(r)
{
req->Hold(me);
@@ -27,16 +28,16 @@ class SQLAuthenticationResult : public SQL::Interface
req->Release(me);
}
- void OnResult(const SQL::Result &r) anope_override
+ void OnResult(const SQL::Result &r) override
{
if (r.Rows() == 0)
{
- Log(LOG_DEBUG) << "m_sql_authentication: Unsuccessful authentication for " << req->GetAccount();
+ Log(LOG_DEBUG) << "sql_authentication: Unsuccessful authentication for " << req->GetAccount();
delete this;
return;
}
- Log(LOG_DEBUG) << "m_sql_authentication: Successful authentication for " << req->GetAccount();
+ Log(LOG_DEBUG) << "sql_authentication: Successful authentication for " << req->GetAccount();
Anope::string email;
try
@@ -66,14 +67,15 @@ class SQLAuthenticationResult : public SQL::Interface
delete this;
}
- void OnError(const SQL::Result &r) anope_override
+ void OnError(const SQL::Result &r) override
{
- Log(this->owner) << "m_sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError();
+ Log(this->owner) << "sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError();
delete this;
}
};
-class ModuleSQLAuthentication : public Module
+class ModuleSQLAuthentication final
+ : public Module
{
Anope::string engine;
Anope::string query;
@@ -81,14 +83,14 @@ class ModuleSQLAuthentication : public Module
ServiceReference<SQL::Provider> SQL;
- public:
+public:
ModuleSQLAuthentication(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
me = this;
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
this->engine = config->Get<const Anope::string>("engine");
@@ -99,7 +101,7 @@ class ModuleSQLAuthentication : public Module
this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
}
- EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
{
if (!this->disable_reason.empty() && (command->name == "nickserv/register" || command->name == "nickserv/group"))
{
@@ -116,7 +118,7 @@ class ModuleSQLAuthentication : public Module
return EVENT_CONTINUE;
}
- void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override
+ void OnCheckAuthentication(User *u, IdentifyRequest *req) override
{
if (!this->SQL)
{
@@ -141,10 +143,10 @@ class ModuleSQLAuthentication : public Module
this->SQL->Run(new SQLAuthenticationResult(u, req), q);
- Log(LOG_DEBUG) << "m_sql_authentication: Checking authentication for " << req->GetAccount();
+ Log(LOG_DEBUG) << "sql_authentication: Checking authentication for " << req->GetAccount();
}
- void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+ void OnPreNickExpire(NickAlias *na, bool &expire) override
{
// We can't let nicks expire if they still have a group or
// there will be a zombie account left over that can't be
diff --git a/modules/extra/m_sql_log.cpp b/modules/sql_log.cpp
index 7a207725e..63200c2e4 100644
--- a/modules/extra/m_sql_log.cpp
+++ b/modules/sql_log.cpp
@@ -9,30 +9,30 @@
#include "module.h"
#include "modules/sql.h"
-class SQLLog : public Module
+class SQLLog final
+ : public Module
{
std::set<Anope::string> inited;
Anope::string table;
- public:
+public:
SQLLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR | EXTRA)
{
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
this->table = config->Get<const Anope::string>("table", "logs");
}
- void OnLogMessage(LogInfo *li, const Log *l, const Anope::string &msg) anope_override
+ void OnLogMessage(LogInfo *li, const Log *l, const Anope::string &msg) override
{
Anope::string ref_name;
ServiceReference<SQL::Provider> SQL;
- for (unsigned i = 0; i < li->targets.size(); ++i)
+ for (const auto &target : li->targets)
{
- const Anope::string &target = li->targets[i];
size_t sz = target.find("sql_log:");
if (!sz)
{
diff --git a/modules/extra/m_sql_oper.cpp b/modules/sql_oper.cpp
index 7ad5cd95a..0cdd82436 100644
--- a/modules/extra/m_sql_oper.cpp
+++ b/modules/sql_oper.cpp
@@ -9,16 +9,18 @@
#include "module.h"
#include "modules/sql.h"
-struct SQLOper : Oper
+struct SQLOper final
+ : Oper
{
SQLOper(const Anope::string &n, OperType *o) : Oper(n, o) { }
};
-class SQLOperResult : public SQL::Interface
+class SQLOperResult final
+ : public SQL::Interface
{
Reference<User> user;
- struct SQLOperResultDeleter
+ struct SQLOperResultDeleter final
{
SQLOperResult *res;
SQLOperResultDeleter(SQLOperResult *r) : res(r) { }
@@ -32,17 +34,17 @@ class SQLOperResult : public SQL::Interface
delete user->Account()->o;
user->Account()->o = NULL;
- Log(this->owner) << "m_sql_oper: Removed services operator from " << user->nick << " (" << user->Account()->display << ")";
+ Log(this->owner) << "sql_oper: Removed services operator from " << user->nick << " (" << user->Account()->display << ")";
BotInfo *OperServ = Config->GetClient("OperServ");
user->RemoveMode(OperServ, "OPER"); // Probably not set, just incase
}
}
- public:
+public:
SQLOperResult(Module *m, User *u) : SQL::Interface(m), user(u) { }
- void OnResult(const SQL::Result &r) anope_override
+ void OnResult(const SQL::Result &r) override
{
SQLOperResultDeleter d(this);
@@ -51,7 +53,7 @@ class SQLOperResult : public SQL::Interface
if (r.Rows() == 0)
{
- Log(LOG_DEBUG) << "m_sql_oper: Got 0 rows for " << user->nick;
+ Log(LOG_DEBUG) << "sql_oper: Got 0 rows for " << user->nick;
Deoper();
return;
}
@@ -67,7 +69,7 @@ class SQLOperResult : public SQL::Interface
return;
}
- Log(LOG_DEBUG) << "m_sql_oper: Got result for " << user->nick << ", opertype " << opertype;
+ Log(LOG_DEBUG) << "sql_oper: Got result for " << user->nick << ", opertype " << opertype;
Anope::string modes;
try
@@ -89,7 +91,7 @@ class SQLOperResult : public SQL::Interface
OperType *ot = OperType::Find(opertype);
if (ot == NULL)
{
- Log(this->owner) << "m_sql_oper: Oper " << user->nick << " has type " << opertype << ", but this opertype does not exist?";
+ Log(this->owner) << "sql_oper: Oper " << user->nick << " has type " << opertype << ", but this opertype does not exist?";
return;
}
@@ -101,7 +103,7 @@ class SQLOperResult : public SQL::Interface
if (!user->Account()->o || user->Account()->o->ot != ot)
{
- Log(this->owner) << "m_sql_oper: Tieing oper " << user->nick << " to type " << opertype;
+ Log(this->owner) << "sql_oper: Tieing oper " << user->nick << " to type " << opertype;
delete user->Account()->o;
user->Account()->o = new SQLOper(user->Account()->display, ot);
@@ -112,35 +114,34 @@ class SQLOperResult : public SQL::Interface
IRCD->SendOper(user);
if (!modes.empty())
- user->SetModes(OperServ, "%s", modes.c_str());
+ user->SetModes(OperServ, modes);
}
}
- void OnError(const SQL::Result &r) anope_override
+ void OnError(const SQL::Result &r) override
{
SQLOperResultDeleter d(this);
- Log(this->owner) << "m_sql_oper: Error executing query " << r.GetQuery().query << ": " << r.GetError();
+ Log(this->owner) << "sql_oper: Error executing query " << r.GetQuery().query << ": " << r.GetError();
}
};
-class ModuleSQLOper : public Module
+class ModuleSQLOper final
+ : public Module
{
Anope::string engine;
Anope::string query;
ServiceReference<SQL::Provider> SQL;
- public:
+public:
ModuleSQLOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
{
}
~ModuleSQLOper()
{
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- NickCore *nc = it->second;
-
if (nc->o && dynamic_cast<SQLOper *>(nc->o))
{
delete nc->o;
@@ -149,7 +150,7 @@ class ModuleSQLOper : public Module
}
}
- void OnReload(Configuration::Conf *conf) anope_override
+ void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *config = conf->GetModule(this);
@@ -159,7 +160,7 @@ class ModuleSQLOper : public Module
this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
}
- void OnNickIdentify(User *u) anope_override
+ void OnNickIdentify(User *u) override
{
if (!this->SQL)
{
@@ -173,7 +174,7 @@ class ModuleSQLOper : public Module
this->SQL->Run(new SQLOperResult(this, u), q);
- Log(LOG_DEBUG) << "m_sql_oper: Checking authentication for " << u->Account()->display;
+ Log(LOG_DEBUG) << "sql_oper: Checking authentication for " << u->Account()->display;
}
};
diff --git a/modules/third/language/CMakeLists.txt b/modules/third/language/CMakeLists.txt
index 85278f5be..b20982cfc 100644
--- a/modules/third/language/CMakeLists.txt
+++ b/modules/third/language/CMakeLists.txt
@@ -1,8 +1,8 @@
# Only do this if gettext is installed
-if(GETTEXT_FOUND)
+if(HAVE_LOCALIZATION)
# Get all of the .po files
file(GLOB LANG_SRCS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.*.po")
- sort_list(LANG_SRCS_PO)
+ list(SORT LANG_SRCS_PO)
foreach(LANG_PO ${LANG_SRCS_PO})
# Get the domain for this language file
@@ -26,13 +26,13 @@ if(GETTEXT_FOUND)
# Add to cpack ignored files if not on Windows.
if(NOT WIN32)
add_to_cpack_ignored_files("${LANG_MO}")
- endif(NOT WIN32)
+ endif()
# Install the new language file
install(CODE "FILE(MAKE_DIRECTORY ${LOCALE_DIR}/${LANG_LANG}/LC_MESSAGES/)")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG_MO} DESTINATION ${LOCALE_DIR}/${LANG_LANG}/LC_MESSAGES RENAME ${LANG_DOMAIN}.mo PERMISSIONS ${PERMS})
- endforeach(LANG_PO)
+ endforeach()
# Generate languages, depends on the mo files
add_custom_target(module_language DEPENDS ${LANG_SRCS_MO})
-endif(GETTEXT_FOUND)
+endif()
diff --git a/modules/webcpanel/CMakeLists.txt b/modules/webcpanel/CMakeLists.txt
index ea5a03b35..ab19f12b5 100644
--- a/modules/webcpanel/CMakeLists.txt
+++ b/modules/webcpanel/CMakeLists.txt
@@ -1,5 +1,5 @@
build_subdir(${CMAKE_CURRENT_SOURCE_DIR})
-install(DIRECTORY templates
- DESTINATION "${DB_DIR}/modules/webcpanel"
+install(DIRECTORY "templates/"
+ DESTINATION "${DATA_DIR}/webcpanel/templates/default"
)
diff --git a/modules/webcpanel/pages/chanserv/access.cpp b/modules/webcpanel/pages/chanserv/access.cpp
index 3cf9094cb..18a265152 100644
--- a/modules/webcpanel/pages/chanserv/access.cpp
+++ b/modules/webcpanel/pages/chanserv/access.cpp
@@ -6,7 +6,6 @@
*/
#include "../../webcpanel.h"
-#include "utils.h"
WebCPanel::ChanServ::Access::Access(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
@@ -48,16 +47,16 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
if (u_access.HasPriv("ACCESS_CHANGE") || has_priv)
{
- if (message.get_data["del"].empty() == false && message.get_data["mask"].empty() == false)
+ if (!message.get_data["del"].empty() && !message.get_data["mask"].empty())
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("DEL");
+ params.emplace_back("DEL");
params.push_back(message.get_data["mask"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/access", params, replacements);
}
- else if (message.post_data["mask"].empty() == false && message.post_data["access"].empty() == false && message.post_data["provider"].empty() == false)
+ else if (!message.post_data["mask"].empty() && !message.post_data["access"].empty() && !message.post_data["provider"].empty())
{
const Anope::string &provider = message.post_data["provider"];
@@ -65,7 +64,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("ADD");
+ params.emplace_back("ADD");
params.push_back(message.post_data["mask"]);
params.push_back(message.post_data["access"]);
@@ -75,7 +74,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("ADD");
+ params.emplace_back("ADD");
params.push_back(message.post_data["mask"]);
WebPanel::RunCommandWithName(client, na->nc, "ChanServ", "chanserv/xop", message.post_data["access"], params, replacements);
@@ -84,7 +83,7 @@ bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("MODIFY");
+ params.emplace_back("MODIFY");
params.push_back(message.post_data["mask"]);
params.push_back(message.post_data["access"]);
diff --git a/modules/webcpanel/pages/chanserv/access.h b/modules/webcpanel/pages/chanserv/access.h
deleted file mode 100644
index e99cc4fa6..000000000
--- a/modules/webcpanel/pages/chanserv/access.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace ChanServ
-{
-
-class Access : public WebPanelProtectedPage
-{
- public:
- Access(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-
- std::set<Anope::string> GetData() anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/chanserv/akick.cpp b/modules/webcpanel/pages/chanserv/akick.cpp
index 2454e4ef2..dbb9520be 100644
--- a/modules/webcpanel/pages/chanserv/akick.cpp
+++ b/modules/webcpanel/pages/chanserv/akick.cpp
@@ -6,7 +6,6 @@
*/
#include "../../webcpanel.h"
-#include "utils.h"
WebCPanel::ChanServ::Akick::Akick(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
@@ -46,22 +45,22 @@ bool WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st
replacements["AKICK"] = "YES";
- if (message.get_data["del"].empty() == false && message.get_data["mask"].empty() == false)
+ if (!message.get_data["del"].empty() && !message.get_data["mask"].empty())
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("DEL");
+ params.emplace_back("DEL");
params.push_back(message.get_data["mask"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/akick", params, replacements);
}
- else if (message.post_data["mask"].empty() == false)
+ else if (!message.post_data["mask"].empty())
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("ADD");
+ params.emplace_back("ADD");
params.push_back(message.post_data["mask"]);
- if (message.post_data["reason"].empty() == false)
+ if (!message.post_data["reason"].empty())
params.push_back(message.post_data["reason"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/akick", params, replacements);
diff --git a/modules/webcpanel/pages/chanserv/akick.h b/modules/webcpanel/pages/chanserv/akick.h
deleted file mode 100644
index da94c54d3..000000000
--- a/modules/webcpanel/pages/chanserv/akick.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace ChanServ
-{
-
-class Akick : public WebPanelProtectedPage
-{
- public:
- Akick(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-
- std::set<Anope::string> GetData() anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/chanserv/chanserv.h b/modules/webcpanel/pages/chanserv/chanserv.h
new file mode 100644
index 000000000..6740880af
--- /dev/null
+++ b/modules/webcpanel/pages/chanserv/chanserv.h
@@ -0,0 +1,72 @@
+/*
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+namespace WebCPanel::ChanServ
+{
+ class Access;
+ class Akick;
+ class Drop;
+ class Info;
+ class Modes;
+ class Set;
+
+ extern void BuildChanList(NickAlias *, TemplateFileServer::Replacements &);
+}
+
+class WebCPanel::ChanServ::Access final
+ : public WebPanelProtectedPage
+{
+public:
+ Access(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+ std::set<Anope::string> GetData() override;
+};
+
+class WebCPanel::ChanServ::Akick final
+ : public WebPanelProtectedPage
+{
+public:
+ Akick(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+ std::set<Anope::string> GetData() override;
+};
+
+class WebCPanel::ChanServ::Drop final
+ : public WebPanelProtectedPage
+{
+public:
+ Drop(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+};
+
+class WebCPanel::ChanServ::Info final
+ : public WebPanelProtectedPage
+{
+public:
+ Info(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+};
+
+class WebCPanel::ChanServ::Modes final
+ : public WebPanelProtectedPage
+{
+public:
+ Modes(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+ std::set<Anope::string> GetData() override;
+};
+
+class WebCPanel::ChanServ::Set final
+ : public WebPanelProtectedPage
+{
+public:
+ Set(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+ std::set<Anope::string> GetData() override;
+};
diff --git a/modules/webcpanel/pages/chanserv/drop.cpp b/modules/webcpanel/pages/chanserv/drop.cpp
index 35975fc0d..877054bae 100644
--- a/modules/webcpanel/pages/chanserv/drop.cpp
+++ b/modules/webcpanel/pages/chanserv/drop.cpp
@@ -6,7 +6,6 @@
*/
#include "../../webcpanel.h"
-#include "utils.h"
WebCPanel::ChanServ::Drop::Drop(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage (cat, u)
{
@@ -33,9 +32,8 @@ bool WebCPanel::ChanServ::Drop::OnRequest(HTTPProvider *server, const Anope::str
std::deque<ChannelInfo *> queue;
na->nc->GetChannelReferences(queue);
- for (unsigned i = 0; i < queue.size(); ++i)
+ for (auto *ci : queue)
{
- ChannelInfo *ci = queue[i];
if ((ci->HasExt("SECUREFOUNDER") ? ci->AccessFor(na->nc).founder : ci->AccessFor(na->nc).HasPriv("FOUNDER")) || (na->nc->IsServicesOper() && na->nc->o->ot->HasCommand("chanserv/drop")))
{
replacements["CHANNEL_NAMES"] = ci->name;
diff --git a/modules/webcpanel/pages/chanserv/drop.h b/modules/webcpanel/pages/chanserv/drop.h
deleted file mode 100644
index 3319e4d93..000000000
--- a/modules/webcpanel/pages/chanserv/drop.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
- namespace ChanServ
- {
-
- class Drop : public WebPanelProtectedPage
- {
- public:
- Drop(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-
- };
-
- }
-
-}
diff --git a/modules/webcpanel/pages/chanserv/info.cpp b/modules/webcpanel/pages/chanserv/info.cpp
index 7aa3b7dda..75729a7d6 100644
--- a/modules/webcpanel/pages/chanserv/info.cpp
+++ b/modules/webcpanel/pages/chanserv/info.cpp
@@ -6,7 +6,6 @@
*/
#include "../../webcpanel.h"
-#include "utils.h"
WebCPanel::ChanServ::Info::Info(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
diff --git a/modules/webcpanel/pages/chanserv/info.h b/modules/webcpanel/pages/chanserv/info.h
deleted file mode 100644
index f3bbefaad..000000000
--- a/modules/webcpanel/pages/chanserv/info.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace ChanServ
-{
-
-class Info : public WebPanelProtectedPage
-{
- public:
- Info(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/chanserv/modes.cpp b/modules/webcpanel/pages/chanserv/modes.cpp
index 83ce1cef0..32510f39f 100644
--- a/modules/webcpanel/pages/chanserv/modes.cpp
+++ b/modules/webcpanel/pages/chanserv/modes.cpp
@@ -6,7 +6,6 @@
*/
#include "../../webcpanel.h"
-#include "utils.h"
WebCPanel::ChanServ::Modes::Modes(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
@@ -57,10 +56,8 @@ bool WebCPanel::ChanServ::Modes::OnRequest(HTTPProvider *server, const Anope::st
replacements["MODE"] = "YES";
/* build a list with the names of all listmodes */
- for (unsigned i = 0; i < ModeManager::GetChannelModes().size(); ++i)
+ for (auto *cm : ModeManager::GetChannelModes())
{
- ChannelMode *cm = ModeManager::GetChannelModes()[i];
-
if (cm->type == MODE_LIST && cm->mchar)
replacements["LISTMODES"] = cm->mchar;
}
@@ -75,28 +72,27 @@ bool WebCPanel::ChanServ::Modes::OnRequest(HTTPProvider *server, const Anope::st
ChannelMode *cm = ModeManager::FindChannelModeByChar(mode[0]);
if (cm)
{
- if (message.get_data["del"].empty() == false && message.get_data["mask"].empty() == false)
+ if (!message.get_data["del"].empty() && !message.get_data["mask"].empty())
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("SET");
+ params.emplace_back("SET");
params.push_back("-" + Anope::string(cm->mchar));
params.push_back(message.get_data["mask"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/mode", params, replacements);
}
- else if (message.post_data["mask"].empty() == false)
+ else if (!message.post_data["mask"].empty())
{
std::vector<Anope::string> params;
params.push_back(ci->name);
- params.push_back("SET");
+ params.emplace_back("SET");
params.push_back("+" + Anope::string(cm->mchar));
params.push_back(message.post_data["mask"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "ChanServ", "chanserv/mode", params, replacements);
}
- std::vector<Anope::string> v = c->GetModeList(cm->name);
- for (unsigned int i = 0; i < v.size(); ++i)
- replacements["MASKS"] = v[i];
+ for (const auto &mask : c->GetModeList(cm->name))
+ replacements["MASKS"] = mask;
}
Page.Serve(server, page_name, client, message, reply, replacements);
diff --git a/modules/webcpanel/pages/chanserv/modes.h b/modules/webcpanel/pages/chanserv/modes.h
deleted file mode 100644
index bb7c263db..000000000
--- a/modules/webcpanel/pages/chanserv/modes.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace ChanServ
-{
-
-class Modes : public WebPanelProtectedPage
-{
- public:
- Modes(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-
- std::set<Anope::string> GetData() anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/chanserv/set.cpp b/modules/webcpanel/pages/chanserv/set.cpp
index 81cc7f940..fbf6ff34a 100644
--- a/modules/webcpanel/pages/chanserv/set.cpp
+++ b/modules/webcpanel/pages/chanserv/set.cpp
@@ -6,7 +6,6 @@
*/
#include "../../webcpanel.h"
-#include "utils.h"
WebCPanel::ChanServ::Set::Set(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
@@ -42,7 +41,7 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
can_set = true;
}
- if (can_set && message.post_data.empty() == false)
+ if (can_set && !message.post_data.empty())
{
if (ci->HasExt("KEEPTOPIC") != message.post_data.count("keeptopic"))
{
@@ -76,14 +75,6 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
ci->Shrink<bool>("RESTRICTED");
replacements["MESSAGES"] = "Restricted updated";
}
- if (ci->HasExt("CS_SECURE") != message.post_data.count("secure"))
- {
- if (!ci->HasExt("CS_SECURE"))
- ci->Extend<bool>("CS_SECURE");
- else
- ci->Shrink<bool>("CS_SECURE");
- replacements["MESSAGES"] = "Secure updated";
- }
if (ci->HasExt("SECUREOPS") != message.post_data.count("secureops"))
{
if (!ci->HasExt("SECUREOPS"))
@@ -132,9 +123,6 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
if (ci->HasExt("RESTRICTED"))
replacements["RESTRICTED"];
- if (ci->HasExt("CS_SECURE"))
- replacements["SECURE"];
-
if (ci->HasExt("SECUREOPS"))
replacements["SECUREOPS"];
diff --git a/modules/webcpanel/pages/chanserv/set.h b/modules/webcpanel/pages/chanserv/set.h
deleted file mode 100644
index 22b01b8b3..000000000
--- a/modules/webcpanel/pages/chanserv/set.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace ChanServ
-{
-
-class Set : public WebPanelProtectedPage
-{
- public:
- Set(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-
- std::set<Anope::string> GetData() anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/chanserv/utils.cpp b/modules/webcpanel/pages/chanserv/utils.cpp
index 407bb8e11..c1eafcf8b 100644
--- a/modules/webcpanel/pages/chanserv/utils.cpp
+++ b/modules/webcpanel/pages/chanserv/utils.cpp
@@ -27,10 +27,8 @@ void BuildChanList(NickAlias *na, TemplateFileServer::Replacements &replacements
na->nc->GetChannelReferences(queue);
std::sort(queue.begin(), queue.end(), ChannelSort);
- for (unsigned i = 0; i < queue.size(); ++i)
+ for (auto *ci : queue)
{
- ChannelInfo *ci = queue[i];
-
if (na->nc != ci->GetFounder() && ci->AccessFor(na->nc).empty())
continue;
diff --git a/modules/webcpanel/pages/chanserv/utils.h b/modules/webcpanel/pages/chanserv/utils.h
deleted file mode 100644
index 7b6dbf846..000000000
--- a/modules/webcpanel/pages/chanserv/utils.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace ChanServ
-{
-
-extern void BuildChanList(NickAlias *, TemplateFileServer::Replacements &);
-
-}
-
-}
diff --git a/modules/webcpanel/pages/confirm.h b/modules/webcpanel/pages/confirm.h
index 10ff36a8a..fa25ab0b1 100644
--- a/modules/webcpanel/pages/confirm.h
+++ b/modules/webcpanel/pages/confirm.h
@@ -5,17 +5,20 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "modules/httpd.h"
namespace WebCPanel
{
-class Confirm : public WebPanelPage
+class Confirm final
+ : public WebPanelPage
{
- public:
+public:
Confirm(const Anope::string &u) : WebPanelPage(u) { }
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) override;
};
}
diff --git a/modules/webcpanel/pages/hostserv/request.h b/modules/webcpanel/pages/hostserv/hostserv.h
index 6dacddaac..5473f60a9 100644
--- a/modules/webcpanel/pages/hostserv/request.h
+++ b/modules/webcpanel/pages/hostserv/hostserv.h
@@ -5,20 +5,17 @@
* Please read COPYING and README for further details.
*/
-namespace WebCPanel
-{
+#pragma once
-namespace HostServ
+namespace WebCPanel::HostServ
{
+ class Request;
+}
-class Request : public WebPanelProtectedPage
+class WebCPanel::HostServ::Request final
+ : public WebPanelProtectedPage
{
- public:
+public:
Request(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/hostserv/request.cpp b/modules/webcpanel/pages/hostserv/request.cpp
index 06d51ce48..35bc61610 100644
--- a/modules/webcpanel/pages/hostserv/request.cpp
+++ b/modules/webcpanel/pages/hostserv/request.cpp
@@ -21,13 +21,8 @@ bool WebCPanel::HostServ::Request::OnRequest(HTTPProvider *server, const Anope::
WebPanel::RunCommand(client, na->nc->display, na->nc, "HostServ", "hostserv/request", params, replacements, "CMDR");
}
- if (na->HasVhost())
- {
- if (na->GetVhostIdent().empty() == false)
- replacements["VHOST"] = na->GetVhostIdent() + "@" + na->GetVhostHost();
- else
- replacements["VHOST"] = na->GetVhostHost();
- }
+ if (na->HasVHost())
+ replacements["VHOST"] = na->GetVHostMask();
if (ServiceReference<Command>("Command", "hostserv/request"))
replacements["CAN_REQUEST"] = "YES";
TemplateFileServer page("hostserv/request.html");
diff --git a/modules/webcpanel/pages/index.cpp b/modules/webcpanel/pages/index.cpp
index 401c8748b..7b9a65c18 100644
--- a/modules/webcpanel/pages/index.cpp
+++ b/modules/webcpanel/pages/index.cpp
@@ -7,7 +7,8 @@
#include "../webcpanel.h"
-class WebpanelRequest : public IdentifyRequest
+class WebpanelRequest final
+ : public IdentifyRequest
{
HTTPReply reply;
HTTPMessage message;
@@ -16,10 +17,10 @@ class WebpanelRequest : public IdentifyRequest
Reference<HTTPClient> client;
TemplateFileServer::Replacements replacements;
- public:
+public:
WebpanelRequest(Module *o, HTTPReply &r, HTTPMessage &m, HTTPProvider *s, const Anope::string &p_n, HTTPClient *c, TemplateFileServer::Replacements &re, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(o, user, pass), reply(r), message(m), server(s), page_name(p_n), client(c), replacements(re) { }
- void OnSuccess() anope_override
+ void OnSuccess() override
{
if (!client || !server)
return;
@@ -49,7 +50,7 @@ class WebpanelRequest : public IdentifyRequest
{
char c;
do
- c = 48 + (rand() % 75);
+ c = 48 + (Anope::RandomNumber() % 75);
while (!isalnum(c));
id += c;
}
@@ -60,15 +61,15 @@ class WebpanelRequest : public IdentifyRequest
{
HTTPReply::cookie c;
- c.push_back(std::make_pair("account", na->nick));
- c.push_back(std::make_pair("Path", "/"));
+ c.emplace_back("account", na->nick);
+ c.emplace_back("Path", "/");
reply.cookies.push_back(c);
}
{
HTTPReply::cookie c;
- c.push_back(std::make_pair("id", id));
- c.push_back(std::make_pair("Path", "/"));
+ c.emplace_back("id", id);
+ c.emplace_back("Path", "/");
reply.cookies.push_back(c);
}
@@ -78,7 +79,7 @@ class WebpanelRequest : public IdentifyRequest
client->SendReply(&reply);
}
- void OnFail() anope_override
+ void OnFail() override
{
if (!client || !server)
return;
@@ -102,7 +103,7 @@ bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page
// Rate limit check.
Anope::string ip = client->clientaddr.addr();
- Anope::hash_map<time_t>::iterator it = last_login_attempt.find(ip);
+ Anope::unordered_map<time_t>::iterator it = last_login_attempt.find(ip);
if (it != last_login_attempt.end())
{
time_t last_time = it->second;
@@ -125,7 +126,7 @@ bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page
last_login_attempt[ip] = Anope::CurTime;
- WebpanelRequest *req = new WebpanelRequest(me, reply, message, server, page_name, client, replacements, user, pass);
+ auto *req = new WebpanelRequest(me, reply, message, server, page_name, client, replacements, user, pass);
FOREACH_MOD(OnCheckAuthentication, (NULL, req));
req->Dispatch();
return false;
diff --git a/modules/webcpanel/pages/index.h b/modules/webcpanel/pages/index.h
index 6f63298ee..b307404cf 100644
--- a/modules/webcpanel/pages/index.h
+++ b/modules/webcpanel/pages/index.h
@@ -5,22 +5,25 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "modules/httpd.h"
namespace WebCPanel
{
-class Index : public WebPanelPage
+class Index final
+ : public WebPanelPage
{
static const int FLUSH_TIME = 60;
- Anope::hash_map<time_t> last_login_attempt;
- time_t last_clear;
+ Anope::unordered_map<time_t> last_login_attempt;
+ time_t last_clear = 0;
- public:
- Index(const Anope::string &u) : WebPanelPage(u), last_clear(0) { }
+public:
+ Index(const Anope::string &u) : WebPanelPage(u) { }
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) override;
};
}
diff --git a/modules/webcpanel/pages/logout.h b/modules/webcpanel/pages/logout.h
index 72f83d851..be0e0688a 100644
--- a/modules/webcpanel/pages/logout.h
+++ b/modules/webcpanel/pages/logout.h
@@ -5,15 +5,18 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
namespace WebCPanel
{
-class Logout : public WebPanelProtectedPage
+class Logout final
+ : public WebPanelProtectedPage
{
- public:
+public:
Logout(const Anope::string &u);
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
};
}
diff --git a/modules/webcpanel/pages/memoserv/memos.cpp b/modules/webcpanel/pages/memoserv/memos.cpp
index 44d951a86..f597f105e 100644
--- a/modules/webcpanel/pages/memoserv/memos.cpp
+++ b/modules/webcpanel/pages/memoserv/memos.cpp
@@ -18,9 +18,9 @@ bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
const MemoInfo *mi;
Memo *m;
- for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
+ for (const auto &[_, ci2] : *RegisteredChannelList)
{
- ci = it->second;
+ ci = ci2;
if (ci->AccessFor(na->nc).HasPriv("MEMO"))
{
@@ -73,14 +73,10 @@ bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
std::vector<Anope::string> params;
int number = -1;
- try
- {
- number = convertTo<int>(message.get_data["number"]);
- }
- catch (const ConvertException &ex)
- {
+ if (auto num = Anope::TryConvert<int>(message.get_data["number"]))
+ number = num.value();
+ else
replacements["MESSAGES"] = "ERROR - invalid parameter for NUMBER";
- }
if (number > 0)
{
@@ -98,7 +94,7 @@ bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st
for (unsigned i = 0; i < mi->memos->size(); ++i)
{
m = mi->GetMemo(i);
- replacements["NUMBER"] = stringify(i+1);
+ replacements["NUMBER"] = Anope::ToString(i+1);
replacements["SENDER"] = m->sender;
replacements["TIME"] = Anope::strftime(m->time);
replacements["TEXT"] = m->text;
diff --git a/modules/webcpanel/pages/memoserv/memos.h b/modules/webcpanel/pages/memoserv/memoserv.h
index 5db55faa6..b984b9fca 100644
--- a/modules/webcpanel/pages/memoserv/memos.h
+++ b/modules/webcpanel/pages/memoserv/memoserv.h
@@ -5,20 +5,17 @@
* Please read COPYING and README for further details.
*/
-namespace WebCPanel
-{
+#pragma once
-namespace MemoServ
+namespace WebCPanel::MemoServ
{
+ class Memos;
+}
-class Memos : public WebPanelProtectedPage
+class WebCPanel::MemoServ::Memos final
+ : public WebPanelProtectedPage
{
- public:
+public:
Memos(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/nickserv/access.cpp b/modules/webcpanel/pages/nickserv/access.cpp
deleted file mode 100644
index f0ff358df..000000000
--- a/modules/webcpanel/pages/nickserv/access.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "../../webcpanel.h"
-
-WebCPanel::NickServ::Access::Access(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
-{
-}
-
-bool WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
-{
- if (message.post_data.count("access") > 0)
- {
- std::vector<Anope::string> params;
- params.push_back("ADD");
- params.push_back(message.post_data["access"]);
-
- WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
- }
- else if (message.get_data.count("del") > 0 && message.get_data.count("mask") > 0)
- {
- std::vector<Anope::string> params;
- params.push_back("DEL");
- params.push_back(message.get_data["mask"]);
-
- WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/access", params, replacements);
- }
-
- for (unsigned i = 0; i < na->nc->access.size(); ++i)
- replacements["ACCESS"] = na->nc->access[i];
-
- TemplateFileServer page("nickserv/access.html");
- page.Serve(server, page_name, client, message, reply, replacements);
- return true;
-}
diff --git a/modules/webcpanel/pages/nickserv/access.h b/modules/webcpanel/pages/nickserv/access.h
deleted file mode 100644
index e5ccbae1f..000000000
--- a/modules/webcpanel/pages/nickserv/access.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace NickServ
-{
-
-class Access : public WebPanelProtectedPage
-{
- public:
- Access(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/nickserv/alist.cpp b/modules/webcpanel/pages/nickserv/alist.cpp
index 0ecd172e7..0d8026124 100644
--- a/modules/webcpanel/pages/nickserv/alist.cpp
+++ b/modules/webcpanel/pages/nickserv/alist.cpp
@@ -24,15 +24,13 @@ bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st
int chan_count = 0;
- for (unsigned q = 0; q < queue.size(); ++q)
+ for (auto *ci : queue)
{
- ChannelInfo *ci = queue[q];
-
if (ci->GetFounder() == na->nc)
{
++chan_count;
- replacements["NUMBERS"] = stringify(chan_count);
+ replacements["NUMBERS"] = Anope::ToString(chan_count);
replacements["CHANNELS"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
replacements["ACCESSES"] = "Founder";
continue;
@@ -44,7 +42,7 @@ bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st
++chan_count;
- replacements["NUMBERS"] = stringify(chan_count);
+ replacements["NUMBERS"] = Anope::ToString(chan_count);
replacements["CHANNELS"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
const ChanAccess *highest = access.Highest();
diff --git a/modules/webcpanel/pages/nickserv/alist.h b/modules/webcpanel/pages/nickserv/alist.h
deleted file mode 100644
index f8e0979a3..000000000
--- a/modules/webcpanel/pages/nickserv/alist.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace NickServ
-{
-
-class Alist : public WebPanelProtectedPage
-{
- public:
- Alist(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/nickserv/cert.cpp b/modules/webcpanel/pages/nickserv/cert.cpp
index f9e69bd6b..51851e8d2 100644
--- a/modules/webcpanel/pages/nickserv/cert.cpp
+++ b/modules/webcpanel/pages/nickserv/cert.cpp
@@ -17,7 +17,7 @@ bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str
if (message.post_data.count("certfp") > 0)
{
std::vector<Anope::string> params;
- params.push_back("ADD");
+ params.emplace_back("ADD");
params.push_back(message.post_data["certfp"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
@@ -25,7 +25,7 @@ bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str
else if (message.get_data.count("del") > 0 && message.get_data.count("mask") > 0)
{
std::vector<Anope::string> params;
- params.push_back("DEL");
+ params.emplace_back("DEL");
params.push_back(message.get_data["mask"]);
WebPanel::RunCommand(client, na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
diff --git a/modules/webcpanel/pages/nickserv/cert.h b/modules/webcpanel/pages/nickserv/cert.h
deleted file mode 100644
index cc4b2762b..000000000
--- a/modules/webcpanel/pages/nickserv/cert.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace NickServ
-{
-
-class Cert : public WebPanelProtectedPage
-{
- public:
- Cert(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/nickserv/confirm.h b/modules/webcpanel/pages/nickserv/confirm.h
deleted file mode 100644
index 06668bc51..000000000
--- a/modules/webcpanel/pages/nickserv/confirm.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace NickServ
-{
-
-class Confirm : public WebPanelProtectedPage
-{
- public:
- Confirm(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/nickserv/info.cpp b/modules/webcpanel/pages/nickserv/info.cpp
index 10126b670..43241af14 100644
--- a/modules/webcpanel/pages/nickserv/info.cpp
+++ b/modules/webcpanel/pages/nickserv/info.cpp
@@ -13,7 +13,7 @@ WebCPanel::NickServ::Info::Info(const Anope::string &cat, const Anope::string &u
bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
{
- if (message.post_data.empty() == false)
+ if (!message.post_data.empty())
{
if (message.post_data.count("email") > 0)
{
@@ -56,14 +56,6 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
na->nc->Shrink<bool>("NS_PRIVATE");
replacements["MESSAGES"] = "Private updated";
}
- if (na->nc->HasExt("NS_SECURE") != message.post_data.count("secure"))
- {
- if (!na->nc->HasExt("NS_SECURE"))
- na->nc->Extend<bool>("NS_SECURE");
- else
- na->nc->Shrink<bool>("NS_SECURE");
- replacements["MESSAGES"] = "Secure updated";
- }
if (message.post_data["kill"] == "on" && !na->nc->HasExt("KILLPROTECT"))
{
na->nc->Extend<bool>("KILLPROTECT");
@@ -82,19 +74,38 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
na->nc->Shrink<bool>("KILL_QUICK");
replacements["MESSAGES"] = "Kill updated";
}
+ if (na->nc->HasExt("NS_KEEP_MODES") != message.post_data.count("keepmodes"))
+ {
+ if (!na->nc->HasExt("NS_KEEP_MODES"))
+ na->nc->Extend<bool>("NS_KEEP_MODES");
+ else
+ na->nc->Shrink<bool>("NS_KEEP_MODES");
+ replacements["MESSAGES"] = "Keepmodes updated";
+ }
+ if (na->nc->HasExt("MSG") != message.post_data.count("msg"))
+ {
+ if (!na->nc->HasExt("MSG"))
+ na->nc->Extend<bool>("MSG");
+ else
+ na->nc->Shrink<bool>("MSG");
+ replacements["MESSAGES"] = "Message updated";
+ }
+ if (na->nc->HasExt("NEVEROP") != message.post_data.count("neverop"))
+ {
+ if (!na->nc->HasExt("NEVEROP"))
+ na->nc->Extend<bool>("NEVEROP");
+ else
+ na->nc->Shrink<bool>("NEVEROP");
+ replacements["MESSAGES"] = "Neverop updated";
+ }
}
replacements["DISPLAY"] = na->nc->display;
- if (na->nc->email.empty() == false)
+ if (!na->nc->email.empty())
replacements["EMAIL"] = na->nc->email;
- replacements["TIME_REGISTERED"] = Anope::strftime(na->time_registered, na->nc);
- if (na->HasVhost())
- {
- if (na->GetVhostIdent().empty() == false)
- replacements["VHOST"] = na->GetVhostIdent() + "@" + na->GetVhostHost();
- else
- replacements["VHOST"] = na->GetVhostHost();
- }
+ replacements["TIME_REGISTERED"] = Anope::strftime(na->nc->time_registered, na->nc);
+ if (na->HasVHost())
+ replacements["VHOST"] = na->GetVHostMask();
Anope::string *greet = na->nc->GetExt<Anope::string>("greet");
if (greet)
replacements["GREET"] = *greet;
@@ -102,14 +113,18 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
replacements["AUTOOP"];
if (na->nc->HasExt("NS_PRIVATE"))
replacements["PRIVATE"];
- if (na->nc->HasExt("NS_SECURE"))
- replacements["SECURE"];
if (na->nc->HasExt("KILLPROTECT"))
replacements["KILL_ON"];
if (na->nc->HasExt("KILL_QUICK"))
replacements["KILL_QUICK"];
if (!na->nc->HasExt("KILLPROTECT") && !na->nc->HasExt("KILL_QUICK"))
replacements["KILL_OFF"];
+ if (na->nc->HasExt("NS_KEEP_MODES"))
+ replacements["KEEPMODES"];
+ if (na->nc->HasExt("MSG"))
+ replacements["MSG"];
+ if (na->nc->HasExt("NEVEROP"))
+ replacements["NEVEROP"];
TemplateFileServer page("nickserv/info.html");
page.Serve(server, page_name, client, message, reply, replacements);
diff --git a/modules/webcpanel/pages/nickserv/info.h b/modules/webcpanel/pages/nickserv/info.h
deleted file mode 100644
index 1420acb48..000000000
--- a/modules/webcpanel/pages/nickserv/info.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * (C) 2003-2025 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-namespace WebCPanel
-{
-
-namespace NickServ
-{
-
-class Info : public WebPanelProtectedPage
-{
- public:
- Info(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
-};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/nickserv/nickserv.h b/modules/webcpanel/pages/nickserv/nickserv.h
new file mode 100644
index 000000000..240afdb5e
--- /dev/null
+++ b/modules/webcpanel/pages/nickserv/nickserv.h
@@ -0,0 +1,48 @@
+/*
+ * (C) 2003-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#pragma once
+
+namespace WebCPanel::NickServ
+{
+ class Alist;
+ class Cert;
+ class Confirm;
+ class Info;
+}
+
+class WebCPanel::NickServ::Alist final
+ : public WebPanelProtectedPage
+{
+public:
+ Alist(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+};
+
+class WebCPanel::NickServ::Cert final
+ : public WebPanelProtectedPage
+{
+public:
+ Cert(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+};
+
+class WebCPanel::NickServ::Confirm final
+ : public WebPanelProtectedPage
+{
+public:
+ Confirm(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+};
+
+class WebCPanel::NickServ::Info final
+ : public WebPanelProtectedPage
+{
+public:
+ Info(const Anope::string &cat, const Anope::string &u);
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
+};
diff --git a/modules/webcpanel/pages/operserv/akill.cpp b/modules/webcpanel/pages/operserv/akill.cpp
index e9720d2f5..df5806d13 100644
--- a/modules/webcpanel/pages/operserv/akill.cpp
+++ b/modules/webcpanel/pages/operserv/akill.cpp
@@ -29,18 +29,18 @@ bool WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::st
{
std::vector<Anope::string> params;
std::stringstream cmdstr;
- params.push_back("ADD");
+ params.emplace_back("ADD");
cmdstr << "+" << HTTPUtils::URLDecode(message.post_data["expiry"]);
cmdstr << " " << HTTPUtils::URLDecode(message.post_data["mask"]);
cmdstr << " " << HTTPUtils::URLDecode(message.post_data["reason"]);
- params.push_back(cmdstr.str());
+ params.emplace_back(cmdstr.str());
WebPanel::RunCommand(client, na->nc->display, na->nc, "OperServ", "operserv/akill", params, replacements);
}
if (message.get_data["del"] == "1" && message.get_data.count("number") > 0)
{
std::vector<Anope::string> params;
- params.push_back("DEL");
+ params.emplace_back("DEL");
params.push_back(HTTPUtils::URLDecode(message.get_data["number"]));
WebPanel::RunCommand(client, na->nc->display, na->nc, "OperServ", "operserv/akill", params, replacements);
}
@@ -48,7 +48,7 @@ bool WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::st
for (unsigned i = 0, end = akills->GetCount(); i < end; ++i)
{
const XLine *x = akills->GetEntry(i);
- replacements["NUMBER"] = stringify(i + 1);
+ replacements["NUMBER"] = Anope::ToString(i + 1);
replacements["HOST"] = x->mask;
replacements["SETTER"] = x->by;
replacements["TIME"] = Anope::strftime(x->created, NULL, true);
diff --git a/modules/webcpanel/pages/operserv/akill.h b/modules/webcpanel/pages/operserv/operserv.h
index bb338573d..2f9f56902 100644
--- a/modules/webcpanel/pages/operserv/akill.h
+++ b/modules/webcpanel/pages/operserv/operserv.h
@@ -5,20 +5,17 @@
* Please read COPYING and README for further details.
*/
-namespace WebCPanel
-{
+#pragma once
-namespace OperServ
+namespace WebCPanel::OperServ
{
+ class Akill;
+}
-class Akill : public WebPanelProtectedPage
+class WebCPanel::OperServ::Akill final
+ : public WebPanelProtectedPage
{
- public:
+public:
Akill(const Anope::string &cat, const Anope::string &u);
-
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) override;
};
-
-}
-
-}
diff --git a/modules/webcpanel/pages/register.h b/modules/webcpanel/pages/register.h
index 80ebd7cc1..103f10bd2 100644
--- a/modules/webcpanel/pages/register.h
+++ b/modules/webcpanel/pages/register.h
@@ -5,17 +5,20 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "modules/httpd.h"
namespace WebCPanel
{
-class Register : public WebPanelPage
+class Register final
+ : public WebPanelPage
{
- public:
+public:
Register(const Anope::string &u) : WebPanelPage(u) { }
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) override;
};
}
diff --git a/modules/webcpanel/static_fileserver.cpp b/modules/webcpanel/static_fileserver.cpp
index cd286dadc..78f1e47dd 100644
--- a/modules/webcpanel/static_fileserver.cpp
+++ b/modules/webcpanel/static_fileserver.cpp
@@ -6,8 +6,8 @@
*/
#include "webcpanel.h"
+#include <cerrno>
#include <fstream>
-#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/modules/webcpanel/static_fileserver.h b/modules/webcpanel/static_fileserver.h
index 23a4a2af0..506dcd13d 100644
--- a/modules/webcpanel/static_fileserver.h
+++ b/modules/webcpanel/static_fileserver.h
@@ -5,14 +5,17 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "modules/httpd.h"
/* A basic file server. Used for serving static content on disk. */
-class StaticFileServer : public HTTPPage
+class StaticFileServer final
+ : public HTTPPage
{
Anope::string file_name;
- public:
+public:
StaticFileServer(const Anope::string &f_n, const Anope::string &u, const Anope::string &c_t);
- bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override;
+ bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) override;
};
diff --git a/modules/webcpanel/template_fileserver.cpp b/modules/webcpanel/template_fileserver.cpp
index 57b865bc1..ec34d4af6 100644
--- a/modules/webcpanel/template_fileserver.cpp
+++ b/modules/webcpanel/template_fileserver.cpp
@@ -6,15 +6,15 @@
*/
#include "webcpanel.h"
+#include <cerrno>
#include <fstream>
#include <stack>
-#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-struct ForLoop
+struct ForLoop final
{
static std::vector<ForLoop> Stack;
@@ -25,28 +25,24 @@ struct ForLoop
ForLoop(size_t s, TemplateFileServer::Replacements &r, const std::vector<Anope::string> &v, const std::vector<Anope::string> &r_names) : start(s), vars(v)
{
- for (unsigned i = 0; i < r_names.size(); ++i)
- ranges.push_back(r.equal_range(r_names[i]));
+ for (const auto &r_name : r_names)
+ ranges.push_back(r.equal_range(r_name));
}
void increment(const TemplateFileServer::Replacements &r)
{
- for (unsigned i = 0; i < ranges.size(); ++i)
+ for (auto &[begin, end] : ranges)
{
- range &ra = ranges[i];
-
- if (ra.first != r.end() && ra.first != ra.second)
- ++ra.first;
+ if (begin != r.end() && begin != end)
+ ++begin;
}
}
bool finished(const TemplateFileServer::Replacements &r) const
{
- for (unsigned i = 0; i < ranges.size(); ++i)
+ for (const auto &[begin, end] : ranges)
{
- const range &ra = ranges[i];
-
- if (ra.first != r.end() && ra.first != ra.second)
+ if (begin != r.end() && begin != end)
return false;
}
@@ -186,7 +182,7 @@ void TemplateFileServer::Serve(HTTPProvider *server, const Anope::string &page_n
if (temp_variables.size() != real_variables.size())
Log() << "Invalid FOR in web template " << this->file_name << " variable mismatch";
else
- ForLoop::Stack.push_back(ForLoop(j + f, r, temp_variables, real_variables));
+ ForLoop::Stack.emplace_back(j + f, r, temp_variables, real_variables);
}
}
else if (content == "END FOR")
diff --git a/modules/webcpanel/template_fileserver.h b/modules/webcpanel/template_fileserver.h
index ca644d369..ae0bd08fa 100644
--- a/modules/webcpanel/template_fileserver.h
+++ b/modules/webcpanel/template_fileserver.h
@@ -5,18 +5,21 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "modules/httpd.h"
/* A basic file server. Used for serving non-static non-binary content on disk. */
-class TemplateFileServer
+class TemplateFileServer final
{
Anope::string file_name;
- public:
- struct Replacements : std::multimap<Anope::string, Anope::string>
+public:
+ struct Replacements final
+ : std::multimap<Anope::string, Anope::string>
{
- Anope::string& operator[](const Anope::string &key)
+ Anope::string &operator[](const Anope::string &key)
{
- return insert(std::make_pair(key, ""))->second;
+ return emplace(key, "")->second;
}
};
diff --git a/modules/webcpanel/templates/default/chanserv/access.html b/modules/webcpanel/templates/chanserv/access.html
index c50434f8a..6d719b46f 100644
--- a/modules/webcpanel/templates/default/chanserv/access.html
+++ b/modules/webcpanel/templates/chanserv/access.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
{INCLUDE chanserv/chanlist.html}
<div class="panel-heading">Access List</div>
<div class="panel-body">
@@ -10,7 +10,7 @@
{IF EQ ACCESS_LIST YES}
{IF EXISTS ACCESSES}
- <table id="tableNSAccess" class="table table-hover">
+ <table id="tableAccess" class="table table-hover">
<thead>
<tr>
<th>Mask</th>
@@ -74,4 +74,4 @@
{END IF}
{END IF}
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/chanserv/akick.html b/modules/webcpanel/templates/chanserv/akick.html
index ddfea546c..c0dcf522a 100644
--- a/modules/webcpanel/templates/default/chanserv/akick.html
+++ b/modules/webcpanel/templates/chanserv/akick.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
{INCLUDE chanserv/chanlist.html}
<div class="panel-heading">Akick List</div>
<div class="panel-body">
@@ -10,7 +10,7 @@
{IF EQ AKICK YES}
{IF EXISTS MASKS}
- <table id="tableNSAccess" class="table table-hover">
+ <table id="tableAccess" class="table table-hover">
<thead>
<tr>
<th>Mask</th>
@@ -58,4 +58,4 @@
</form>
{END IF}
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/chanserv/chanlist.html b/modules/webcpanel/templates/chanserv/chanlist.html
index 8f00f02ac..8f00f02ac 100644
--- a/modules/webcpanel/templates/default/chanserv/chanlist.html
+++ b/modules/webcpanel/templates/chanserv/chanlist.html
diff --git a/modules/webcpanel/templates/default/chanserv/drop.html b/modules/webcpanel/templates/chanserv/drop.html
index c28eb051a..3a160dbb1 100644
--- a/modules/webcpanel/templates/default/chanserv/drop.html
+++ b/modules/webcpanel/templates/chanserv/drop.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
{INCLUDE chanserv/chanlist.html}
<div class="panel-heading">Channels you can drop</div>
<div class="panel-body">
@@ -29,4 +29,4 @@
</div>
{END IF}
</div>
-{INCLUDE footer.html} \ No newline at end of file
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/chanserv/main.html b/modules/webcpanel/templates/chanserv/main.html
new file mode 100644
index 000000000..6bfd05983
--- /dev/null
+++ b/modules/webcpanel/templates/chanserv/main.html
@@ -0,0 +1,3 @@
+{INCLUDE layout/header.loggedin.html}
+{INCLUDE chanserv/chanlist.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/chanserv/modes.html b/modules/webcpanel/templates/chanserv/modes.html
index 3c7fe7ab3..bb017bca9 100644
--- a/modules/webcpanel/templates/default/chanserv/modes.html
+++ b/modules/webcpanel/templates/chanserv/modes.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
{INCLUDE chanserv/chanlist.html}
<div class="panel-heading">Channel Mode List</div>
<div class="panel-body">
@@ -15,7 +15,7 @@
<br>
{IF EXISTS MASKS}
- <table id="tableNSAccess" class="table table-hover">
+ <table id="tableAccess" class="table table-hover">
<thead>
<tr>
<th>Mask</th>
@@ -53,4 +53,4 @@
</form>
{END IF}
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/chanserv/set.html b/modules/webcpanel/templates/chanserv/set.html
index 9437ca71a..3c63294ac 100644
--- a/modules/webcpanel/templates/default/chanserv/set.html
+++ b/modules/webcpanel/templates/chanserv/set.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
{INCLUDE chanserv/chanlist.html}
<div class="panel-heading">Channel Information</div>
<div class="panel-body">
@@ -65,10 +65,6 @@
<td><input type="checkbox" name="restricted" value="on" {IF EXISTS RESTRICTED}checked{END IF}></td>
</tr>
<tr>
- <td>Secure</td>
- <td><input type="checkbox" name="secure" value="on" {IF EXISTS SECURE}checked{END IF}></td>
- </tr>
- <tr>
<td>Secure Ops</td>
<td><input type="checkbox" name="secureops" value="on" {IF EXISTS SECUREOPS}checked{END IF}></td>
</tr>
@@ -90,4 +86,4 @@
{END IF}
{END IF}
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/confirm.html b/modules/webcpanel/templates/confirm.html
new file mode 100644
index 000000000..4b5f08c67
--- /dev/null
+++ b/modules/webcpanel/templates/confirm.html
@@ -0,0 +1,22 @@
+{INCLUDE layout/header.html}
+ <div class="row">
+ <div class="col-lg-offset-4 col-lg-4">
+ <a href="/">
+ <img src="/static/logo.png" class="img-responsive">
+ </a>
+ <a href="/" class="btn btn-lg btn-default btn-block">Back Home</a>
+
+ <h1 class="form-signin-heading">Register</h1>
+
+ {IF EXISTS MESSAGES}
+ <div class="alert alert-warning">
+ {FOR M IN MESSAGES}
+ {M}<br/>
+ {END FOR}
+ </div>
+ {END IF}
+
+ <a href="/register" class="btn btn-lg btn-default btn-block">Retry</a>
+ </div>
+ </div>
+{INCLUDE layout/footer.html}
diff --git a/modules/webcpanel/templates/default/cubes.png b/modules/webcpanel/templates/cubes.png
index d75208db7..d75208db7 100644
--- a/modules/webcpanel/templates/default/cubes.png
+++ b/modules/webcpanel/templates/cubes.png
Binary files differ
diff --git a/modules/webcpanel/templates/default/chanserv/main.html b/modules/webcpanel/templates/default/chanserv/main.html
deleted file mode 100644
index e77626f31..000000000
--- a/modules/webcpanel/templates/default/chanserv/main.html
+++ /dev/null
@@ -1,3 +0,0 @@
-{INCLUDE header.html}
-{INCLUDE chanserv/chanlist.html}
-{INCLUDE footer.html}
diff --git a/modules/webcpanel/templates/default/confirm.html b/modules/webcpanel/templates/default/confirm.html
deleted file mode 100644
index 3ef3bf52d..000000000
--- a/modules/webcpanel/templates/default/confirm.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE html>
-<!--[if IE 7]> <html lang="en" class="ie7"> <![endif]-->
-<!--[if IE 8]> <html lang="en" class="ie8"> <![endif]-->
-<!--[if IE 9]> <html lang="en" class="ie9"> <![endif]-->
-<!--[if !IE]><!-->
-<html lang="en">
- <!--<![endif]-->
- <head>
- <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
- <link href="/static/style.css" media="screen" rel="stylesheet" type="text/css" />
- <!--[if lt IE 9]><script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script><![endif]-->
-
- <title>{TITLE}</title>
- </head>
- <body>
- <div id="frontPages" class="container">
- <div class="row">
- <div class="col-lg-offset-4 col-lg-4">
- <a href="/">
- <img src="/static/logo.png" class="img-responsive">
- </a>
- <a href="/" class="btn btn-lg btn-default btn-block">Back Home</a>
-
- <h1 class="form-signin-heading">Register</h1>
-
- {IF EXISTS MESSAGES}
- <div class="alert alert-warning">
- {FOR M IN MESSAGES}
- {M}<br/>
- {END FOR}
- </div>
- {END IF}
-
- <a href="/register" class="btn btn-lg btn-default btn-block">Retry</a>
- </div>
- </div>
-
- <br>
- <div class="row">
- <div class="col-lg-offset-3 col-lg-6">
- <div class="footer text-center">
- Anope IRC Services - &copy; 2013-2024 Anope Team - <a href="https://www.anope.org/">https://www.anope.org/</a>
- </div>
- </div>
- </div>
- </div>
-
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
- </body>
-</html>
diff --git a/modules/webcpanel/templates/default/footer.html b/modules/webcpanel/templates/default/footer.html
deleted file mode 100644
index 9fc3e5845..000000000
--- a/modules/webcpanel/templates/default/footer.html
+++ /dev/null
@@ -1,14 +0,0 @@
- <br>
- </div>
- </div>
- </div>
- <div class="row">
- <div class="col-lg-12">
- <div class="footer text-center">
- Anope IRC Services - &copy; 2013-2024 Anope Team - <a href="https://www.anope.org/">https://www.anope.org/</a>
- </div>
- </div>
- </div>
- </div>
- </body>
-</html>
diff --git a/modules/webcpanel/templates/default/login.html b/modules/webcpanel/templates/default/login.html
deleted file mode 100644
index 864d74897..000000000
--- a/modules/webcpanel/templates/default/login.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<!--[if IE 7]> <html lang="en" class="ie7"> <![endif]-->
-<!--[if IE 8]> <html lang="en" class="ie8"> <![endif]-->
-<!--[if IE 9]> <html lang="en" class="ie9"> <![endif]-->
-<!--[if !IE]><!-->
-<html lang="en">
- <!--<![endif]-->
- <head>
- <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
- <link href="/static/style.css" media="screen" rel="stylesheet" type="text/css" />
- <!--[if lt IE 9]><script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script><![endif]-->
-
- <title>{TITLE}</title>
- </head>
- <body>
- <div id="frontPages" class="container">
- <div class="row">
- <div class="col-lg-offset-4 col-lg-4">
- <a href="/">
- <img src="/static/logo.png" class="img-responsive">
- </a>
-
- <h1 class="form-signin-heading">Login <small>to continue</small></h1>
-
- {IF EXISTS INVALID_LOGIN}
- <div class="alert alert-danger">
- {INVALID_LOGIN}
- </div>
- {END IF}
-
- <form class="form-horizontal form-signin" action="/" method="post">
- <input type="text" name="username" class="form-control" placeholder="Username" required="required" autofocus
- style="margin-bottom: -1px; border-bottom-left-radius: 0; border-bottom-right-radius: 0;">
- <input type="password" name="password" class="form-control" placeholder="Password" required="required"
- style="margin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0;">
- <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
- <a class="btn btn-lg btn-warning btn-block" href="/register">Register</a>
- </form>
- </div>
- </div>
-
- <br>
- <div class="row">
- <div class="col-lg-offset-3 col-lg-6">
- <div class="footer text-center">
- Anope IRC Services - &copy; 2013-2024 Anope Team - <a href="https://www.anope.org/">https://www.anope.org/</a>
- </div>
- </div>
- </div>
- </div>
-
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
- </body>
-</html>
diff --git a/modules/webcpanel/templates/default/nickserv/access.html b/modules/webcpanel/templates/default/nickserv/access.html
deleted file mode 100644
index 6387da854..000000000
--- a/modules/webcpanel/templates/default/nickserv/access.html
+++ /dev/null
@@ -1,42 +0,0 @@
-{INCLUDE header.html}
- <div class="panel-heading">Nick access list</div>
- <div class="panel-body">
- {FOR M IN MESSAGES}
- <div class="alert alert-info">
- {M}<br>
- </div>
- {END FOR}
-
- {IF EXISTS ACCESS}
- <table id="tableNSAccess" class="table table-hover">
- <tbody>
- {FOR A IN ACCESS}
- <tr>
- <td class="col-lg-4">{A}</td>
- <td class="col-lg-8"><a href="/nickserv/access?mask={A}&del=1" class="btn btn-sm btn-danger">Delete</a></td>
- </tr>
- {END FOR}
- </tbody>
- </table>
- {ELSE}
- <em>Your access list is empty.</em>
- {END IF}
-
- <hr>
-
- <h4>Add an access entry</h4>
- <form class="form-horizontal" method="post" action="/nickserv/access">
- <div class="form-group">
- <label class="control-label col-lg-2" for="access">Hostmask:</label>
- <div class="col-lg-5">
- <input class="form-control" type="text" name="access" id="access" placeholder="Mask must be in the form user@host">
- </div>
- </div>
- <div class="form-group">
- <div class="col-lg-offset-2 col-lg-5">
- <button type="submit" class="btn btn-primary">Add</button>
- </div>
- </div>
- </form>
- </div>
-{INCLUDE footer.html}
diff --git a/modules/webcpanel/templates/default/favicon.ico b/modules/webcpanel/templates/favicon.ico
index be735614a..be735614a 100644
--- a/modules/webcpanel/templates/default/favicon.ico
+++ b/modules/webcpanel/templates/favicon.ico
Binary files differ
diff --git a/modules/webcpanel/templates/default/hostserv/request.html b/modules/webcpanel/templates/hostserv/request.html
index f557244d1..76bc0b11b 100644
--- a/modules/webcpanel/templates/default/hostserv/request.html
+++ b/modules/webcpanel/templates/hostserv/request.html
@@ -1,5 +1,5 @@
-{INCLUDE header.html}
- <div class="panel-heading">vHost Information</div>
+{INCLUDE layout/header.loggedin.html}
+ <div class="panel-heading">VHost Information</div>
<div class="panel-body">
{FOR M IN MESSAGES}
<div class="alert alert-info">
@@ -10,7 +10,7 @@
<table id="tableInfo" class="table table-hover">
<tbody>
<tr>
- <td>Your current vHost:</td>
+ <td>Your current VHost:</td>
<td>
{IF EXISTS VHOST}
{VHOST}
@@ -24,9 +24,9 @@
<tr>
<td>
{IF EXISTS VHOST}
- Request a new vHost
+ Request a new VHost
{ELSE}
- Request a vHost
+ Request a VHost
{END IF}
</td>
<form method="post" action="/hostserv/request">
@@ -36,10 +36,10 @@
</tr>
{ELSE}
<tr>
- <td colspan="2" class="text-center"><strong>vHost requests are disabled on this network.</strong></td>
+ <td colspan="2" class="text-center"><strong>VHost requests are disabled on this network.</strong></td>
</tr>
{END IF}
</tbody>
</table>
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/layout/footer.html b/modules/webcpanel/templates/layout/footer.html
new file mode 100644
index 000000000..4d0de1b9c
--- /dev/null
+++ b/modules/webcpanel/templates/layout/footer.html
@@ -0,0 +1,11 @@
+ <br>
+ <div class="row">
+ <div class="col-lg-12">
+ <div class="footer text-center">
+ <a href="https://www.anope.org/">Anope IRC Services &copy; 2013-2025 Anope Team</a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/modules/webcpanel/templates/layout/footer.loggedin.html b/modules/webcpanel/templates/layout/footer.loggedin.html
new file mode 100644
index 000000000..6a3a07542
--- /dev/null
+++ b/modules/webcpanel/templates/layout/footer.loggedin.html
@@ -0,0 +1,4 @@
+ </div>
+ </div>
+ </div>
+{INCLUDE layout/footer.html}
diff --git a/modules/webcpanel/templates/layout/header.html b/modules/webcpanel/templates/layout/header.html
new file mode 100644
index 000000000..8d473e75c
--- /dev/null
+++ b/modules/webcpanel/templates/layout/header.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
+ <link href="/static/style.css" media="screen" rel="stylesheet" type="text/css" />
+
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
+ <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
+
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>{TITLE}</title>
+ </head>
+ <body>
+ <div id="frontPages" class="container">
diff --git a/modules/webcpanel/templates/default/header.html b/modules/webcpanel/templates/layout/header.loggedin.html
index 0ccf477c5..e5b6e6d52 100644
--- a/modules/webcpanel/templates/default/header.html
+++ b/modules/webcpanel/templates/layout/header.loggedin.html
@@ -1,27 +1,4 @@
-<!DOCTYPE html>
-<!--[if IE 7]> <html lang="en" class="ie7"> <![endif]-->
-<!--[if IE 8]> <html lang="en" class="ie8"> <![endif]-->
-<!--[if IE 9]> <html lang="en" class="ie9"> <![endif]-->
-<!--[if !IE]><!-->
-<html lang="en">
-<!--<![endif]-->
- <head>
- <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
- <link href="/static/style.css" media="screen" rel="stylesheet" type="text/css" />
-
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
-
- <!--[if lt IE 9]>
- <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.2/html5shiv.js"></script>
- <script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.2.0/respond.js"></script>
- <![endif]-->
-
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>{TITLE}</title>
- </head>
- <body>
- <div id="frontPages" class="container">
+{INCLUDE layout/header.html}
<div class="navbar navbar-default">
<span class="navbar-brand" style="margin-top: -1px">Anope Web <small>Control Panel</small></span>
<ul class="nav navbar-nav">
diff --git a/modules/webcpanel/templates/login.html b/modules/webcpanel/templates/login.html
new file mode 100644
index 000000000..1c0692e69
--- /dev/null
+++ b/modules/webcpanel/templates/login.html
@@ -0,0 +1,26 @@
+{INCLUDE layout/header.html}
+ <div class="row">
+ <div class="col-lg-offset-4 col-lg-4">
+ <a href="/">
+ <img src="/static/logo.png" class="img-responsive">
+ </a>
+
+ <h1 class="form-signin-heading">Login <small>to continue</small></h1>
+
+ {IF EXISTS INVALID_LOGIN}
+ <div class="alert alert-danger">
+ {INVALID_LOGIN}
+ </div>
+ {END IF}
+
+ <form class="form-horizontal form-signin" action="/" method="post">
+ <input type="text" name="username" class="form-control" placeholder="Username" required="required" autofocus
+ style="margin-bottom: -1px; border-bottom-left-radius: 0; border-bottom-right-radius: 0;">
+ <input type="password" name="password" class="form-control" placeholder="Password" required="required"
+ style="margin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0;">
+ <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
+ <a class="btn btn-lg btn-warning btn-block" href="/register">Register</a>
+ </form>
+ </div>
+ </div>
+{INCLUDE layout/footer.html}
diff --git a/modules/webcpanel/templates/default/logo.png b/modules/webcpanel/templates/logo.png
index f7c2ff92a..f7c2ff92a 100644
--- a/modules/webcpanel/templates/default/logo.png
+++ b/modules/webcpanel/templates/logo.png
Binary files differ
diff --git a/modules/webcpanel/templates/default/memoserv/memos.html b/modules/webcpanel/templates/memoserv/memos.html
index b3b54d948..493835c5c 100644
--- a/modules/webcpanel/templates/default/memoserv/memos.html
+++ b/modules/webcpanel/templates/memoserv/memos.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
<div class="panel-heading">Memos List</div>
<div class="panel-body">
{FOR M IN MESSAGES}
@@ -109,4 +109,4 @@
</div>
{END IF}
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/nickserv/alist.html b/modules/webcpanel/templates/nickserv/alist.html
index f3b2e0124..2e3137d9b 100644
--- a/modules/webcpanel/templates/default/nickserv/alist.html
+++ b/modules/webcpanel/templates/nickserv/alist.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
<div class="panel-heading">Channel access list</div>
<div class="panel-body">
<table id="tableInfoNorm" class="table table-hover">
@@ -20,4 +20,4 @@
</tbody>
</table>
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/nickserv/cert.html b/modules/webcpanel/templates/nickserv/cert.html
index 6d41a44b4..af78d9ccc 100644
--- a/modules/webcpanel/templates/default/nickserv/cert.html
+++ b/modules/webcpanel/templates/nickserv/cert.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
<div class="panel-heading">Your certificate fingerprints</div>
<div class="panel-body">
{FOR M IN MESSAGES}
@@ -8,7 +8,7 @@
{END FOR}
{IF EXISTS CERTS}
- <table id="tableNSAccess" class="table table-hover">
+ <table id="tableAccess" class="table table-hover">
<tbody>
{FOR CERT IN CERTS}
<tr>
@@ -39,4 +39,4 @@
</div>
</form>
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/nickserv/confirm.html b/modules/webcpanel/templates/nickserv/confirm.html
index 66dbe34df..08c817ea5 100644
--- a/modules/webcpanel/templates/default/nickserv/confirm.html
+++ b/modules/webcpanel/templates/nickserv/confirm.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
<div class="panel-heading">Confirm your Email</div>
<div class="panel-body">
{FOR M IN MESSAGES}
@@ -26,4 +26,4 @@
</div>
</form>
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/nickserv/info.html b/modules/webcpanel/templates/nickserv/info.html
index 667c8b370..c713cd64c 100644
--- a/modules/webcpanel/templates/default/nickserv/info.html
+++ b/modules/webcpanel/templates/nickserv/info.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
<div class="panel-heading">Your account information</div>
<div class="panel-body">
{FOR M IN ERRORS}
@@ -22,7 +22,7 @@
</tr>
{IF EXISTS EMAIL}
<tr>
- <td>E-mail:</td>
+ <td>Email:</td>
<td>{EMAIL}</td>
</tr>
{END IF}
@@ -32,7 +32,7 @@
</tr>
{IF EXISTS VHOST}
<tr>
- <td>Vhost:</td>
+ <td>VHost:</td>
<td>{VHOST}</td>
</tr>
{END IF}
@@ -45,12 +45,20 @@
<td><input type="checkbox" name="autoop" value="on" {IF EXISTS AUTOOP}checked{END IF}></td>
</tr>
<tr>
- <td>Private:</td>
- <td><input type="checkbox" name="private" value="on" {IF EXISTS PRIVATE}checked{END IF}></td>
+ <td>Keep modes:</td>
+ <td><input type="checkbox" name="keepmodes" value="on" {IF EXISTS KEEPMODES}checked{END IF}></td>
+ </tr>
+ <tr>
+ <td>Message:</td>
+ <td><input type="checkbox" name="msg" value="on" {IF EXISTS MSG}checked{END IF}></td>
</tr>
<tr>
- <td>Secure:</td>
- <td><input type="checkbox" name="secure" value="on" {IF EXISTS SECURE}checked{END IF}></td>
+ <td>Never op:</td>
+ <td><input type="checkbox" name="neverop" value="on" {IF EXISTS NEVEROP}checked{END IF}></td>
+ </tr>
+ <tr>
+ <td>Private:</td>
+ <td><input type="checkbox" name="private" value="on" {IF EXISTS PRIVATE}checked{END IF}></td>
</tr>
<tr>
<td>Kill:</td>
@@ -69,4 +77,4 @@
</div>
</form>
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/operserv/akill.html b/modules/webcpanel/templates/operserv/akill.html
index ffc73f8e4..02fa6eeb5 100644
--- a/modules/webcpanel/templates/default/operserv/akill.html
+++ b/modules/webcpanel/templates/operserv/akill.html
@@ -1,4 +1,4 @@
-{INCLUDE header.html}
+{INCLUDE layout/header.loggedin.html}
<div class="panel-heading">Akill List</div>
<div class="panel-body">
{IF EXISTS NOACCESS}
@@ -20,7 +20,7 @@
{IF EXISTS AKILLS}
<em>{AKILLS}</em>
{ELSE}
- <table id="tableNSAccess" class="table table-hover">
+ <table id="tableAccess" class="table table-hover">
<thead>
<tr>
<th>Number</th>
@@ -74,4 +74,4 @@
</form>
{END IF}
</div>
-{INCLUDE footer.html}
+{INCLUDE layout/footer.loggedin.html}
diff --git a/modules/webcpanel/templates/default/register.html b/modules/webcpanel/templates/register.html
index e71d763f6..cfe3d10d8 100644
--- a/modules/webcpanel/templates/default/register.html
+++ b/modules/webcpanel/templates/register.html
@@ -1,19 +1,4 @@
-<!DOCTYPE html>
-<!--[if IE 7]> <html lang="en" class="ie7"> <![endif]-->
-<!--[if IE 8]> <html lang="en" class="ie8"> <![endif]-->
-<!--[if IE 9]> <html lang="en" class="ie9"> <![endif]-->
-<!--[if !IE]><!-->
-<html lang="en">
- <!--<![endif]-->
- <head>
- <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
- <link href="/static/style.css" media="screen" rel="stylesheet" type="text/css" />
- <!--[if lt IE 9]><script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script><![endif]-->
-
- <title>{TITLE}</title>
- </head>
- <body>
- <div id="frontPages" class="container">
+{INCLUDE layout/header.html}
<div class="row">
<div class="col-lg-offset-4 col-lg-4">
<a href="/">
@@ -48,18 +33,4 @@
</form>
</div>
</div>
-
- <br>
- <div class="row">
- <div class="col-lg-offset-3 col-lg-6">
- <div class="footer text-center">
- Anope IRC Services - &copy; 2013-2024 Anope Team - <a href="https://www.anope.org/">https://www.anope.org/</a>
- </div>
- </div>
- </div>
- </div>
-
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
- </body>
-</html>
+{INCLUDE layout/footer.html}
diff --git a/modules/webcpanel/templates/default/style.css b/modules/webcpanel/templates/style.css
index e425c3d8c..7b63cd632 100644
--- a/modules/webcpanel/templates/default/style.css
+++ b/modules/webcpanel/templates/style.css
@@ -108,18 +108,18 @@ h4 {
font-weight: normal;
}
-#tableNSAccess td {
+#tableAccess td {
vertical-align: middle;
}
-#tableNSAccess td:first-child {
+#tableAccess td:first-child {
padding-right: 10px;
text-align: left;
}
-#tableNSAccess td:last-child {
+#tableAccess td:last-child {
padding-right: 10px;
text-align: right;
}
-#tableNSAccess th small {
+#tableAccess th small {
font-weight: normal;
}
diff --git a/modules/webcpanel/webcpanel.cpp b/modules/webcpanel/webcpanel.cpp
index 821d51160..abeaa82b0 100644
--- a/modules/webcpanel/webcpanel.cpp
+++ b/modules/webcpanel/webcpanel.cpp
@@ -8,9 +8,10 @@
#include "webcpanel.h"
Module *me;
-Anope::string provider_name, template_name, template_base, page_title;
+Anope::string provider_name, template_base, page_title;
-class ModuleWebCPanel : public Module
+class ModuleWebCPanel final
+ : public Module
{
ServiceReference<HTTPProvider> provider;
Panel panel;
@@ -26,7 +27,6 @@ class ModuleWebCPanel : public Module
WebCPanel::NickServ::Info nickserv_info;
WebCPanel::NickServ::Cert nickserv_cert;
- WebCPanel::NickServ::Access nickserv_access;
WebCPanel::NickServ::Alist nickserv_alist;
WebCPanel::NickServ::Confirm nickserv_confirm;
@@ -44,13 +44,13 @@ class ModuleWebCPanel : public Module
WebCPanel::OperServ::Akill operserv_akill;
- public:
+public:
ModuleWebCPanel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
panel(this, "webcpanel"),
id(this, "webcpanel_id"), ip(this, "webcpanel_ip"), last_login(this, "webcpanel_last_login"),
style_css("style.css", "/static/style.css", "text/css"), logo_png("logo.png", "/static/logo.png", "image/png"), cubes_png("cubes.png", "/static/cubes.png", "image/png"), favicon_ico("favicon.ico", "/favicon.ico", "image/x-icon"),
index("/"), logout("/logout"), _register("/register"), confirm("/confirm"),
- nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"), nickserv_confirm("NickServ", "/nickserv/confirm"),
+ nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_alist("NickServ", "/nickserv/alist"), nickserv_confirm("NickServ", "/nickserv/confirm"),
chanserv_info("ChanServ", "/chanserv/info"), chanserv_set("ChanServ", "/chanserv/set"), chanserv_access("ChanServ", "/chanserv/access"), chanserv_akick("ChanServ", "/chanserv/akick"),
chanserv_modes("ChanServ", "/chanserv/modes"), chanserv_drop("ChanServ", "/chanserv/drop"), memoserv_memos("MemoServ", "/memoserv/memos"), hostserv_request("HostServ", "/hostserv/request"),
operserv_akill("OperServ", "/operserv/akill")
@@ -60,13 +60,12 @@ class ModuleWebCPanel : public Module
Configuration::Block *block = Config->GetModule(this);
provider_name = block->Get<const Anope::string>("server", "httpd/main");
- template_name = block->Get<const Anope::string>("template", "default");
- template_base = Anope::DataDir + "/modules/webcpanel/templates/" + template_name;
+ template_base = Anope::ExpandData(block->Get<const Anope::string>("template_dir", "webcpanel/templates/default"));
page_title = block->Get<const Anope::string>("title", "Anope IRC Services");
provider = ServiceReference<HTTPProvider>("HTTPProvider", provider_name);
if (!provider)
- throw ModuleException("Unable to find HTTPD provider. Is m_httpd loaded?");
+ throw ModuleException("Unable to find HTTPD provider. Is httpd loaded?");
provider->RegisterPage(&this->style_css);
provider->RegisterPage(&this->logo_png);
@@ -98,11 +97,6 @@ class ModuleWebCPanel : public Module
provider->RegisterPage(&this->nickserv_cert);
}
- ss.name = "Access";
- ss.url = "/nickserv/access";
- s.subsections.push_back(ss);
- provider->RegisterPage(&this->nickserv_access);
-
ss.name = "AList";
ss.url = "/nickserv/alist";
s.subsections.push_back(ss);
@@ -178,7 +172,7 @@ class ModuleWebCPanel : public Module
s.name = HostServ->nick;
SubSection ss;
- ss.name = "vHost Request";
+ ss.name = "VHost Request";
ss.url = "/hostserv/request";
s.subsections.push_back(ss);
provider->RegisterPage(&this->hostserv_request);
@@ -202,7 +196,7 @@ class ModuleWebCPanel : public Module
}
}
- ~ModuleWebCPanel()
+ ~ModuleWebCPanel() override
{
if (provider)
{
@@ -218,7 +212,6 @@ class ModuleWebCPanel : public Module
provider->UnregisterPage(&this->nickserv_info);
provider->UnregisterPage(&this->nickserv_cert);
- provider->UnregisterPage(&this->nickserv_access);
provider->UnregisterPage(&this->nickserv_alist);
provider->UnregisterPage(&this->nickserv_confirm);
@@ -260,14 +253,15 @@ namespace WebPanel
bi = BotListByNick->begin()->second; // Pick one...
}
- struct MyComandReply : CommandReply
+ struct MyComandReply final
+ : CommandReply
{
TemplateFileServer::Replacements &re;
const Anope::string &k;
MyComandReply(TemplateFileServer::Replacements &_r, const Anope::string &_k) : re(_r), k(_k) { }
- void SendMessage(BotInfo *source, const Anope::string &msg) anope_override
+ void SendMessage(BotInfo *source, const Anope::string &msg) override
{
re[k] = msg;
}
@@ -300,14 +294,15 @@ namespace WebPanel
if (!info)
return;
- struct MyComandReply : CommandReply
+ struct MyComandReply final
+ : CommandReply
{
TemplateFileServer::Replacements &re;
const Anope::string &k;
MyComandReply(TemplateFileServer::Replacements &_r, const Anope::string &_k) : re(_r), k(_k) { }
- void SendMessage(BotInfo *source, const Anope::string &msg) anope_override
+ void SendMessage(BotInfo *source, const Anope::string &msg) override
{
re[k] = msg;
}
diff --git a/modules/webcpanel/webcpanel.h b/modules/webcpanel/webcpanel.h
index 90dc24a41..221ff0e5a 100644
--- a/modules/webcpanel/webcpanel.h
+++ b/modules/webcpanel/webcpanel.h
@@ -5,6 +5,8 @@
* Please read COPYING and README for further details.
*/
+#pragma once
+
#include "module.h"
#include "modules/httpd.h"
@@ -13,9 +15,9 @@
extern Module *me;
-extern Anope::string provider_name, template_name, template_base, page_title;
+extern Anope::string provider_name, template_base, page_title;
-struct SubSection
+struct SubSection final
{
Anope::string name;
Anope::string url;
@@ -28,9 +30,11 @@ struct Section
};
/* An interface for this webpanel used by other modules */
-class Panel : public Section, public Service
+class Panel final
+ : public Section
+ , public Service
{
- public:
+public:
Panel(Module *c, const Anope::string &n) : Service(c, "Panel", n) { }
std::vector<Section> sections;
@@ -61,9 +65,10 @@ class Panel : public Section, public Service
}
};
-class WebPanelPage : public HTTPPage
+class WebPanelPage
+ : public HTTPPage
{
- public:
+public:
WebPanelPage(const Anope::string &u, const Anope::string &ct = "text/html") : HTTPPage(u, ct)
{
}
@@ -71,16 +76,17 @@ class WebPanelPage : public HTTPPage
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
};
-class WebPanelProtectedPage : public WebPanelPage
+class WebPanelProtectedPage
+ : public WebPanelPage
{
Anope::string category;
- public:
+public:
WebPanelProtectedPage(const Anope::string &cat, const Anope::string &u, const Anope::string &ct = "text/html") : WebPanelPage(u, ct), category(cat)
{
}
- bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override anope_final
+ bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) override final
{
ServiceReference<Panel> panel("Panel", "webcpanel");
NickAlias *na;
@@ -103,16 +109,17 @@ class WebPanelProtectedPage : public WebPanelPage
Anope::string sections, get;
- for (std::map<Anope::string, Anope::string>::iterator it = message.get_data.begin(), it_end = message.get_data.end(); it != it_end; ++it)
- if (this->GetData().count(it->first) > 0)
- get += "&" + it->first + "=" + HTTPUtils::URLEncode(it->second);
+ for (const auto &[key, value] : message.get_data)
+ {
+ if (this->GetData().count(key) > 0)
+ get += "&" + key + "=" + HTTPUtils::URLEncode(value);
+ }
if (get.empty() == false)
get = "?" + get.substr(1);
Section *ns = NULL;
- for (unsigned i = 0; i < panel->sections.size(); ++i)
+ for (auto &s : panel->sections)
{
- Section& s = panel->sections[i];
if (s.name == this->category)
ns = &s;
replacements["CATEGORY_URLS"] = s.subsections[0].url;
@@ -122,9 +129,8 @@ class WebPanelProtectedPage : public WebPanelPage
if (ns)
{
sections = "";
- for (unsigned i = 0; i < ns->subsections.size(); ++i)
+ for (const auto &ss : ns->subsections)
{
- SubSection& ss = ns->subsections[i];
replacements["SUBCATEGORY_URLS"] = ss.url;
replacements["SUBCATEGORY_GETS"] = get;
replacements["SUBCATEGORY_NAMES"] = ss.name;
@@ -162,21 +168,8 @@ namespace WebPanel
#include "pages/register.h"
#include "pages/confirm.h"
-#include "pages/nickserv/info.h"
-#include "pages/nickserv/cert.h"
-#include "pages/nickserv/access.h"
-#include "pages/nickserv/alist.h"
-#include "pages/nickserv/confirm.h"
-
-#include "pages/chanserv/info.h"
-#include "pages/chanserv/set.h"
-#include "pages/chanserv/access.h"
-#include "pages/chanserv/akick.h"
-#include "pages/chanserv/modes.h"
-#include "pages/chanserv/drop.h"
-
-#include "pages/memoserv/memos.h"
-
-#include "pages/hostserv/request.h"
-
-#include "pages/operserv/akill.h"
+#include "pages/chanserv/chanserv.h"
+#include "pages/hostserv/hostserv.h"
+#include "pages/memoserv/memoserv.h"
+#include "pages/nickserv/nickserv.h"
+#include "pages/operserv/operserv.h"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b390d164b..79d10e39c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,72 +2,37 @@
file(GLOB SRC_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
if(WIN32)
- append_to_list(SRC_SRCS win32/dir/dir.cpp)
- append_to_list(SRC_SRCS win32/socket.cpp)
- append_to_list(SRC_SRCS win32/windows.cpp)
- append_to_list(SRC_SRCS win32/dl/dl.cpp)
- append_to_list(SRC_SRCS win32/pipe/pipe.cpp)
- append_to_list(SRC_SRCS win32/pthread/pthread.cpp)
- append_to_list(SRC_SRCS win32/sigaction/sigaction.cpp)
-endif(WIN32)
+ list(APPEND SRC_SRCS win32/socket.cpp)
+ list(APPEND SRC_SRCS win32/windows.cpp)
+ list(APPEND SRC_SRCS win32/dl/dl.cpp)
+ list(APPEND SRC_SRCS win32/pipe/pipe.cpp)
+ list(APPEND SRC_SRCS win32/sigaction/sigaction.cpp)
+endif()
if(HAVE_EPOLL)
- append_to_list(SRC_SRCS socketengines/socketengine_epoll.cpp)
-else(HAVE_EPOLL)
- if(HAVE_KQUEUE)
- append_to_list(SRC_SRCS socketengines/socketengine_kqueue.cpp)
- else(HAVE_KQUEUE)
- if(HAVE_POLL)
- append_to_list(SRC_SRCS socketengines/socketengine_poll.cpp)
- else(HAVE_POLL)
- append_to_list(SRC_SRCS socketengines/socketengine_select.cpp)
- endif(HAVE_POLL)
- endif(HAVE_KQUEUE)
-endif(HAVE_EPOLL)
+ list(APPEND SRC_SRCS socketengines/epoll.cpp)
+elseif(HAVE_KQUEUE)
+ list(APPEND SRC_SRCS socketengines/kqueue.cpp)
+elseif(HAVE_POLL)
+ list(APPEND SRC_SRCS socketengines/poll.cpp)
+else()
+ list(APPEND SRC_SRCS socketengines/select.cpp)
+endif()
-sort_list(SRC_SRCS)
+list(SORT SRC_SRCS)
# Set all the files to use C++ as well as set their compile flags (use the module-specific compile flags, though)
set_source_files_properties(${SRC_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
-# Create an empty list to store extra include directories
-set(EXTRA_INCLUDES)
-# Iterate through all the source files
-foreach(SRC ${SRC_SRCS})
- # Temporary variable for the current source's include directories
- set(TEMP_INCLUDES)
- # Calculate the header file dependencies for the given source file
- calculate_depends(${SRC} TEMP_INCLUDES)
- # If there were some extra include directories, add them to the list
- if(TEMP_INCLUDES)
- append_to_list(EXTRA_INCLUDES ${TEMP_INCLUDES})
- endif(TEMP_INCLUDES)
-endforeach(SRC)
-# If there were extra include directories, remove the duplicates and add the directories to the include path
-if(EXTRA_INCLUDES)
- remove_list_duplicates(EXTRA_INCLUDES)
- include_directories(${EXTRA_INCLUDES})
-endif(EXTRA_INCLUDES)
-
# Under Windows, we also include a resource file to the build
if(WIN32)
# Make sure that the resource file is seen as an RC file to be compiled with a resource compiler, not a C++ compiler
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc LANGUAGE RC)
# Add the resource file to the list of sources
- append_to_list(SRC_SRCS ${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc)
- # For MinGW, we have to change the compile flags
- if(MINGW)
- set(RC_CFLAGS "-DMINGW -Ocoff -I${Anope_SOURCE_DIR}/include")
- # If any sort of debugging is being enabled, add a _DEBUG define to the flags for the resource compiler
- if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
- set(RC_CFLAGS "${RC_CFLAGS} -D_DEBUG")
- endif(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
- set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc COMPILE_FLAGS "${RC_CFLAGS}")
- # For anything else, assumingly Visual Studio at this point, use a different set of compile flags
- else(MINGW)
- set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc COMPILE_FLAGS "/i\"${Anope_SOURCE_DIR}/include\"")
- endif(MINGW)
-endif(WIN32)
+ list(APPEND SRC_SRCS ${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc)
+
+ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc COMPILE_FLAGS "/i\"${Anope_SOURCE_DIR}/include\"")
+endif()
# If compiling with Visual Studio, create a static library out of win32/win32_memory.cpp to be included with everything else, needed to override its override of new/delete operators
if(MSVC)
@@ -75,29 +40,36 @@ if(MSVC)
add_library(win32_memory STATIC win32/win32_memory.cpp)
set(WIN32_MEMORY win32_memory)
set(EXTRA_LDFLAGS "/OPT:NOREF") # https://sourceware.org/bugzilla/show_bug.cgi?id=12633
-else(MSVC)
+else()
set(WIN32_MEMORY)
-endif(MSVC)
+endif()
# Generate the Anope executable and set it's linker flags, also set it to export it's symbols even though it's not a module
add_executable(${PROGRAM_NAME} ${SRC_SRCS})
set_target_properties(${PROGRAM_NAME} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS} ${EXTRA_LDFLAGS}" ENABLE_EXPORTS ON INSTALL_RPATH_USE_LINK_PATH ON BUILD_WITH_INSTALL_RPATH ON)
+
# On Windows, also link Anope to the wsock32 and Ws2_32 library, as well as set the version
if(WIN32)
- target_link_libraries(${PROGRAM_NAME} wsock32 Ws2_32 ${LINK_LIBS} ${GETTEXT_LIBRARIES} ${WIN32_MEMORY})
+ target_link_libraries(${PROGRAM_NAME} wsock32 Ws2_32 ${LINK_LIBS} ${WIN32_MEMORY})
set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
-else(WIN32)
- target_link_libraries(${PROGRAM_NAME} ${LINK_LIBS} ${GETTEXT_LIBRARIES})
-endif(WIN32)
+else()
+ target_link_libraries(${PROGRAM_NAME} ${LINK_LIBS})
+endif()
+
+# If being built with localisation we might need to link against libintl.
+if(HAVE_LOCALIZATION AND Intl_LIBRARY)
+ target_link_libraries(${PROGRAM_NAME} ${Intl_LIBRARY})
+endif()
+
# Building the Anope executable requires the version.h header to be generated
add_dependencies(${PROGRAM_NAME} headers)
# Also require the language files if we have gettext
-if(GETTEXT_FOUND)
+if(HAVE_LOCALIZATION)
add_dependencies(${PROGRAM_NAME} language)
-endif(GETTEXT_FOUND)
+endif()
# Get the filename of the Anope executable as it is in on this system
-get_target_property(SERVICES_BINARY ${PROGRAM_NAME} LOCATION)
+set(SERVICES_BINARY "$<TARGET_FILE:${PROGRAM_NAME}>")
get_filename_component(SERVICES_BINARY ${SERVICES_BINARY} NAME)
# Add the Anope executable to the list of files for CPack to ignore
add_to_cpack_ignored_files("${SERVICES_BINARY}$" TRUE)
@@ -108,9 +80,10 @@ configure_file(${Anope_SOURCE_DIR}/include/sysconf.h.cmake ${Anope_BINARY_DIR}/i
# Go into the following directories and run their CMakeLists.txt as well
if(NOT DISABLE_TOOLS)
add_subdirectory(tools)
-endif(NOT DISABLE_TOOLS)
+endif()
# Set Anope to be installed to the bin directory
install(TARGETS ${PROGRAM_NAME}
DESTINATION ${BIN_DIR}
+ RUNTIME
)
diff --git a/src/access.cpp b/src/access.cpp
index fc1d9a51c..d1c7f59c6 100644
--- a/src/access.cpp
+++ b/src/access.cpp
@@ -16,55 +16,8 @@
#include "account.h"
#include "protocol.h"
-static struct
-{
- Anope::string name;
- Anope::string desc;
-} descriptions[] = {
- {"ACCESS_CHANGE", _("Allowed to modify the access list")},
- {"ACCESS_LIST", _("Allowed to view the access list")},
- {"AKICK", _("Allowed to use the AKICK command")},
- {"ASSIGN", _("Allowed to assign/unassign a bot")},
- {"AUTOHALFOP", _("Automatic halfop upon join")},
- {"AUTOOP", _("Automatic channel operator status upon join")},
- {"AUTOOWNER", _("Automatic owner upon join")},
- {"AUTOPROTECT", _("Automatic protect upon join")},
- {"AUTOVOICE", _("Automatic voice on join")},
- {"BADWORDS", _("Allowed to modify channel badwords list")},
- {"BAN", _("Allowed to ban users")},
- {"FANTASIA", _("Allowed to use fantasy commands")},
- {"FOUNDER", _("Allowed to issue commands restricted to channel founders")},
- {"GETKEY", _("Allowed to use GETKEY command")},
- {"GREET", _("Greet message displayed on join")},
- {"HALFOP", _("Allowed to (de)halfop users")},
- {"HALFOPME", _("Allowed to (de)halfop him/herself")},
- {"INFO", _("Allowed to get full INFO output")},
- {"INVITE", _("Allowed to use the INVITE command")},
- {"KICK", _("Allowed to use the KICK command")},
- {"MEMO", _("Allowed to read channel memos")},
- {"MODE", _("Allowed to use the MODE command")},
- {"NOKICK", _("Prevents users being kicked by Services")},
- {"OP", _("Allowed to (de)op users")},
- {"OPME", _("Allowed to (de)op him/herself")},
- {"OWNER", _("Allowed to (de)owner users")},
- {"OWNERME", _("Allowed to (de)owner him/herself")},
- {"PROTECT", _("Allowed to (de)protect users")},
- {"PROTECTME", _("Allowed to (de)protect him/herself")},
- {"SAY", _("Allowed to use SAY and ACT commands")},
- {"SET", _("Allowed to set channel settings")},
- {"SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used")},
- {"TOPIC", _("Allowed to change channel topics")},
- {"UNBAN", _("Allowed to unban users")},
- {"VOICE", _("Allowed to (de)voice users")},
- {"VOICEME", _("Allowed to (de)voice him/herself")}
-};
-
Privilege::Privilege(const Anope::string &n, const Anope::string &d, int r) : name(n), desc(d), rank(r)
{
- if (this->desc.empty())
- for (unsigned j = 0; j < sizeof(descriptions) / sizeof(*descriptions); ++j)
- if (descriptions[j].name.equals_ci(name))
- this->desc = descriptions[j].desc;
}
bool Privilege::operator==(const Privilege &other) const
@@ -94,10 +47,10 @@ void PrivilegeManager::RemovePrivilege(Privilege &p)
if (it != Privileges.end())
Privileges.erase(it);
- for (registered_channel_map::const_iterator cit = RegisteredChannelList->begin(), cit_end = RegisteredChannelList->end(); cit != cit_end; ++cit)
+ for (const auto &[_, ci] : *RegisteredChannelList)
{
- cit->second->QueueUpdate();
- cit->second->RemoveLevel(p.name);
+ ci->QueueUpdate();
+ ci->RemoveLevel(p.name);
}
}
@@ -207,16 +160,17 @@ NickCore *ChanAccess::GetAccount() const
void ChanAccess::Serialize(Serialize::Data &data) const
{
- data["provider"] << this->provider->name;
- data["ci"] << this->ci->name;
- data["mask"] << this->Mask();
- data["creator"] << this->creator;
- data.SetType("last_seen", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
- data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
- data["data"] << this->AccessSerialize();
+ data.Store("provider", this->provider->name);
+ data.Store("ci", this->ci->name);
+ data.Store("mask", this->Mask());
+ data.Store("creator", this->creator);
+ data.Store("description", this->description);
+ data.Store("last_seen", this->last_seen);
+ data.Store("created", this->created);
+ data.Store("data", this->AccessSerialize());
}
-Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string provider, chan;
@@ -238,6 +192,7 @@ Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
data["mask"] >> m;
access->SetMask(m, ci);
data["creator"] >> access->creator;
+ data["description"] >> access->description;
data["last_seen"] >> access->last_seen;
data["created"] >> access->created;
@@ -250,7 +205,7 @@ Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
return access;
}
-bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo* &next) const
+bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo *&next) const
{
next = NULL;
@@ -268,9 +223,8 @@ bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo* &next)
if (acc)
{
- for (unsigned i = 0; i < acc->aliases->size(); ++i)
+ for (auto *na : *acc->aliases)
{
- const NickAlias *na = acc->aliases->at(i);
if (Anope::Match(na->nick, this->mask))
return true;
}
@@ -340,10 +294,8 @@ static bool HasPriv(const ChanAccess::Path &path, const Anope::string &name)
if (path.empty())
return false;
- for (unsigned int i = 0; i < path.size(); ++i)
+ for (auto *access : path)
{
- ChanAccess *access = path[i];
-
EventReturn MOD_RESULT;
FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name));
@@ -390,9 +342,9 @@ static ChanAccess *HighestInPath(const ChanAccess::Path &path)
{
ChanAccess *highest = NULL;
- for (unsigned int i = 0; i < path.size(); ++i)
- if (highest == NULL || *path[i] > *highest)
- highest = path[i];
+ for (auto *ca : path)
+ if (highest == NULL || *ca > *highest)
+ highest = ca;
return highest;
}
@@ -401,9 +353,9 @@ const ChanAccess *AccessGroup::Highest() const
{
ChanAccess *highest = NULL;
- for (unsigned int i = 0; i < paths.size(); ++i)
+ for (const auto &path : paths)
{
- ChanAccess *hip = HighestInPath(paths[i]);
+ ChanAccess *hip = HighestInPath(path);
if (highest == NULL || *hip > *highest)
highest = hip;
diff --git a/src/account.cpp b/src/account.cpp
index 6b69d0e3b..63c65d8fc 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -18,7 +18,7 @@
std::set<IdentifyRequest *> IdentifyRequest::Requests;
-IdentifyRequest::IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass) : owner(o), account(acc), password(pass), dispatched(false), success(false)
+IdentifyRequest::IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass) : owner(o), account(acc), password(pass)
{
Requests.insert(this);
}
diff --git a/src/base.cpp b/src/base.cpp
index 58ce2f097..3cd026bda 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -13,16 +13,12 @@
std::map<Anope::string, std::map<Anope::string, Service *> > Service::Services;
std::map<Anope::string, std::map<Anope::string, Anope::string> > Service::Aliases;
-Base::Base() : references(NULL)
-{
-}
-
Base::~Base()
{
if (this->references != NULL)
{
- for (std::set<ReferenceBase *>::iterator it = this->references->begin(), it_end = this->references->end(); it != it_end; ++it)
- (*it)->Invalidate();
+ for (auto *reference : *this->references)
+ reference->Invalidate();
delete this->references;
}
}
diff --git a/src/bots.cpp b/src/bots.cpp
index b4e3a2996..5aa953672 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -20,7 +20,11 @@
Serialize::Checker<botinfo_map> BotListByNick("BotInfo"), BotListByUID("BotInfo");
-BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), Serializable("BotInfo"), channels("ChannelInfo"), botmodes(bmodes)
+BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes)
+ : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", {}, IRCD ? IRCD->UID_Retrieve() : "", NULL)
+ , Serializable("BotInfo")
+ , channels("ChannelInfo")
+ , botmodes(bmodes)
{
this->lastmsg = this->created = Anope::CurTime;
this->introduced = false;
@@ -35,9 +39,16 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A
// If we're synchronised with the uplink already, send the bot.
if (Me && Me->IsSynced())
{
- Anope::string tmodes = !this->botmodes.empty() ? ("+" + this->botmodes) : IRCD->DefaultPseudoclientModes;
- if (!tmodes.empty())
- this->SetModesInternal(this, tmodes.c_str());
+ spacesepstream modesep(this->botmodes.empty() ? IRCD->DefaultPseudoclientModes : "+" + this->botmodes);
+
+ Anope::string modechars;
+ modesep.GetToken(modechars);
+
+ std::vector<Anope::string> modeparams;
+ modesep.GetTokens(modeparams);
+
+ if (!modechars.empty())
+ this->SetModesInternal(this, modechars, modeparams);
XLine x(this->nick, "Reserved for services");
IRCD->SendSQLine(NULL, &x);
@@ -75,17 +86,17 @@ BotInfo::~BotInfo()
void BotInfo::Serialize(Serialize::Data &data) const
{
- data["nick"] << this->nick;
- data["user"] << this->ident;
- data["host"] << this->host;
- data["realname"] << this->realname;
- data["created"] << this->created;
- data["oper_only"] << this->oper_only;
+ data.Store("nick", this->nick);
+ data.Store("user", this->ident);
+ data.Store("host", this->host);
+ data.Store("realname", this->realname);
+ data.Store("created", this->created);
+ data.Store("oper_only", this->oper_only);
Extensible::ExtensibleSerialize(this, this, data);
}
-Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *BotInfo::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string nick, user, host, realname, flags;
@@ -131,8 +142,8 @@ void BotInfo::OnKill()
IRCD->SendClientIntroduction(this);
this->introduced = true;
- for (User::ChanUserList::const_iterator cit = this->chans.begin(), cit_end = this->chans.end(); cit != cit_end; ++cit)
- IRCD->SendJoin(this, cit->second->chan, &cit->second->status);
+ for (const auto &[_, chan] : this->chans)
+ IRCD->SendJoin(this, chan->chan, &chan->status);
}
void BotInfo::SetNewNick(const Anope::string &newnick)
@@ -216,23 +227,28 @@ void BotInfo::Part(Channel *c, const Anope::string &reason)
FOREACH_MOD(OnPrePartChannel, (this, c));
- IRCD->SendPart(this, c, "%s", !reason.empty() ? reason.c_str() : "");
+ IRCD->SendPart(this, c, reason);
c->DeleteUser(this);
FOREACH_MOD(OnPartChannel, (this, c, c->name, reason));
}
-void BotInfo::OnMessage(User *u, const Anope::string &message)
+void BotInfo::OnMessage(User *u, const Anope::string &message, const Anope::map<Anope::string> &tags)
{
if (this->commands.empty())
return;
- CommandSource source(u->nick, u, u->Account(), u, this);
+ Anope::string msgid;
+ auto iter = tags.find("msgid");
+ if (iter != tags.end())
+ msgid = iter->second;
+
+ CommandSource source(u->nick, u, u->Account(), u, this, msgid);
Command::Run(source, message);
}
-CommandInfo& BotInfo::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission)
+CommandInfo &BotInfo::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission)
{
CommandInfo ci;
ci.name = sname;
@@ -249,7 +265,14 @@ CommandInfo *BotInfo::GetCommand(const Anope::string &cname)
return NULL;
}
-BotInfo* BotInfo::Find(const Anope::string &nick, bool nick_only)
+Anope::string BotInfo::GetQueryCommand() const
+{
+ if (Config->ServiceAlias && !this->alias.empty())
+ return Anope::printf("/%s", this->alias.c_str());
+ return Anope::printf("/msg %s", this->nick.c_str());
+}
+
+BotInfo *BotInfo::Find(const Anope::string &nick, bool nick_only)
{
if (!nick_only && IRCD != NULL && IRCD->RequiresID)
{
diff --git a/src/channels.cpp b/src/channels.cpp
index b8e9f024d..c3eb2bedf 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -71,25 +71,23 @@ void Channel::Reset()
{
this->modes.clear();
- for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
+ for (const auto &[_, uc] : this->users)
{
- ChanUserContainer *uc = it->second;
-
ChannelStatus f = uc->status;
uc->status.Clear();
/* reset modes for my clients */
if (uc->user->server == Me)
{
- for (size_t i = 0; i < f.Modes().length(); ++i)
- this->SetMode(NULL, ModeManager::FindChannelModeByChar(f.Modes()[i]), uc->user->GetUID(), false);
+ for (auto mode : f.Modes())
+ this->SetMode(NULL, ModeManager::FindChannelModeByChar(mode), uc->user->GetUID(), false);
/* Modes might not exist yet, so be sure the status is really reset */
uc->status = f;
}
}
- for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
- this->SetCorrectModes(it->second->user, true);
+ for (auto &[_, cuc] : this->users)
+ this->SetCorrectModes(cuc->user, true);
// If the channel is syncing now, do not force a sync due to Reset(), as we are probably iterating over users in Message::SJoin
// A sync will come soon
@@ -139,12 +137,12 @@ bool Channel::CheckDelete()
return MOD_RESULT != EVENT_STOP && this->users.empty();
}
-ChanUserContainer* Channel::JoinUser(User *user, const ChannelStatus *status)
+ChanUserContainer *Channel::JoinUser(User *user, const ChannelStatus *status)
{
if (user->server && user->server->IsSynced())
Log(user, this, "join");
- ChanUserContainer *cuc = new ChanUserContainer(user, this);
+ auto *cuc = new ChanUserContainer(user, this);
user->chans[this] = cuc;
this->users[user] = cuc;
if (status)
@@ -203,10 +201,12 @@ size_t Channel::HasMode(const Anope::string &mname, const Anope::string &param)
{
if (param.empty())
return modes.count(mname);
- std::vector<Anope::string> v = this->GetModeList(mname);
- for (unsigned int i = 0; i < v.size(); ++i)
- if (v[i].equals_ci(param))
+
+ for (const auto &mode : this->GetModeList(mname))
+ {
+ if (mode.equals_ci(param))
return 1;
+ }
return 0;
}
@@ -214,22 +214,22 @@ Anope::string Channel::GetModes(bool complete, bool plus)
{
Anope::string res, params;
- for (std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it)
+ for (const auto &[mode, value] : this->modes)
{
- ChannelMode *cm = ModeManager::FindChannelModeByName(it->first);
+ ChannelMode *cm = ModeManager::FindChannelModeByName(mode);
if (!cm || cm->type == MODE_LIST)
continue;
res += cm->mchar;
- if (complete && !it->second.empty())
+ if (complete && !value.empty())
{
ChannelModeParam *cmp = NULL;
if (cm->type == MODE_PARAM)
cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
if (plus || !cmp || !cmp->minus_no_arg)
- params += " " + it->second;
+ params += " " + value;
}
}
@@ -242,7 +242,7 @@ const Channel::ModeList &Channel::GetModes() const
}
template<typename F, typename S>
-struct second
+struct second final
{
S operator()(const std::pair<F, S> &p)
{
@@ -304,7 +304,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
else if (this->HasMode(cm->name, param))
return;
- this->modes.insert(std::make_pair(cm->name, param));
+ this->modes.emplace(cm->name, param);
if (param.empty() && cm->type != MODE_REGULAR)
{
@@ -542,15 +542,21 @@ void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...)
{
char buf[BUFSIZE] = "";
va_list args;
- Anope::string modebuf, sbuf;
- int add = -1;
va_start(args, cmodes);
vsnprintf(buf, BUFSIZE - 1, cmodes, args);
va_end(args);
+ SetModes(bi, enforce_mlock, Anope::string(buf));
+}
+
+
+void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const Anope::string &cmodes)
+{
+ Anope::string modebuf, sbuf;
+ int add = -1;
Reference<Channel> this_reference(this);
- spacesepstream sep(buf);
+ spacesepstream sep(cmodes);
sep.GetToken(modebuf);
for (unsigned i = 0, end = modebuf.length(); this_reference && i < end; ++i)
{
@@ -605,13 +611,13 @@ void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...)
}
}
-void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool enforce_mlock)
+void Channel::SetModesInternal(MessageSource &source, const Anope::string &modes, const std::vector<Anope::string> &params, time_t ts, bool enforce_mlock)
{
if (!ts)
;
else if (ts > this->creation_time)
{
- Log(LOG_DEBUG) << "Dropping mode " << mode << " on " << this->name << ", " << ts << " > " << this->creation_time;
+ Log(LOG_DEBUG) << "Dropping mode " << modes << " on " << this->name << ", " << ts << " > " << this->creation_time;
return;
}
else if (ts < this->creation_time)
@@ -625,20 +631,18 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
/* Removing channel modes *may* delete this channel */
Reference<Channel> this_reference(this);
- spacesepstream sep_modes(mode);
- Anope::string m;
-
- sep_modes.GetToken(m);
-
Anope::string modestring;
Anope::string paramstring;
int add = -1;
bool changed = false;
- for (unsigned int i = 0, end = m.length(); i < end && this_reference; ++i)
+ auto paramit = params.begin();
+ for (const auto mchar : modes)
{
- ChannelMode *cm;
+ if (!this_reference)
+ break;
- switch (m[i])
+ ChannelMode *cm;
+ switch (mchar)
{
case '+':
modestring += '+';
@@ -651,10 +655,10 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
default:
if (add == -1)
continue;
- cm = ModeManager::FindChannelModeByChar(m[i]);
+ cm = ModeManager::FindChannelModeByChar(mchar);
if (!cm)
{
- Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << m[i];
+ Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << mchar;
continue;
}
modestring += cm->mchar;
@@ -680,9 +684,9 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
continue;
}
}
- Anope::string token;
- if (sep_modes.GetToken(token))
+ if (paramit != params.end())
{
+ auto token = *paramit++;
User *u = NULL;
if (cm->type == MODE_STATUS && (u = User::Find(token)))
paramstring += " " + u->nick;
@@ -697,7 +701,7 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
this->RemoveModeInternal(source, cm, token, enforce_mlock);
}
else
- Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << mode;
+ Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << modes;
}
if (!this_reference)
@@ -728,10 +732,9 @@ bool Channel::MatchesList(User *u, const Anope::string &mode)
if (!this->HasMode(mode))
return false;
- std::vector<Anope::string> v = this->GetModeList(mode);
- for (unsigned i = 0; i < v.size(); ++i)
+ for (const auto &entry : this->GetModeList(mode))
{
- Entry e(mode, v[i]);
+ Entry e(mode, entry);
if (e.Matches(u))
return true;
}
@@ -778,6 +781,11 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
vsnprintf(buf, BUFSIZE - 1, reason, args);
va_end(args);
+ return Kick(bi, u, Anope::string(buf));
+}
+
+bool Channel::Kick(BotInfo *bi, User *u, const Anope::string &reason)
+{
/* Do not kick protected clients or Ulines */
if (u->IsProtected())
return false;
@@ -786,11 +794,11 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
bi = this->WhoSends();
EventReturn MOD_RESULT;
- FOREACH_RESULT(OnBotKick, MOD_RESULT, (bi, this, u, buf));
+ FOREACH_RESULT(OnBotKick, MOD_RESULT, (bi, this, u, reason));
if (MOD_RESULT == EVENT_STOP)
return false;
- IRCD->SendKick(bi, this, u, "%s", buf);
- this->KickInternal(bi, u->nick, buf);
+ IRCD->SendKick(bi, this, u, reason);
+ this->KickInternal(bi, u->nick, reason);
return true;
}
@@ -845,9 +853,8 @@ void Channel::SetCorrectModes(User *user, bool give_modes)
bool giving = give_modes;
/* whether or not we have given a mode */
bool given = false;
- for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i)
+ for (auto *cm : ModeManager::GetStatusChannelModesByRank())
{
- ChannelModeStatus *cm = ModeManager::GetStatusChannelModesByRank()[i];
bool has_priv = u_access.HasPriv("AUTO" + cm->name);
if (give_modes && has_priv)
@@ -880,10 +887,9 @@ bool Channel::Unban(User *u, const Anope::string &mode, bool full)
bool ret = false;
- std::vector<Anope::string> v = this->GetModeList(mode);
- for (unsigned int i = 0; i < v.size(); ++i)
+ for (const auto &entry : this->GetModeList(mode))
{
- Entry ban(mode, v[i]);
+ Entry ban(mode, entry);
if (ban.Matches(u, full))
{
this->RemoveMode(NULL, mode, ban.GetMask());
@@ -921,12 +927,12 @@ bool Channel::CheckKick(User *user)
Log(LOG_DEBUG) << "Autokicking " << user->nick << " (" << mask << ") from " << this->name;
this->SetMode(NULL, "BAN", mask);
- this->Kick(NULL, user, "%s", reason.c_str());
+ this->Kick(NULL, user, reason);
return true;
}
-BotInfo* Channel::WhoSends() const
+BotInfo *Channel::WhoSends() const
{
if (ci)
return ci->WhoSends();
@@ -941,7 +947,7 @@ BotInfo* Channel::WhoSends() const
return NULL;
}
-Channel* Channel::Find(const Anope::string &name)
+Channel *Channel::Find(const Anope::string &name)
{
channel_map::const_iterator it = ChannelList.find(name);
@@ -952,7 +958,7 @@ Channel* Channel::Find(const Anope::string &name)
Channel *Channel::FindOrCreate(const Anope::string &name, bool &created, time_t ts)
{
- Channel* &chan = ChannelList[name];
+ Channel *&chan = ChannelList[name];
created = chan == NULL;
if (!chan)
chan = new Channel(name, ts);
@@ -967,10 +973,8 @@ void Channel::QueueForDeletion()
void Channel::DeleteChannels()
{
- for (unsigned int i = 0; i < deleting.size(); ++i)
+ for (auto *c : deleting)
{
- Channel *c = deleting[i];
-
if (c->CheckDelete())
delete c;
}
diff --git a/src/command.cpp b/src/command.cpp
index eb5c89753..d5bbca2dd 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -17,8 +17,19 @@
#include "regchannel.h"
#include "channels.h"
-CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r),
- c(NULL), service(bi)
+void CommandReply::SendMessage(CommandSource &source, const Anope::string &msg)
+{
+ SendMessage(source.service, msg);
+}
+
+CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi, const Anope::string &m)
+ : nick(n)
+ , u(user)
+ , nc(core)
+ , ip(user ? user->ip.str() : "")
+ , reply(r)
+ , service(bi)
+ , msgid(m)
{
}
@@ -107,6 +118,21 @@ void CommandSource::Reply(const char *message, ...)
va_end(args);
}
+void CommandSource::Reply(int count, const char *single, const char *plural, ...)
+{
+ va_list args;
+ char buf[4096]; // Messages can be really big.
+
+ const char *translated_message = Language::Translate(this->nc, count, single, plural);
+
+ va_start(args, plural);
+ vsnprintf(buf, sizeof(buf), translated_message, args);
+
+ this->Reply(Anope::string(buf));
+
+ va_end(args);
+}
+
void CommandSource::Reply(const Anope::string &message)
{
const char *translated_message = Language::Translate(this->nc, message.c_str());
@@ -114,7 +140,7 @@ void CommandSource::Reply(const Anope::string &message)
sepstream sep(translated_message, '\n', true);
Anope::string tok;
while (sep.GetToken(tok))
- this->reply->SendMessage(this->service, tok);
+ this->reply->SendMessage(*this, tok);
}
Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(o)
@@ -122,10 +148,6 @@ Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t
allow_unregistered = require_user = false;
}
-Command::~Command()
-{
-}
-
void Command::SetDesc(const Anope::string &d)
{
this->desc = d;
@@ -192,14 +214,56 @@ void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcomma
this->SendSyntax(source);
bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
if (has_help)
- source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
+ source.Reply(MORE_INFO, source.service->GetQueryCommand().c_str(), source.command.c_str());
+}
+
+namespace
+{
+ void HandleUnknownCommand(CommandSource& source, const Anope::string &message)
+ {
+ // Try to find a similar command.
+ size_t distance = Config->GetBlock("options")->Get<size_t>("didyoumeandifference", "4");
+ Anope::string similar;
+ auto umessage = message.upper();
+ for (const auto &[command, info] : source.service->commands)
+ {
+ if (info.hide || command == message)
+ continue; // Don't suggest a hidden alias or a missing command.
+
+ size_t dist = Anope::Distance(umessage, command);
+ if (dist < distance)
+ {
+ distance = dist;
+ similar = command;
+ }
+ }
+
+ bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
+ if (has_help && similar.empty())
+ {
+ source.Reply(_("Unknown command \002%s\002. \"%s HELP\" for help."), message.c_str(),
+ source.service->GetQueryCommand().c_str());
+ }
+ else if (has_help)
+ {
+ source.Reply(_("Unknown command \002%s\002. Did you mean \002%s\002? \"%s HELP\" for help."),
+ message.c_str(), similar.c_str(), source.service->GetQueryCommand().c_str());
+ }
+ else if (similar.empty())
+ {
+ source.Reply(_("Unknown command \002%s\002. Did you mean \002%s\002?"), message.c_str(), similar.c_str());
+ }
+ else
+ {
+ source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ }
+ }
}
void Command::Run(CommandSource &source, const Anope::string &message)
{
std::vector<Anope::string> params;
spacesepstream(message).GetTokens(params);
- bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
CommandInfo::map::const_iterator it = source.service->commands.end();
unsigned count = 0;
@@ -216,10 +280,7 @@ void Command::Run(CommandSource &source, const Anope::string &message)
if (it == source.service->commands.end())
{
- if (has_help)
- source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
- else
- source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ HandleUnknownCommand(source, message);
return;
}
@@ -227,10 +288,7 @@ void Command::Run(CommandSource &source, const Anope::string &message)
ServiceReference<Command> c("Command", info.name);
if (!c)
{
- if (has_help)
- source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
- else
- source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ HandleUnknownCommand(source, message);
Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
return;
}
@@ -288,19 +346,14 @@ void Command::Run(CommandSource &source, const Anope::string &cmdname, const Com
FOREACH_MOD(OnPostCommand, (source, this, params));
}
-bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo* &bot, Anope::string &name)
+bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo *&bot, Anope::string &name)
{
bot = NULL;
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ for (const auto &[_, bi] : *BotListByNick)
{
- BotInfo *bi = it->second;
-
- for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit)
+ for (const auto &[c_name, info] : bi->commands)
{
- const Anope::string &c_name = cit->first;
- const CommandInfo &info = cit->second;
-
if (info.name != command_service)
continue;
diff --git a/src/config.cpp b/src/config.cpp
index 73820b77d..1f68ada50 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -17,11 +17,14 @@
#include "channels.h"
#include "hashcomp.h"
+#include <stack>
+#include <stdexcept>
+
using Configuration::File;
using Configuration::Conf;
using Configuration::Internal::Block;
-File ServicesConf("services.conf", false); // Services configuration file name
+File ServicesConf("anope.conf", false); // Configuration file name
Conf *Config = NULL;
Block Block::EmptyBlock("");
@@ -40,7 +43,7 @@ int Block::CountBlock(const Anope::string &bname) const
return blocks.count(bname);
}
-const Block* Block::GetBlock(const Anope::string &bname, int num) const
+const Block *Block::GetBlock(const Anope::string &bname, int num) const
{
std::pair<block_map::const_iterator, block_map::const_iterator> it = blocks.equal_range(bname);
@@ -50,7 +53,7 @@ const Block* Block::GetBlock(const Anope::string &bname, int num) const
return &EmptyBlock;
}
-Block* Block::GetMutableBlock(const Anope::string &bname, int num)
+Block *Block::GetMutableBlock(const Anope::string &bname, int num)
{
std::pair<block_map::iterator, block_map::iterator> it = blocks.equal_range(bname);
@@ -66,12 +69,12 @@ bool Block::Set(const Anope::string &tag, const Anope::string &value)
return true;
}
-const Block::item_map* Block::GetItems() const
+const Block::item_map &Block::GetItems() const
{
- return &items;
+ return items;
}
-template<> const Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const
+template<> const Anope::string Block::Get(const Anope::string &tag, const Anope::string &def) const
{
Anope::map<Anope::string>::const_iterator it = items.find(tag);
if (it != items.end())
@@ -118,7 +121,7 @@ template<typename T> static void ValidateNotZero(const Anope::string &block, con
Conf::Conf() : Block("")
{
ReadTimeout = 0;
- UsePrivmsg = DefPrivmsg = false;
+ DefPrivmsg = false;
this->LoadConf(ServicesConf);
@@ -154,9 +157,11 @@ Conf::Conf() : Block("")
{"networkinfo", "chanlen"},
};
- for (unsigned i = 0; i < sizeof(noreload) / sizeof(noreload[0]); ++i)
- if (this->GetBlock(noreload[i].block)->Get<const Anope::string>(noreload[i].name) != Config->GetBlock(noreload[i].block)->Get<const Anope::string>(noreload[i].name))
- throw ConfigException("<" + noreload[i].block + ":" + noreload[i].name + "> can not be modified once set");
+ for (const auto &tag : noreload)
+ {
+ if (this->GetBlock(tag.block)->Get<const Anope::string>(tag.name) != Config->GetBlock(tag.block)->Get<const Anope::string>(tag.name))
+ throw ConfigException("<" + tag.block + ":" + tag.name + "> can not be modified once set");
+ }
}
const Block *serverinfo = this->GetBlock("serverinfo"), *options = this->GetBlock("options"),
@@ -175,24 +180,22 @@ Conf::Conf() : Block("")
ValidateNotZero("options", "readtimeout", options->Get<time_t>("readtimeout"));
- ValidateNotZero("networkinfo", "nicklen", networkinfo->Get<unsigned>("nicklen"));
- ValidateNotZero("networkinfo", "userlen", networkinfo->Get<unsigned>("userlen"));
- ValidateNotZero("networkinfo", "hostlen", networkinfo->Get<unsigned>("hostlen"));
- ValidateNotZero("networkinfo", "chanlen", networkinfo->Get<unsigned>("chanlen"));
+ ValidateNotZero("networkinfo", "nicklen", networkinfo->Get<unsigned>("nicklen", "1"));
+ ValidateNotZero("networkinfo", "userlen", networkinfo->Get<unsigned>("userlen", "1"));
+ ValidateNotZero("networkinfo", "hostlen", networkinfo->Get<unsigned>("hostlen", "1"));
+ ValidateNotZero("networkinfo", "chanlen", networkinfo->Get<unsigned>("chanlen", "1"));
spacesepstream(options->Get<const Anope::string>("ulineservers")).GetTokens(this->Ulines);
if (mail->Get<bool>("usemail"))
{
- Anope::string check[] = { "sendmailpath", "sendfrom", "registration_subject", "registration_message", "emailchange_subject", "emailchange_message", "memo_subject", "memo_message" };
- for (unsigned i = 0; i < sizeof(check) / sizeof(Anope::string); ++i)
- ValidateNotEmpty("mail", check[i], mail->Get<const Anope::string>(check[i]));
+ Anope::string check[] = { "sendfrom", "registration_subject", "registration_message", "emailchange_subject", "emailchange_message", "memo_subject", "memo_message" };
+ for (const auto &field : check)
+ ValidateNotEmpty("mail", field, mail->Get<const Anope::string>(field));
}
this->ReadTimeout = options->Get<time_t>("readtimeout");
- this->UsePrivmsg = options->Get<bool>("useprivmsg");
- this->UseStrictPrivmsg = options->Get<bool>("usestrictprivmsg");
- this->StrictPrivmsg = !UseStrictPrivmsg ? "/msg " : "/";
+ this->ServiceAlias = options->Get<bool>("servicealias");
{
std::vector<Anope::string> defaults;
spacesepstream(this->GetModule("nickserv")->Get<const Anope::string>("defaults")).GetTokens(defaults);
@@ -206,19 +209,33 @@ Conf::Conf() : Block("")
{
const Block *uplink = this->GetBlock("uplink", i);
- const Anope::string &host = uplink->Get<const Anope::string>("host");
- bool ipv6 = uplink->Get<bool>("ipv6");
- int port = uplink->Get<int>("port");
- const Anope::string &password = uplink->Get<const Anope::string>("password");
+ int protocol;
+ const Anope::string &protocolstr = uplink->Get<const Anope::string>("protocol", "ipv4");
+ if (protocolstr == "ipv4")
+ protocol = AF_INET;
+ else if (protocolstr == "ipv6")
+ protocol = AF_INET6;
+ else if (protocolstr == "unix")
+ protocol = AF_UNIX;
+ else
+ throw ConfigException("uplink:protocol must be set to ipv4, ipv6, or unix");
+ const Anope::string &host = uplink->Get<const Anope::string>("host");
ValidateNotEmptyOrSpaces("uplink", "host", host);
- ValidateNotZero("uplink", "port", port);
- ValidateNotEmptyOrSpaces("uplink", "password", password);
- if (password.find(' ') != Anope::string::npos || password[0] == ':')
+ int port = 0;
+ if (protocol != AF_UNIX)
+ {
+ port = uplink->Get<int>("port");
+ ValidateNotZero("uplink", "port", port);
+ }
+
+ const Anope::string &password = uplink->Get<const Anope::string>("password");
+ ValidateNotEmptyOrSpaces("uplink", "password", password);
+ if (password[0] == ':')
throw ConfigException("uplink:password is not valid");
- this->Uplinks.push_back(Uplink(host, port, password, ipv6));
+ this->Uplinks.emplace_back(host, port, password, protocol);
}
for (int i = 0; i < this->CountBlock("module"); ++i)
@@ -244,7 +261,7 @@ Conf::Conf() : Block("")
ValidateNotEmpty("opertype", "name", oname);
- OperType *ot = new OperType(oname);
+ auto *ot = new OperType(oname);
ot->modes = modes;
spacesepstream cmdstr(commands);
@@ -261,10 +278,8 @@ Conf::Conf() : Block("")
/* Strip leading ' ' after , */
if (str.length() > 1 && str[0] == ' ')
str.erase(str.begin());
- for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
+ for (auto *ot2 : this->MyOperTypes)
{
- OperType *ot2 = this->MyOperTypes[j];
-
if (ot2->GetName().equals_ci(str))
{
Log() << "Inheriting commands and privs from " << ot2->GetName() << " to " << ot->GetName();
@@ -293,24 +308,26 @@ Conf::Conf() : Block("")
ValidateNotEmpty("oper", "type", type);
OperType *ot = NULL;
- for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
- if (this->MyOperTypes[j]->GetName() == type)
- ot = this->MyOperTypes[j];
+ for (auto *opertype : this->MyOperTypes)
+ {
+ if (opertype->GetName() == type)
+ ot = opertype;
+ }
if (ot == NULL)
throw ConfigException("Oper block for " + nname + " has invalid oper type " + type);
- Oper *o = new Oper(nname, ot);
+ auto *o = new Oper(nname, ot);
o->require_oper = require_oper;
o->password = password;
- o->certfp = certfp;
+ spacesepstream(certfp).GetTokens(o->certfp);
spacesepstream(host).GetTokens(o->hosts);
o->vhost = vhost;
this->Opers.push_back(o);
}
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- it->second->conf = false;
+ for (const auto &[_, bi] : *BotListByNick)
+ bi->conf = false;
for (int i = 0; i < this->CountBlock("service"); ++i)
{
const Block *service = this->GetBlock("service", i);
@@ -320,7 +337,8 @@ Conf::Conf() : Block("")
&host = service->Get<const Anope::string>("host"),
&gecos = service->Get<const Anope::string>("gecos"),
&modes = service->Get<const Anope::string>("modes"),
- &channels = service->Get<const Anope::string>("channels");
+ &channels = service->Get<const Anope::string>("channels"),
+ &alias = service->Get<const Anope::string>("alias", nick.upper());
ValidateNotEmptyOrSpaces("service", "nick", nick);
ValidateNotEmptyOrSpaces("service", "user", user);
@@ -331,6 +349,8 @@ Conf::Conf() : Block("")
BotInfo *bi = BotInfo::Find(nick, true);
if (!bi)
bi = new BotInfo(nick, user, host, gecos, modes);
+
+ bi->alias = alias;
bi->conf = true;
std::vector<Anope::string> oldchannels = bi->botchannels;
@@ -358,28 +378,30 @@ Conf::Conf() : Block("")
/* Remove all existing modes */
ChanUserContainer *cu = c->FindUser(bi);
if (cu != NULL)
- for (size_t j = 0; j < cu->status.Modes().length(); ++j)
- c->RemoveMode(bi, ModeManager::FindChannelModeByChar(cu->status.Modes()[j]), bi->GetUID());
+ {
+ for (auto mode : cu->status.Modes())
+ c->RemoveMode(bi, ModeManager::FindChannelModeByChar(mode), bi->GetUID());
+ }
/* Set the new modes */
- for (unsigned j = 0; j < want_modes.length(); ++j)
+ for (char want_mode : want_modes)
{
- ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(want_mode);
if (cm == NULL)
- cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
+ cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_mode));
if (cm && cm->type == MODE_STATUS)
c->SetMode(bi, cm, bi->GetUID());
}
}
- for (unsigned k = 0; k < oldchannels.size(); ++k)
+ for (const auto &oldchannel : oldchannels)
{
- size_t ch = oldchannels[k].find('#');
- Anope::string chname = oldchannels[k].substr(ch != Anope::string::npos ? ch : 0);
+ size_t ch = oldchannel.find('#');
+ Anope::string chname = oldchannel.substr(ch != Anope::string::npos ? ch : 0);
bool found = false;
- for (unsigned j = 0; j < bi->botchannels.size(); ++j)
+ for (const auto &botchannel : bi->botchannels)
{
- ch = bi->botchannels[j].find('#');
- Anope::string ochname = bi->botchannels[j].substr(ch != Anope::string::npos ? ch : 0);
+ ch = botchannel.find('#');
+ Anope::string ochname = botchannel.substr(ch != Anope::string::npos ? ch : 0);
if (chname.equals_ci(ochname))
found = true;
@@ -421,8 +443,8 @@ Conf::Conf() : Block("")
this->LogInfos.push_back(l);
}
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- it->second->commands.clear();
+ for (const auto &[_, bi] : *BotListByNick)
+ bi->commands.clear();
for (int i = 0; i < this->CountBlock("command"); ++i)
{
const Block *command = this->GetBlock("command", i);
@@ -499,17 +521,14 @@ Conf::Conf() : Block("")
if (Config)
/* Clear existing conf opers */
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
+ for (const auto &[_, nc] : *NickCoreList)
{
- NickCore *nc = it->second;
if (nc->o && std::find(Config->Opers.begin(), Config->Opers.end(), nc->o) != Config->Opers.end())
nc->o = NULL;
}
/* Apply new opers */
- for (unsigned i = 0; i < this->Opers.size(); ++i)
+ for (auto *o : this->Opers)
{
- Oper *o = this->Opers[i];
-
NickAlias *na = NickAlias::Find(o->name);
if (!na)
continue;
@@ -541,29 +560,31 @@ Conf::Conf() : Block("")
}
}
Anope::CaseMapRebuild();
-
- /* Check the user keys */
- if (!options->Get<unsigned>("seed"))
- Log() << "Configuration option options:seed should be set. It's for YOUR safety! Remember that!";
}
Conf::~Conf()
{
- for (unsigned i = 0; i < MyOperTypes.size(); ++i)
- delete MyOperTypes[i];
- for (unsigned i = 0; i < Opers.size(); ++i)
- delete Opers[i];
+ for (const auto *opertype : MyOperTypes)
+ delete opertype;
+
+ for (const auto *oper : Opers)
+ delete oper;
}
void Conf::Post(Conf *old)
{
/* Apply module changes */
- for (unsigned i = 0; i < old->ModulesAutoLoad.size(); ++i)
- if (std::find(this->ModulesAutoLoad.begin(), this->ModulesAutoLoad.end(), old->ModulesAutoLoad[i]) == this->ModulesAutoLoad.end())
- ModuleManager::UnloadModule(ModuleManager::FindModule(old->ModulesAutoLoad[i]), NULL);
- for (unsigned i = 0; i < this->ModulesAutoLoad.size(); ++i)
- if (std::find(old->ModulesAutoLoad.begin(), old->ModulesAutoLoad.end(), this->ModulesAutoLoad[i]) == old->ModulesAutoLoad.end())
- ModuleManager::LoadModule(this->ModulesAutoLoad[i], NULL);
+ for (const auto &mod : old->ModulesAutoLoad)
+ {
+ if (std::find(this->ModulesAutoLoad.begin(), this->ModulesAutoLoad.end(), mod) == this->ModulesAutoLoad.end())
+ ModuleManager::UnloadModule(ModuleManager::FindModule(mod), NULL);
+ }
+
+ for (const auto &mod : this->ModulesAutoLoad)
+ {
+ if (std::find(old->ModulesAutoLoad.begin(), old->ModulesAutoLoad.end(), mod) == old->ModulesAutoLoad.end())
+ ModuleManager::LoadModule(mod, NULL);
+ }
/* Apply opertype changes, as non-conf opers still point to the old oper types */
for (unsigned i = Oper::opers.size(); i > 0; --i)
@@ -576,9 +597,11 @@ void Conf::Post(Conf *old)
OperType *ot = o->ot;
o->ot = NULL;
- for (unsigned j = 0; j < MyOperTypes.size(); ++j)
- if (ot->GetName() == MyOperTypes[j]->GetName())
- o->ot = MyOperTypes[j];
+ for (auto *opertype : MyOperTypes)
+ {
+ if (ot->GetName() == opertype->GetName())
+ o->ot = opertype;
+ }
if (o->ot == NULL)
{
@@ -597,7 +620,7 @@ void Conf::Post(Conf *old)
}
}
-Block *Conf::GetModule(Module *m)
+Block *Conf::GetModule(const Module *m)
{
if (!m)
return NULL;
@@ -611,7 +634,7 @@ Block *Conf::GetModule(const Anope::string &mname)
if (it != modules.end())
return it->second;
- Block* &block = modules[mname];
+ Block *&block = modules[mname];
/* Search for the block */
for (std::pair<block_map::iterator, block_map::iterator> iters = blocks.equal_range("module"); iters.first != iters.second; ++iters.first)
@@ -658,7 +681,7 @@ const Block *Conf::GetCommand(CommandSource &source)
return &Block::EmptyBlock;
}
-File::File(const Anope::string &n, bool e) : name(n), executable(e), fp(NULL)
+File::File(const Anope::string &n, bool e) : name(n), executable(e)
{
}
@@ -674,7 +697,7 @@ const Anope::string &File::GetName() const
Anope::string File::GetPath() const
{
- return (this->executable ? "" : Anope::ConfigDir + "/") + this->name;
+ return this->executable ? this->name : Anope::ExpandConfig(this->name);
}
bool File::IsOpen() const
@@ -685,7 +708,7 @@ bool File::IsOpen() const
bool File::Open()
{
this->Close();
- this->fp = (this->executable ? popen(this->name.c_str(), "r") : fopen((Anope::ConfigDir + "/" + this->name).c_str(), "r"));
+ this->fp = (this->executable ? popen(GetPath().c_str(), "r") : fopen(GetPath().c_str(), "r"));
return this->fp != NULL;
}
@@ -801,12 +824,12 @@ void Conf::LoadConf(File &file)
if (block_stack.empty() || itemname.empty())
{
file.Close();
- throw ConfigException("Unexpected quoted string: " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Unexpected quoted string: " + file.GetName() + ":" + Anope::ToString(linenumber));
}
if (in_word || !wordbuffer.empty())
{
file.Close();
- throw ConfigException("Unexpected quoted string (prior unhandled words): " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Unexpected quoted string (prior unhandled words): " + file.GetName() + ":" + Anope::ToString(linenumber));
}
in_quote = in_word = true;
}
@@ -815,13 +838,13 @@ void Conf::LoadConf(File &file)
if (block_stack.empty())
{
file.Close();
- throw ConfigException("Config item outside of section (or stray '='): " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Config item outside of section (or stray '='): " + file.GetName() + ":" + Anope::ToString(linenumber));
}
if (!itemname.empty() || wordbuffer.empty())
{
file.Close();
- throw ConfigException("Stray '=' sign or item without value: " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Stray '=' sign or item without value: " + file.GetName() + ":" + Anope::ToString(linenumber));
}
in_word = false;
@@ -847,7 +870,7 @@ void Conf::LoadConf(File &file)
}
Block *b = block_stack.empty() ? this : block_stack.top();
- block_map::iterator it = b->blocks.insert(std::make_pair(wordbuffer, Configuration::Block(wordbuffer)));
+ block_map::iterator it = b->blocks.emplace(wordbuffer, Configuration::Block(wordbuffer));
b = &it->second;
b->linenum = linenumber;
block_stack.push(b);
@@ -868,7 +891,7 @@ void Conf::LoadConf(File &file)
if (!in_word && !wordbuffer.empty())
{
file.Close();
- throw ConfigException("Unexpected word: " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Unexpected word: " + file.GetName() + ":" + Anope::ToString(linenumber));
}
wordbuffer += ch;
in_word = true;
@@ -895,7 +918,7 @@ void Conf::LoadConf(File &file)
if (block_stack.empty())
{
file.Close();
- throw ConfigException("Stray ';' outside of block: " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Stray ';' outside of block: " + file.GetName() + ":" + Anope::ToString(linenumber));
}
Block *b = block_stack.top();
@@ -926,7 +949,7 @@ void Conf::LoadConf(File &file)
if (block_stack.empty())
{
file.Close();
- throw ConfigException("Stray '}': " + file.GetName() + ":" + stringify(linenumber));
+ throw ConfigException("Stray '}': " + file.GetName() + ":" + Anope::ToString(linenumber));
}
block_stack.pop();
@@ -946,7 +969,7 @@ void Conf::LoadConf(File &file)
if (!block_stack.empty())
{
if (block_stack.top())
- throw ConfigException("Unterminated block at end of file: " + file.GetName() + ". Block was opened on line " + stringify(block_stack.top()->linenum));
+ throw ConfigException("Unterminated block at end of file: " + file.GetName() + ". Block was opened on line " + Anope::ToString(block_stack.top()->linenum));
else
throw ConfigException("Unterminated commented block at end of file: " + file.GetName());
}
diff --git a/src/extensible.cpp b/src/extensible.cpp
index 844130f30..f2d7ff872 100644
--- a/src/extensible.cpp
+++ b/src/extensible.cpp
@@ -52,15 +52,14 @@ void Extensible::ExtensibleSerialize(const Extensible *e, const Serializable *s,
void Extensible::ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data)
{
- for (std::set<ExtensibleBase *>::iterator it = extensible_items.begin(); it != extensible_items.end(); ++it)
+ for (auto *extensible_item : extensible_items)
{
- ExtensibleBase *eb = *it;
- eb->ExtensibleUnserialize(e, s, data);
+ extensible_item->ExtensibleUnserialize(e, s, data);
}
}
template<>
-bool* Extensible::Extend(const Anope::string &name, const bool &what)
+bool *Extensible::Extend(const Anope::string &name, const bool &what)
{
ExtensibleRef<bool> ref(name);
if (ref)
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 3abaa388e..da12be638 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -91,7 +91,7 @@ bool ci::less::operator()(const Anope::string &s1, const Anope::string &s2) cons
return s1.ci_str().compare(s2.ci_str()) < 0;
}
-sepstream::sepstream(const Anope::string &source, char separator, bool ae) : tokens(source), sep(separator), pos(0), allow_empty(ae)
+sepstream::sepstream(const Anope::string &source, char separator, bool ae) : tokens(source), sep(separator), allow_empty(ae)
{
}
@@ -106,7 +106,7 @@ bool sepstream::GetToken(Anope::string &token)
if (!this->allow_empty)
{
this->pos = this->tokens.find_first_not_of(this->sep, this->pos);
- if (this->pos == std::string::npos)
+ if (this->pos == Anope::string::npos)
{
this->pos = this->tokens.length() + 1;
token.clear();
@@ -115,7 +115,7 @@ bool sepstream::GetToken(Anope::string &token)
}
size_t p = this->tokens.find(this->sep, this->pos);
- if (p == std::string::npos)
+ if (p == Anope::string::npos)
p = this->tokens.length();
token = this->tokens.substr(this->pos, p - this->pos);
@@ -152,7 +152,7 @@ bool sepstream::GetTokenRemainder(Anope::string &token, int num)
return false;
}
-const Anope::string sepstream::GetRemaining()
+Anope::string sepstream::GetRemaining()
{
return !this->StreamEnd() ? this->tokens.substr(this->pos) : "";
}
diff --git a/src/init.cpp b/src/init.cpp
index df229ce72..0508ab94f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -23,13 +23,18 @@
#include <sys/wait.h>
#include <sys/stat.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <pwd.h>
+#include <cerrno>
#include <grp.h>
+#include <pwd.h>
+#include <sys/types.h>
#endif
+#include <thread>
-Anope::string Anope::ConfigDir = "conf", Anope::DataDir = "data", Anope::ModuleDir = "lib", Anope::LocaleDir = "locale", Anope::LogDir = "logs";
+Anope::string Anope::ConfigDir = DEFAULT_CONF_DIR;
+Anope::string Anope::DataDir = DEFAULT_DATA_DIR;
+Anope::string Anope::LocaleDir = DEFAULT_LOCALE_DIR;
+Anope::string Anope::LogDir = DEFAULT_LOG_DIR;
+Anope::string Anope::ModuleDir = DEFAULT_MODULE_DIR;
/* Vector of pairs of command line arguments and their params */
static std::vector<std::pair<Anope::string, Anope::string> > CommandLineArguments;
@@ -57,7 +62,7 @@ static void ParseCommandLineArguments(int ac, char **av)
if (option.empty())
continue;
- CommandLineArguments.push_back(std::make_pair(option, param));
+ CommandLineArguments.emplace_back(option, param);
}
}
@@ -71,11 +76,11 @@ static bool GetCommandLineArgument(const Anope::string &name, char shortname, An
{
param.clear();
- for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = CommandLineArguments.begin(), it_end = CommandLineArguments.end(); it != it_end; ++it)
+ for (const auto &[argument, value] : CommandLineArguments)
{
- if (it->first.equals_ci(name) || (it->first.length() == 1 && it->first[0] == shortname))
+ if (argument.equals_ci(name) || (argument.length() == 1 && argument[0] == shortname))
{
- param = it->second;
+ param = value;
return true;
}
}
@@ -131,7 +136,7 @@ void Anope::HandleSignal()
try
{
- Configuration::Conf *new_config = new Configuration::Conf();
+ auto *new_config = new Configuration::Conf();
Configuration::Conf *old = Config;
Config = new_config;
Config->Post(old);
@@ -147,10 +152,10 @@ void Anope::HandleSignal()
case SIGINT:
#ifndef _WIN32
Log() << "Received " << strsignal(Signal) << " signal (" << Signal << "), exiting.";
- Anope::QuitReason = Anope::string("Services terminating via signal ") + strsignal(Signal) + " (" + stringify(Signal) + ")";
+ Anope::QuitReason = Anope::string("Services terminating via signal ") + strsignal(Signal) + " (" + Anope::ToString(Signal) + ")";
#else
Log() << "Received signal " << Signal << ", exiting.";
- Anope::QuitReason = Anope::string("Services terminating via signal ") + stringify(Signal);
+ Anope::QuitReason = Anope::string("Services terminating via signal ") + Anope::ToString(Signal);
#endif
Anope::Quitting = true;
Anope::SaveDatabases();
@@ -210,26 +215,28 @@ static void InitSignals()
static void remove_pidfile()
{
- remove(Config->GetBlock("serverinfo")->Get<const Anope::string>("pid").c_str());
+ auto pidfile = Anope::ExpandData(Config->GetBlock("serverinfo")->Get<const Anope::string>("pid"));
+ if (!pidfile.empty())
+ remove(pidfile.c_str());
}
/* Create our PID file and write the PID to it. */
static void write_pidfile()
{
- FILE *pidfile = fopen(Config->GetBlock("serverinfo")->Get<const Anope::string>("pid").c_str(), "w");
- if (pidfile)
- {
+ auto pidfile = Anope::ExpandData(Config->GetBlock("serverinfo")->Get<const Anope::string>("pid"));
+ if (Anope::NoPID || pidfile.empty())
+ return;
+
+ std::ofstream stream(pidfile.str());
+ if (!stream.is_open())
+ throw CoreException("Can not write to PID file " + pidfile);
#ifdef _WIN32
- fprintf(pidfile, "%d\n", static_cast<int>(GetCurrentProcessId()));
+ stream << GetCurrentProcessId() << std::endl;
#else
- fprintf(pidfile, "%d\n", static_cast<int>(getpid()));
+ stream << getpid() << std::endl;
#endif
- fclose(pidfile);
- atexit(remove_pidfile);
- }
- else
- throw CoreException("Can not write to PID file " + Config->GetBlock("serverinfo")->Get<const Anope::string>("pid"));
+ atexit(remove_pidfile);
}
static void setuidgid()
@@ -258,14 +265,10 @@ static void setuidgid()
gid = g->gr_gid;
}
- for (unsigned i = 0; i < Config->LogInfos.size(); ++i)
+ for (const auto &li : Config->LogInfos)
{
- LogInfo& li = Config->LogInfos[i];
-
- for (unsigned j = 0; j < li.logfiles.size(); ++j)
+ for (const auto *lf : li.logfiles)
{
- LogFile* lf = li.logfiles[j];
-
errno = 0;
if (chown(lf->filename.c_str(), uid, gid) != 0)
Log() << "Unable to change the ownership of " << lf->filename << " to " << uid << "/" << gid << ": " << Anope::LastError();
@@ -289,13 +292,16 @@ static void setuidgid()
#endif
}
-void Anope::Init(int ac, char **av)
+bool Anope::Init(int ac, char **av)
{
/* Set file creation mask and group ID. */
#if defined(DEFUMASK) && HAVE_UMASK
umask(DEFUMASK);
#endif
+ Anope::UpdateTime();
+ Anope::StartTime = Anope::CurTime;
+
Serialize::RegisterTypes();
/* Parse command line arguments */
@@ -304,7 +310,8 @@ void Anope::Init(int ac, char **av)
if (GetCommandLineArgument("version", 'v'))
{
Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::VersionBuildString();
- throw CoreException();
+ Anope::ReturnValue = EXIT_SUCCESS;
+ return false;
}
if (GetCommandLineArgument("help", 'h'))
@@ -318,10 +325,11 @@ void Anope::Init(int ac, char **av)
Log(LOG_TERMINAL) << "-d, --debug[=level]";
Log(LOG_TERMINAL) << "-h, --help";
Log(LOG_TERMINAL) << " --localedir=locale directory";
- Log(LOG_TERMINAL) << " --logdir=logs directory";
- Log(LOG_TERMINAL) << " --modulesdir=modules directory";
+ Log(LOG_TERMINAL) << " --logdir=log directory";
+ Log(LOG_TERMINAL) << " --moduledir=module directory";
Log(LOG_TERMINAL) << "-e, --noexpire";
Log(LOG_TERMINAL) << "-n, --nofork";
+ Log(LOG_TERMINAL) << "-p, --nopid";
Log(LOG_TERMINAL) << " --nothird";
Log(LOG_TERMINAL) << " --protocoldebug";
Log(LOG_TERMINAL) << "-r, --readonly";
@@ -330,7 +338,8 @@ void Anope::Init(int ac, char **av)
Log(LOG_TERMINAL) << "";
Log(LOG_TERMINAL) << "Further support is available from https://www.anope.org/";
Log(LOG_TERMINAL) << "Or visit us on IRC at irc.teranova.net #anope";
- throw CoreException();
+ Anope::ReturnValue = EXIT_SUCCESS;
+ return false;
}
if (GetCommandLineArgument("nofork", 'n'))
@@ -348,6 +357,9 @@ void Anope::Init(int ac, char **av)
if (GetCommandLineArgument("nothird"))
Anope::NoThird = true;
+ if (GetCommandLineArgument("nopid", 'p'))
+ Anope::NoPID = true;
+
if (GetCommandLineArgument("noexpire", 'e'))
Anope::NoExpire = true;
@@ -359,7 +371,7 @@ void Anope::Init(int ac, char **av)
{
if (!arg.empty())
{
- int level = arg.is_number_only() ? convertTo<int>(arg) : -1;
+ auto level = Anope::Convert<int>(arg, -1);
if (level > 0)
Anope::Debug = level;
else
@@ -397,10 +409,10 @@ void Anope::Init(int ac, char **av)
Anope::LocaleDir = arg;
}
- if (GetCommandLineArgument("modulesdir", 0, arg))
+ if (GetCommandLineArgument("moduledir", 0, arg))
{
if (arg.empty())
- throw CoreException("The --modulesdir option requires a path");
+ throw CoreException("The --moduledir option requires a path");
Anope::ModuleDir = arg;
}
@@ -411,24 +423,18 @@ void Anope::Init(int ac, char **av)
Anope::LogDir = arg;
}
- /* Chdir to Services data directory. */
- if (chdir(Anope::ServicesDir.c_str()) < 0)
+ Log(LOG_TERMINAL) << "Anope " << Anope::Version() << ", " << Anope::VersionBuildString();
+
+ /* Chdir to Anope data directory. */
+ Log() << "Moving to " << Anope::ServicesDir;
+ if (chdir(Anope::ServicesDir.c_str()) != 0)
{
throw CoreException("Unable to chdir to " + Anope::ServicesDir + ": " + Anope::LastError());
}
- Log(LOG_TERMINAL) << "Anope " << Anope::Version() << ", " << Anope::VersionBuildString();
-
-#ifdef _WIN32
- if (!SupportedWindowsVersion())
- throw CoreException(GetWindowsVersion() + " is not a supported version of Windows");
-#endif
-
-#ifdef _WIN32
- Log(LOG_TERMINAL) << "Using configuration file " << Anope::ConfigDir << "\\" << ServicesConf.GetName();
-#else
- Log(LOG_TERMINAL) << "Using configuration file " << Anope::ConfigDir << "/" << ServicesConf.GetName();
+ Log(LOG_TERMINAL) << "Using configuration file " << Anope::ExpandConfig(ServicesConf.GetName());
+#ifndef _WIN32
/* Fork to background */
if (!Anope::NoFork)
{
@@ -453,7 +459,7 @@ void Anope::Init(int ac, char **av)
sigemptyset(&mask);
sigsuspend(&mask);
- exit(Anope::ReturnValue);
+ return false;
}
else if (i == -1)
{
@@ -479,7 +485,7 @@ void Anope::Init(int ac, char **av)
catch (const ConfigException &ex)
{
Log(LOG_TERMINAL) << ex.GetReason();
- Log(LOG_TERMINAL) << "*** Support resources: Read through the services.conf self-contained";
+ Log(LOG_TERMINAL) << "*** Support resources: Read through the anope.conf self-contained";
Log(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'";
Log(LOG_TERMINAL) << "*** folder. Visit our portal located at https://www.anope.org/. Join";
Log(LOG_TERMINAL) << "*** our support channel on /server irc.teranova.net channel #anope.";
@@ -489,9 +495,9 @@ void Anope::Init(int ac, char **av)
/* Create me */
Configuration::Block *block = Config->GetBlock("serverinfo");
Me = new Server(NULL, block->Get<const Anope::string>("name"), 0, block->Get<const Anope::string>("description"), block->Get<const Anope::string>("id"));
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ for (const auto &[_, bi] : *BotListByNick)
{
- it->second->server = Me;
+ bi->server = Me;
++Me->users;
}
@@ -503,10 +509,6 @@ void Anope::Init(int ac, char **av)
/* Initialize multi-language support */
Language::InitLanguages();
- /* Initialize random number generator */
- block = Config->GetBlock("options");
- srand(block->Get<unsigned>("seed") ^ time(NULL));
-
/* load modules */
Log() << "Loading modules...";
for (int i = 0; i < Config->CountBlock("module"); ++i)
@@ -523,7 +525,7 @@ void Anope::Init(int ac, char **av)
std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl;
std::cerr << " require root privileges to run, and it is discouraged that you run Anope" << std::endl;
std::cerr << " as the root superuser." << std::endl;
- sleep(3);
+ std::this_thread::sleep_for(std::chrono::seconds(3));
}
}
@@ -532,8 +534,12 @@ void Anope::Init(int ac, char **av)
setuidgid();
#endif
- Module *protocol = ModuleManager::FindFirstOf(PROTOCOL);
- if (protocol == NULL)
+ auto *encryption = ModuleManager::FindFirstOf(ENCRYPTION);
+ if (!encryption)
+ throw CoreException("You must load a non-deprecated encryption module!");
+
+ auto *protocol = ModuleManager::FindFirstOf(PROTOCOL);
+ if (!protocol)
throw CoreException("You must load a protocol module!");
/* Write our PID to the PID file. */
@@ -547,8 +553,8 @@ void Anope::Init(int ac, char **av)
Anope::string sid = IRCD->SID_Retrieve();
if (Me->GetSID() == Me->GetName())
Me->SetSID(sid);
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- it->second->GenerateUID();
+ for (const auto &[_, bi] : *BotListByNick)
+ bi->GenerateUID();
}
/* Load up databases */
@@ -560,8 +566,9 @@ void Anope::Init(int ac, char **av)
FOREACH_MOD(OnPostInit, ());
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
- it->second->Sync();
+ for (const auto &[_, ci] : ChannelList)
+ ci->Sync();
Serialize::CheckTypes();
+ return true;
}
diff --git a/src/language.cpp b/src/language.cpp
index cdcf4afa0..8d449d362 100644
--- a/src/language.cpp
+++ b/src/language.cpp
@@ -15,7 +15,7 @@
#include "config.h"
#include "language.h"
-#if GETTEXT_FOUND
+#if HAVE_LOCALIZATION
# include <libintl.h>
#endif
@@ -24,7 +24,7 @@ std::vector<Anope::string> Language::Domains;
void Language::InitLanguages()
{
-#if GETTEXT_FOUND
+#if HAVE_LOCALIZATION
Log(LOG_DEBUG) << "Initializing Languages...";
Languages.clear();
@@ -73,12 +73,67 @@ const char *Language::Translate(const NickCore *nc, const char *string)
return Translate(nc ? nc->language.c_str() : "", string);
}
-#if GETTEXT_FOUND
+const char *Language::Translate(int count, const char *singular, const char *plural)
+{
+ return Translate("", count, singular, plural);
+}
+
+const char *Language::Translate(User *u, int count, const char *singular, const char *plural)
+{
+ if (u && u->IsIdentified())
+ return Translate(u->Account(), count, singular, plural);
+ else
+ return Translate("", count, singular, plural);
+}
+
+const char *Language::Translate(const NickCore *nc, int count, const char *singular, const char *plural)
+{
+ return Translate(nc ? nc->language.c_str() : "", count, singular, plural);
+}
+
+#if HAVE_LOCALIZATION
#if defined(__GLIBC__) && defined(__USE_GNU_GETTEXT)
extern "C" int _nl_msg_cat_cntr;
#endif
+namespace
+{
+ void PreTranslate(const char* lang)
+ {
+#if defined(__GLIBC__) && defined(__USE_GNU_GETTEXT)
+ ++_nl_msg_cat_cntr;
+#endif
+
+#ifdef _WIN32
+ SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(lang), SUBLANG_DEFAULT), SORT_DEFAULT));
+#else
+ /* First, set LANG and LANGUAGE env variables.
+ * Some systems (Debian) don't care about this, so we must setlocale LC_ALL as well.
+ * BUT if this call fails because the LANGUAGE env variable is set, setlocale resets
+ * the locale to "C", which short circuits gettext and causes it to fail on systems that
+ * use the LANGUAGE env variable. We must reset the locale to en_US (or, anything not
+ * C or POSIX) then.
+ */
+ setenv("LANG", lang, 1);
+ setenv("LANGUAGE", lang, 1);
+ if (setlocale(LC_ALL, lang) == NULL)
+ setlocale(LC_ALL, "en_US");
+#endif
+ }
+
+ void PostTranslate()
+ {
+#ifdef _WIN32
+ SetThreadLocale(MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT));
+#else
+ unsetenv("LANGUAGE");
+ unsetenv("LANG");
+ setlocale(LC_ALL, "");
+#endif
+ }
+}
+
const char *Language::Translate(const char *lang, const char *string)
{
if (!string || !*string)
@@ -87,36 +142,31 @@ const char *Language::Translate(const char *lang, const char *string)
if (!lang || !*lang)
lang = Config->DefLanguage.c_str();
-#if defined(__GLIBC__) && defined(__USE_GNU_GETTEXT)
- ++_nl_msg_cat_cntr;
-#endif
+ PreTranslate(lang);
-#ifdef _WIN32
- SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(lang), SUBLANG_DEFAULT), SORT_DEFAULT));
-#else
- /* First, set LANG and LANGUAGE env variables.
- * Some systems (Debian) don't care about this, so we must setlocale LC_ALL as well.
- * BUT if this call fails because the LANGUAGE env variable is set, setlocale resets
- * the locale to "C", which short circuits gettext and causes it to fail on systems that
- * use the LANGUAGE env variable. We must reset the locale to en_US (or, anything not
- * C or POSIX) then.
- */
- setenv("LANG", lang, 1);
- setenv("LANGUAGE", lang, 1);
- if (setlocale(LC_ALL, lang) == NULL)
- setlocale(LC_ALL, "en_US");
-#endif
const char *translated_string = dgettext("anope", string);
for (unsigned i = 0; translated_string == string && i < Domains.size(); ++i)
translated_string = dgettext(Domains[i].c_str(), string);
-#ifdef _WIN32
- SetThreadLocale(MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT));
-#else
- unsetenv("LANGUAGE");
- unsetenv("LANG");
- setlocale(LC_ALL, "");
-#endif
+ PostTranslate();
+ return translated_string;
+}
+
+const char *Language::Translate(const char *lang, int count, const char *singular, const char *plural)
+{
+ if (!singular || !*singular || !plural || !*plural)
+ return "";
+
+ if (!lang || !*lang)
+ lang = Config->DefLanguage.c_str();
+
+ PreTranslate(lang);
+
+ const char *translated_string = dngettext("anope", singular, plural, count);
+ for (unsigned i = 0; (translated_string == singular || translated_string == plural) && i < Domains.size(); ++i)
+ translated_string = dngettext(Domains[i].c_str(), singular, plural, count);
+
+ PostTranslate();
return translated_string;
}
#else
@@ -124,4 +174,10 @@ const char *Language::Translate(const char *lang, const char *string)
{
return string != NULL ? string : "";
}
+const char *Language::Translate(const char *lang, int count, const char *singular, const char *plural)
+{
+ return Language::Translate("", count == 1 ? singular : plural);
+}
#endif
+
+
diff --git a/src/logger.cpp b/src/logger.cpp
index c2e250831..28614d9f1 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -29,20 +29,15 @@
static Anope::string GetTimeStamp()
{
char tbuf[256];
- time_t t;
- if (time(&t) < 0)
- t = Anope::CurTime;
-
- tm tm = *localtime(&t);
+ Anope::UpdateTime();
+ auto tm = *localtime(&Anope::CurTime);
if (Anope::Debug)
{
char *s;
- struct timeval tv;
- gettimeofday(&tv, NULL);
strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S", &tm);
s = tbuf + strlen(tbuf);
- s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06d", static_cast<int>(tv.tv_usec));
+ s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06lld", static_cast<long long>(Anope::CurTimeNs / 1000));
strftime(s, sizeof(tbuf) - (s - tbuf) - 1, " %Y]", &tm);
}
else
@@ -57,7 +52,7 @@ static inline Anope::string CreateLogName(const Anope::string &file, time_t t =
tm *tm = localtime(&t);
strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
- return Anope::LogDir + "/" + file + "." + timestamp;
+ return Anope::ExpandLog(file + "." + timestamp);
}
LogFile::LogFile(const Anope::string &name) : filename(name), stream(name.c_str(), std::ios_base::out | std::ios_base::app)
@@ -74,11 +69,11 @@ const Anope::string &LogFile::GetName() const
return this->filename;
}
-Log::Log(LogType t, const Anope::string &cat, BotInfo *b) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(t), category(cat)
+Log::Log(LogType t, const Anope::string &cat, BotInfo *b) : bi(b), type(t), category(cat)
{
}
-Log::Log(LogType t, CommandSource &src, Command *_c, ChannelInfo *_ci) : u(src.GetUser()), nc(src.nc), c(_c), source(&src), chan(NULL), ci(_ci), s(NULL), m(NULL), type(t)
+Log::Log(LogType t, CommandSource &src, Command *_c, ChannelInfo *_ci) : u(src.GetUser()), nc(src.nc), c(_c), source(&src), ci(_ci), type(t)
{
if (!c)
throw CoreException("Invalid pointers passed to Log::Log");
@@ -87,35 +82,34 @@ Log::Log(LogType t, CommandSource &src, Command *_c, ChannelInfo *_ci) : u(src.G
throw CoreException("This constructor does not support this log type");
size_t sl = c->name.find('/');
- this->bi = NULL;
if (sl != Anope::string::npos)
this->bi = Config->GetClient(c->name.substr(0, sl));
this->category = c->name;
}
-Log::Log(User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc(NULL), c(NULL), source(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), m(NULL), type(LOG_CHANNEL), category(cat)
+Log::Log(User *_u, Channel *ch, const Anope::string &cat) : u(_u), chan(ch), ci(chan ? *chan->ci : nullptr), type(LOG_CHANNEL), category(cat)
{
if (!chan)
throw CoreException("Invalid pointers passed to Log::Log");
}
-Log::Log(User *_u, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat)
+Log::Log(User *_u, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(_u), type(LOG_USER), category(cat)
{
if (!u)
throw CoreException("Invalid pointers passed to Log::Log");
}
-Log::Log(Server *serv, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat)
+Log::Log(Server *serv, const Anope::string &cat, BotInfo *_bi) : bi(_bi), s(serv), type(LOG_SERVER), category(cat)
{
if (!s)
throw CoreException("Invalid pointer passed to Log::Log");
}
-Log::Log(BotInfo *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat)
+Log::Log(BotInfo *b, const Anope::string &cat) : bi(b), type(LOG_NORMAL), category(cat)
{
}
-Log::Log(Module *mod, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat)
+Log::Log(Module *mod, const Anope::string &cat, BotInfo *_bi) : bi(_bi), m(mod), type(LOG_MODULE), category(cat)
{
}
@@ -131,9 +125,13 @@ Log::~Log()
FOREACH_MOD(OnLog, (this));
if (Config)
- for (unsigned i = 0; i < Config->LogInfos.size(); ++i)
- if (Config->LogInfos[i].HasType(this->type, this->category))
- Config->LogInfos[i].ProcessMessage(this);
+ {
+ for (auto &li : Config->LogInfos)
+ {
+ if (li.HasType(this->type, this->category))
+ li.ProcessMessage(this);
+ }
+ }
}
Anope::string Log::FormatSource() const
@@ -227,14 +225,14 @@ Anope::string Log::BuildPrefix() const
return buffer;
}
-LogInfo::LogInfo(int la, bool rio, bool ldebug) : bot(NULL), last_day(0), log_age(la), raw_io(rio), debug(ldebug)
+LogInfo::LogInfo(int la, bool rio, bool ldebug) : log_age(la), raw_io(rio), debug(ldebug)
{
}
LogInfo::~LogInfo()
{
- for (unsigned i = 0; i < this->logfiles.size(); ++i)
- delete this->logfiles[i];
+ for (const auto *logfile : this->logfiles)
+ delete logfile;
this->logfiles.clear();
}
@@ -281,16 +279,15 @@ bool LogInfo::HasType(LogType ltype, const Anope::string &type) const
if (list == NULL)
return false;
- for (unsigned i = 0; i < list->size(); ++i)
+ for (auto value : *list)
{
- Anope::string cat = list->at(i);
bool inverse = false;
- if (cat[0] == '~')
+ if (value[0] == '~')
{
- cat.erase(cat.begin());
+ value.erase(value.begin());
inverse = true;
}
- if (Anope::Match(type, cat))
+ if (Anope::Match(type, value))
{
return !inverse;
}
@@ -301,18 +298,16 @@ bool LogInfo::HasType(LogType ltype, const Anope::string &type) const
void LogInfo::OpenLogFiles()
{
- for (unsigned i = 0; i < this->logfiles.size(); ++i)
- delete this->logfiles[i];
+ for (const auto *logfile : this->logfiles)
+ delete logfile;
this->logfiles.clear();
- for (unsigned i = 0; i < this->targets.size(); ++i)
+ for (const auto &target : this->targets)
{
- const Anope::string &target = this->targets[i];
-
if (target.empty() || target[0] == '#' || target == "globops" || target.find(":") != Anope::string::npos)
continue;
- LogFile *lf = new LogFile(CreateLogName(target));
+ auto *lf = new LogFile(CreateLogName(target));
if (!lf->stream.is_open())
{
Log() << "Unable to open logfile " << lf->GetName();
@@ -353,10 +348,8 @@ void LogInfo::ProcessMessage(const Log *l)
FOREACH_MOD(OnLogMessage, (this, l, buffer));
- for (unsigned i = 0; i < this->targets.size(); ++i)
+ for (const auto &target : this->targets)
{
- const Anope::string &target = this->targets[i];
-
if (!target.empty() && target[0] == '#')
{
if (UplinkSock && l->type <= LOG_NORMAL && Me && Me->IsSynced())
@@ -371,7 +364,7 @@ void LogInfo::ProcessMessage(const Log *l)
if (!bi)
bi = c->WhoSends();
if (bi)
- IRCD->SendPrivmsg(bi, c->name, "%s", buffer.c_str());
+ IRCD->SendPrivmsg(bi, c->name, buffer);
}
}
else if (target == "globops")
@@ -382,7 +375,7 @@ void LogInfo::ProcessMessage(const Log *l)
if (!bi)
bi = this->bot;
if (bi)
- IRCD->SendGlobops(bi, "%s", buffer.c_str());
+ IRCD->SendGlobops(bi, buffer);
}
}
}
@@ -394,11 +387,10 @@ void LogInfo::ProcessMessage(const Log *l)
this->OpenLogFiles();
if (this->log_age)
- for (unsigned i = 0; i < this->targets.size(); ++i)
+ {
+ for (const auto &target : this->targets)
{
- const Anope::string &target = this->targets[i];
-
- if (target.empty() || target[0] == '#' || target == "globops" || target.find(":") != Anope::string::npos)
+ if (target.empty() || target[0] == '#' || target == "globops" || target.find(":") != Anope::string::npos)
continue;
Anope::string oldlog = CreateLogName(target, Anope::CurTime - 86400 * this->log_age);
@@ -408,11 +400,11 @@ void LogInfo::ProcessMessage(const Log *l)
Log(LOG_DEBUG) << "Deleted old logfile " << oldlog;
}
}
+ }
}
- for (unsigned i = 0; i < this->logfiles.size(); ++i)
+ for (auto *lf : this->logfiles)
{
- LogFile *lf = this->logfiles[i];
lf->stream << GetTimeStamp() << " " << buffer << std::endl;
}
}
diff --git a/src/mail.cpp b/src/mail.cpp
index fe8bb0b90..f3adab44c 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -15,8 +15,9 @@
Mail::Message::Message(const Anope::string &sf, const Anope::string &mailto, const Anope::string &a, const Anope::string &s, const Anope::string &m)
: Thread()
- , sendmail_path(Config->GetBlock("mail")->Get<const Anope::string>("sendmailpath"))
- , send_from(sf), mail_to(mailto)
+ , sendmail_path(Config->GetBlock("mail")->Get<const Anope::string>("sendmailpath", "/usr/sbin/sendmail -it"))
+ , send_from(sf)
+ , mail_to(mailto)
, addr(a)
, subject(s)
, message(m)
@@ -36,8 +37,7 @@ Mail::Message::~Message()
void Mail::Message::Run()
{
errno = 0;
- FILE *pipe = popen(sendmail_path.c_str(), "w");
-
+ auto *pipe = popen(sendmail_path.c_str(), "w");
if (!pipe)
{
error = strerror(errno);
@@ -54,13 +54,16 @@ void Mail::Message::Run()
fprintf(pipe, "Content-Type: %s\r\n", content_type.c_str());
fprintf(pipe, "Content-Transfer-Encoding: 8bit\r\n");
fprintf(pipe, "\r\n");
- fprintf(pipe, "%s", message.c_str());
- fprintf(pipe, "\r\n.\r\n");
- int result = pclose(pipe);
+ std::stringstream stream(message.str());
+ for (Anope::string line; std::getline(stream, line.str()); )
+ fprintf(pipe, "%s\r\n", line.c_str());
+ fprintf(pipe, "\r\n");
+ auto result = pclose(pipe);
if (result > 0)
- error = "Sendmail exited with code " + stringify(result);
+ error = "Sendmail exited with code " + Anope::ToString(result);
+
SetExitState();
}
@@ -88,9 +91,9 @@ bool Mail::Send(User *u, NickCore *nc, BotInfo *service, const Anope::string &su
if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty())
u->SendMessage(service, _("Services have been configured to not send mail."));
else if (Anope::CurTime - u->lastmail < b->Get<time_t>("delay"))
- u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), b->Get<time_t>("delay") - (Anope::CurTime - u->lastmail));
+ u->SendMessage(service, _("Please wait \002%lu\002 seconds and retry."), (unsigned long)b->Get<time_t>("delay") - (Anope::CurTime - u->lastmail));
else if (nc->email.empty())
- u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str());
+ u->SendMessage(service, _("Email for \002%s\002 is invalid."), nc->display.c_str());
else
{
u->lastmail = nc->lastmail = Anope::CurTime;
@@ -117,9 +120,9 @@ bool Mail::Send(NickCore *nc, const Anope::string &subject, const Anope::string
}
/**
- * Checks whether we have a valid, common e-mail address.
+ * Checks whether we have a valid, common email address.
* This is NOT entirely RFC compliant, and won't be so, because I said
- * *common* cases. ;) It is very unlikely that e-mail addresses that
+ * *common* cases. ;) It is very unlikely that email addresses that
* are really being used will fail the check.
*
* @param email Email to Validate
@@ -146,13 +149,15 @@ bool Mail::Validate(const Anope::string &email)
return false;
/* Check for forbidden characters in the name */
- for (unsigned i = 0, end = copy.length(); i < end; ++i)
+ for (auto chr : copy)
{
- if (copy[i] <= 31 || copy[i] >= 127)
+ if (chr <= 31 || chr >= 127)
return false;
- for (unsigned int j = 0; j < 13; ++j)
- if (copy[i] == specials[j])
+ for (auto special : specials)
+ {
+ if (chr == special)
return false;
+ }
}
/* Check for forbidden characters in the domain */
@@ -160,9 +165,11 @@ bool Mail::Validate(const Anope::string &email)
{
if (domain[i] <= 31 || domain[i] >= 127)
return false;
- for (unsigned int j = 0; j < 13; ++j)
- if (domain[i] == specials[j])
+ for (auto special : specials)
+ {
+ if (domain[i] == special)
return false;
+ }
if (domain[i] == '.')
{
if (!i || i == end - 1)
diff --git a/src/main.cpp b/src/main.cpp
index 37e039fd2..f53b0ba0f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,4 +1,4 @@
-/* Services -- main source file.
+/* Anope -- main source file.
*
* (C) 2003-2025 Anope Team
* Contact us at team@anope.org
@@ -17,14 +17,14 @@
#include "uplink.h"
#ifndef _WIN32
-#include <limits.h>
+#include <climits>
#else
#include <process.h>
#endif
/* Command-line options: */
int Anope::Debug = 0;
-bool Anope::ReadOnly = false, Anope::NoFork = false, Anope::NoThird = false, Anope::NoExpire = false, Anope::ProtocolDebug = false;
+bool Anope::ReadOnly = false, Anope::NoFork = false, Anope::NoThird = false, Anope::NoPID = false, Anope::NoExpire = false, Anope::ProtocolDebug = false;
Anope::string Anope::ServicesDir;
Anope::string Anope::ServicesBin;
@@ -36,28 +36,37 @@ Anope::string Anope::QuitReason;
static Anope::string BinaryDir; /* Full path to services bin directory */
-time_t Anope::StartTime = time(NULL);
-time_t Anope::CurTime = time(NULL);
+time_t Anope::StartTime = 0;
+time_t Anope::CurTime = 0;
+long long Anope::CurTimeNs = 0;
-int Anope::CurrentUplink = -1;
+size_t Anope::CurrentUplink = -1;
-class UpdateTimer : public Timer
+class UpdateTimer final
+ : public Timer
{
- public:
- UpdateTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { }
+public:
+ UpdateTimer(time_t timeout)
+ : Timer(timeout, true)
+ {
+ }
- void Tick(time_t) anope_override
+ void Tick() override
{
Anope::SaveDatabases();
}
};
-class ExpireTimer : public Timer
+class ExpireTimer final
+ : public Timer
{
- public:
- ExpireTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { }
+public:
+ ExpireTimer(time_t timeout)
+ : Timer(timeout, true)
+ {
+ }
- void Tick(time_t) anope_override
+ void Tick() override
{
FOREACH_MOD(OnExpireTick, ());
}
@@ -76,13 +85,13 @@ void Anope::SaveDatabases()
*/
static Anope::string GetFullProgDir(const Anope::string &argv0)
{
- char buffer[PATH_MAX];
#ifdef _WIN32
/* Windows has specific API calls to get the EXE path that never fail.
* For once, Windows has something of use, compared to the POSIX code
* for this, this is positively neato.
*/
- if (GetModuleFileName(NULL, buffer, PATH_MAX))
+ char buffer[MAX_PATH];
+ if (GetModuleFileName(NULL, buffer, MAX_PATH))
{
Anope::string fullpath = buffer;
Anope::string::size_type n = fullpath.rfind("\\");
@@ -91,6 +100,7 @@ static Anope::string GetFullProgDir(const Anope::string &argv0)
}
#else
// Get the current working directory
+ char buffer[PATH_MAX];
if (getcwd(buffer, PATH_MAX))
{
Anope::string remainder = argv0;
@@ -137,12 +147,13 @@ int main(int ac, char **av, char **envp)
try
{
/* General initialization first */
- Anope::Init(ac, av);
+ if (!Anope::Init(ac, av))
+ return Anope::ReturnValue;
}
catch (const CoreException &ex)
{
Log() << ex.GetReason();
- return -1;
+ return EXIT_FAILURE;
}
try
@@ -156,7 +167,7 @@ int main(int ac, char **av, char **envp)
/* Set up timers */
time_t last_check = Anope::CurTime;
- UpdateTimer updateTimer(Config->GetBlock("options")->Get<time_t>("updatetimeout", "5m"));
+ UpdateTimer updateTimer(Config->GetBlock("options")->Get<time_t>("updatetimeout", "2m"));
ExpireTimer expireTimer(Config->GetBlock("options")->Get<time_t>("expiretimeout", "30m"));
/*** Main loop. ***/
@@ -167,7 +178,7 @@ int main(int ac, char **av, char **envp)
/* Process timers */
if (Anope::CurTime - last_check >= Config->TimeoutCheck)
{
- TimerManager::TickTimers(Anope::CurTime);
+ TimerManager::TickTimers();
last_check = Anope::CurTime;
}
@@ -206,11 +217,13 @@ int main(int ac, char **av, char **envp)
if (Anope::Restarting)
{
- chdir(BinaryDir.c_str());
- Anope::string sbin = "./" + Anope::ServicesBin;
- av[0] = const_cast<char *>(sbin.c_str());
- execve(Anope::ServicesBin.c_str(), av, envp);
- Log() << "Restart failed";
+ if (chdir(BinaryDir.c_str()) == 0)
+ {
+ Anope::string sbin = "./" + Anope::ServicesBin;
+ av[0] = const_cast<char *>(sbin.c_str());
+ execve(Anope::ServicesBin.c_str(), av, envp);
+ }
+ Log() << "Restart failed: " << strerror(errno);
Anope::ReturnValue = -1;
}
diff --git a/src/memos.cpp b/src/memos.cpp
index 53177135d..809c05383 100644
--- a/src/memos.cpp
+++ b/src/memos.cpp
@@ -36,15 +36,15 @@ Memo::~Memo()
void Memo::Serialize(Serialize::Data &data) const
{
- data["owner"] << this->owner;
- data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
- data["sender"] << this->sender;
- data["text"] << this->text;
- data["unread"] << this->unread;
- data["receipt"] << this->receipt;
+ data.Store("owner", this->owner);
+ data.Store("time", this->time);
+ data.Store("sender", this->sender);
+ data.Store("text", this->text);
+ data.Store("unread", this->unread);
+ data.Store("receipt", this->receipt);
}
-Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *Memo::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string owner;
@@ -76,7 +76,7 @@ Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
return m;
}
-MemoInfo::MemoInfo() : memomax(0), memos("Memo")
+MemoInfo::MemoInfo() : memos("Memo")
{
}
@@ -113,9 +113,11 @@ void MemoInfo::Del(unsigned index)
bool MemoInfo::HasIgnore(User *u)
{
- for (unsigned i = 0; i < this->ignores.size(); ++i)
- if (u->nick.equals_ci(this->ignores[i]) || (u->IsIdentified() && u->Account()->display.equals_ci(this->ignores[i])) || Anope::Match(u->GetMask(), Anope::string(this->ignores[i])))
+ for (const auto &ignore : this->ignores)
+ {
+ if (u->nick.equals_ci(ignore) || (u->IsIdentified() && u->Account()->display.equals_ci(ignore)) || Anope::Match(u->GetMask(), Anope::string(ignore)))
return true;
+ }
return false;
}
diff --git a/src/messages.cpp b/src/messages.cpp
index b2f65a5c2..ddc6ec380 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -19,10 +19,11 @@
#include "messages.h"
#include "servers.h"
#include "channels.h"
+#include "numeric.h"
using namespace Message;
-void Away::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Away::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
const Anope::string &msg = !params.empty() ? params[0] : "";
@@ -33,7 +34,7 @@ void Away::Run(MessageSource &source, const std::vector<Anope::string> &params)
Log(source.GetUser(), "away") << "is no longer away";
}
-void Capab::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Capab::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
if (params.size() == 1)
{
@@ -43,18 +44,20 @@ void Capab::Run(MessageSource &source, const std::vector<Anope::string> &params)
Servers::Capab.insert(token);
}
else
- for (unsigned i = 0; i < params.size(); ++i)
- Servers::Capab.insert(params[i]);
+ {
+ for (const auto &param : params)
+ Servers::Capab.insert(param);
+ }
}
-void Error::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Error::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Log(LOG_TERMINAL) << "ERROR: " << params[0];
Anope::QuitReason = "Received ERROR from uplink: " + params[0];
Anope::Quitting = true;
}
-void Invite::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Invite::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
User *targ = User::Find(params[0]);
Channel *c = Channel::Find(params[1]);
@@ -65,7 +68,7 @@ void Invite::Run(MessageSource &source, const std::vector<Anope::string> &params
FOREACH_MOD(OnInvite, (source.GetUser(), c, targ));
}
-void Join::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Join::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
User *user = source.GetUser();
const Anope::string &channels = params[0];
@@ -92,14 +95,14 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> &params)
}
std::list<SJoinUser> users;
- users.push_back(std::make_pair(ChannelStatus(), user));
+ users.emplace_back(ChannelStatus(), user);
Channel *chan = Channel::Find(channel);
- SJoin(source, channel, chan ? chan->creation_time : Anope::CurTime, "", users);
+ SJoin(source, channel, chan ? chan->creation_time : Anope::CurTime, "", {}, users);
}
}
-void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users)
+void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::vector<Anope::string> &modeparams, const std::list<SJoinUser> &users)
{
bool created;
Channel *c = Channel::FindOrCreate(chan, created, ts ? ts : Anope::CurTime);
@@ -125,12 +128,10 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
/* If we are syncing, mlock is checked later in Channel::Sync. It is important to not check it here
* so that Channel::SetCorrectModes can correctly detect the presence of channel mode +r.
*/
- c->SetModesInternal(source, modes, ts, !c->syncing);
+ c->SetModesInternal(source, modes, modeparams, ts, !c->syncing);
- for (std::list<SJoinUser>::const_iterator it = users.begin(), it_end = users.end(); it != it_end; ++it)
+ for (const auto &[status, u] : users)
{
- const ChannelStatus &status = it->first;
- User *u = it->second;
keep_their_modes = ts <= c->creation_time; // OnJoinChannel can call modules which can modify this channel's ts
if (c->FindUser(u))
@@ -167,7 +168,7 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
}
}
-void Kick::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Kick::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
const Anope::string &channel = params[0];
const Anope::string &users = params[1];
@@ -184,7 +185,7 @@ void Kick::Run(MessageSource &source, const std::vector<Anope::string> &params)
c->KickInternal(source, user, reason);
}
-void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
User *u = User::Find(params[0]);
BotInfo *bi;
@@ -199,7 +200,7 @@ void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params)
if (last_time == Anope::CurTime)
{
- Anope::QuitReason = "Kill loop detected. Are Services U:Lined?";
+ Anope::QuitReason = "Kill loop detected. Is Anope U:Lined?";
Anope::Quitting = true;
return;
}
@@ -211,53 +212,46 @@ void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params)
u->KillInternal(source, params[1]);
}
-void Message::Mode::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Message::Mode::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
- Anope::string buf;
- for (unsigned i = 1; i < params.size(); ++i)
- buf += " " + params[i];
-
if (IRCD->IsChannelValid(params[0]))
{
Channel *c = Channel::Find(params[0]);
if (c)
- c->SetModesInternal(source, buf.substr(1), 0);
+ c->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
}
else
{
User *u = User::Find(params[0]);
if (u)
- u->SetModesInternal(source, "%s", buf.substr(1).c_str());
+ u->SetModesInternal(source, params[1], { params.begin() + 2, params.end() });
}
}
/* XXX We should cache the file somewhere not open/read/close it on every request */
-void MOTD::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void MOTD::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Server *s = Server::Find(params[0]);
if (s != Me)
return;
- FILE *f = fopen(Config->GetBlock("serverinfo")->Get<const Anope::string>("motd").c_str(), "r");
- if (f)
+ auto motdfile = Anope::ExpandConfig(Config->GetBlock("serverinfo")->Get<const Anope::string>("motd"));
+ std::ifstream stream(motdfile.str());
+ if (!stream.is_open())
{
- IRCD->SendNumeric(375, source.GetSource(), ":- %s Message of the Day", s->GetName().c_str());
- char buf[BUFSIZE];
- while (fgets(buf, sizeof(buf), f))
- {
- buf[strlen(buf) - 1] = 0;
- IRCD->SendNumeric(372, source.GetSource(), ":- %s", buf);
- }
- fclose(f);
- IRCD->SendNumeric(376, source.GetSource(), ":End of /MOTD command.");
+ IRCD->SendNumeric(ERR_NOSUCHNICK, source.GetSource(), "- MOTD file not readable! Please contact your IRC administrator.");
+ return;
}
- else
- IRCD->SendNumeric(422, source.GetSource(), ":- MOTD file not found! Please contact your IRC administrator.");
+
+ IRCD->SendNumeric(RPL_MOTDSTART, source.GetSource(), "- " + s->GetName() + " Message of the Day");
+ for (Anope::string line; std::getline(stream, line.str()); )
+ IRCD->SendNumeric(RPL_MOTD, source.GetSource(), Anope::printf("- %s", line.c_str()));
+ IRCD->SendNumeric(RPL_ENDOFMOTD, source.GetSource(), "End of /MOTD command.");
}
-void Notice::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Notice::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Anope::string message = params[1];
@@ -269,11 +263,11 @@ void Notice::Run(MessageSource &source, const std::vector<Anope::string> &params
BotInfo *bi = BotInfo::Find(params[0]);
if (!bi)
return;
- FOREACH_MOD(OnBotNotice, (u, bi, message));
+ FOREACH_MOD(OnBotNotice, (u, bi, message, tags));
}
}
-void Part::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Part::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
User *u = source.GetUser();
const Anope::string &reason = params.size() > 1 ? params[1] : "";
@@ -295,12 +289,12 @@ void Part::Run(MessageSource &source, const std::vector<Anope::string> &params)
}
}
-void Ping::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Ping::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
IRCD->SendPong(params.size() > 1 ? params[1] : Me->GetSID(), params[0]);
}
-void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
const Anope::string &receiver = params[0];
Anope::string message = params[1];
@@ -312,7 +306,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
Channel *c = Channel::Find(receiver);
if (c)
{
- FOREACH_MOD(OnPrivmsg, (u, c, message));
+ FOREACH_MOD(OnPrivmsg, (u, c, message, tags));
}
}
else
@@ -330,50 +324,39 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
if (!servername.equals_ci(Me->GetName()))
return;
}
- else if (!IRCD->RequiresID && Config->UseStrictPrivmsg)
- {
- BotInfo *bi = BotInfo::Find(receiver);
- if (!bi)
- return;
- Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << u->nick;
- u->SendMessage(bi, _("\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."), bi->nick.c_str(), bi->nick.c_str(), Me->GetName().c_str(), bi->nick.c_str());
- return;
- }
BotInfo *bi = BotInfo::Find(botname, nick_only);
-
if (bi)
{
- if (message[0] == '\1' && message[message.length() - 1] == '\1')
+ Anope::string ctcpname, ctcpbody;
+ if (Anope::ParseCTCP(message, ctcpname, ctcpbody))
{
- if (message.substr(0, 6).equals_ci("\1PING "))
+ if (ctcpname.equals_ci("PING"))
{
- Anope::string buf = message;
- buf.erase(buf.begin());
- buf.erase(buf.end() - 1);
- IRCD->SendCTCP(bi, u->nick, "%s", buf.c_str());
+ IRCD->SendNotice(bi, u->nick, Anope::FormatCTCP("PING", ctcpbody));
}
- else if (message.substr(0, 9).equals_ci("\1VERSION\1"))
+ else if (ctcpname.equals_ci("VERSION"))
{
Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
- IRCD->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)", Anope::VersionBuildString().c_str());
+ IRCD->SendNotice(bi, u->nick, Anope::FormatCTCP("VERSION", Anope::printf("Anope-%s %s -- %s -- %s", Anope::Version().c_str(),
+ Anope::VersionBuildString().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)")));
}
return;
}
EventReturn MOD_RESULT;
- FOREACH_RESULT(OnBotPrivmsg, MOD_RESULT, (u, bi, message));
+ FOREACH_RESULT(OnBotPrivmsg, MOD_RESULT, (u, bi, message, tags));
if (MOD_RESULT == EVENT_STOP)
return;
- bi->OnMessage(u, message);
+ bi->OnMessage(u, message, tags);
}
}
return;
}
-void Quit::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Quit::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
const Anope::string &reason = params[0];
User *user = source.GetUser();
@@ -383,7 +366,7 @@ void Quit::Run(MessageSource &source, const std::vector<Anope::string> &params)
user->Quit(reason);
}
-void SQuit::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void SQuit::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Server *s = Server::Find(params[0]);
@@ -404,7 +387,7 @@ void SQuit::Run(MessageSource &source, const std::vector<Anope::string> &params)
s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
}
-void Stats::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Stats::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
User *u = source.GetUser();
@@ -413,60 +396,58 @@ void Stats::Run(MessageSource &source, const std::vector<Anope::string> &params)
case 'l':
if (u->HasMode("OPER"))
{
- IRCD->SendNumeric(211, source.GetSource(), "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime");
- IRCD->SendNumeric(211, source.GetSource(), "%s %d %d %d %d %d %d %ld", Config->Uplinks[Anope::CurrentUplink].host.c_str(), UplinkSock->WriteBufferLen(), TotalWritten, -1, UplinkSock->ReadBufferLen(), TotalRead, -1, static_cast<long>(Anope::CurTime - Anope::StartTime));
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime");
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), Config->Uplinks[Anope::CurrentUplink].host, UplinkSock->WriteBufferLen(), TotalWritten, -1, UplinkSock->ReadBufferLen(), TotalRead, -1, Anope::CurTime - Anope::StartTime);
}
- IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), params[0][0], "End of /STATS report.");
break;
case 'o':
case 'O':
/* Check whether the user is an operator */
if (!u->HasMode("OPER") && Config->GetBlock("options")->Get<bool>("hidestatso"))
- IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), params[0][0], "End of /STATS report.");
else
{
- for (unsigned i = 0; i < Oper::opers.size(); ++i)
+ for (auto *o : Oper::opers)
{
- Oper *o = Oper::opers[i];
-
const NickAlias *na = NickAlias::Find(o->name);
if (na)
- IRCD->SendNumeric(243, source.GetSource(), "O * * %s %s 0", o->name.c_str(), o->ot->GetName().replace_all_cs(" ", "_").c_str());
+ IRCD->SendNumeric(RPL_STATSOLINE, source.GetSource(), 'O', '*', '*', o->name, o->ot->GetName().replace_all_cs(" ", "_"), '0');
}
- IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), params[0][0], "End of /STATS report.");
}
break;
case 'u':
{
long uptime = static_cast<long>(Anope::CurTime - Anope::StartTime);
- IRCD->SendNumeric(242, source.GetSource(), ":Services up %ld day%s, %02ld:%02ld:%02ld", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60);
- IRCD->SendNumeric(250, source.GetSource(), ":Current users: %lu (%d ops); maximum %u", static_cast<unsigned long>(UserListByNick.size()), OperCount, MaxUserCount);
- IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
+ IRCD->SendNumeric(RPL_STATSUPTIME, source.GetSource(), Anope::printf("Services up %ld day%s, %02ld:%02ld:%02ld", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60));
+ IRCD->SendNumeric(RPL_STATSCONN, source.GetSource(), Anope::printf("Current users: %zu (%d ops); maximum %u", UserListByNick.size(), OperCount, MaxUserCount));
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), params[0][0], "End of /STATS report.");
break;
} /* case 'u' */
default:
- IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
+ IRCD->SendNumeric(RPL_STATSLINKINFO, source.GetSource(), params[0][0], "End of /STATS report.");
}
return;
}
-void Time::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Time::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
time_t t;
time(&t);
struct tm *tm = localtime(&t);
char buf[64];
strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %Y %Z", tm);
- IRCD->SendNumeric(391, source.GetSource(), "%s :%s", Me->GetName().c_str(), buf);
+ IRCD->SendNumeric(RPL_TIME, source.GetSource(), Me->GetName(), buf);
return;
}
-void Topic::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Topic::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Channel *c = Channel::Find(params[0]);
if (c)
@@ -475,28 +456,29 @@ void Topic::Run(MessageSource &source, const std::vector<Anope::string> &params)
return;
}
-void Version::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Version::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
- IRCD->SendNumeric(351, source.GetSource(), "Anope-%s %s :%s -(%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)", Anope::VersionBuildString().c_str());
+ IRCD->SendNumeric(RPL_VERSION, source.GetSource(), "Anope-" + Anope::Version(), Me->GetName(), Anope::printf("%s -(%s) -- %s",
+ IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)", Anope::VersionBuildString().c_str()));
}
-void Whois::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Whois::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
{
User *u = User::Find(params[0]);
if (u && u->server == Me)
{
const BotInfo *bi = BotInfo::Find(u->GetUID());
- IRCD->SendNumeric(311, source.GetSource(), "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str());
+ IRCD->SendNumeric(RPL_WHOISUSER, source.GetSource(), u->nick, u->GetIdent(), u->host, '*', u->realname);
if (bi)
- IRCD->SendNumeric(307, source.GetSource(), "%s :is a registered nick", bi->nick.c_str());
- IRCD->SendNumeric(312, source.GetSource(), "%s %s :%s", u->nick.c_str(), Me->GetName().c_str(), Config->GetBlock("serverinfo")->Get<const Anope::string>("description").c_str());
+ IRCD->SendNumeric(RPL_WHOISREGNICK, source.GetSource(), bi->nick, "is a registered nick");
+ IRCD->SendNumeric(RPL_WHOISSERVER, source.GetSource(), u->nick, Me->GetName(), Config->GetBlock("serverinfo")->Get<const Anope::string>("description"));
if (bi)
- IRCD->SendNumeric(317, source.GetSource(), "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(bi->signon));
- IRCD->SendNumeric(313, source.GetSource(), "%s :is a Network Service", u->nick.c_str());
- IRCD->SendNumeric(318, source.GetSource(), "%s :End of /WHOIS list.", u->nick.c_str());
+ IRCD->SendNumeric(RPL_WHOISIDLE, source.GetSource(), bi->nick, Anope::CurTime - bi->lastmsg, bi->signon, "seconds idle, signon time");
+ IRCD->SendNumeric(RPL_WHOISOPERATOR, source.GetSource(), u->nick, "is a Network Service");
+ IRCD->SendNumeric(RPL_ENDOFWHOIS, source.GetSource(), u->nick, "End of /WHOIS list.");
}
else
- IRCD->SendNumeric(401, source.GetSource(), "%s :No such user.", params[0].c_str());
+ IRCD->SendNumeric(ERR_NOSUCHNICK, source.GetSource(), params[0], "No such user.");
}
diff --git a/src/misc.cpp b/src/misc.cpp
index 3ffab7199..2c1950ba6 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -19,15 +19,19 @@
#include "regexpr.h"
#include "sockets.h"
-#include <errno.h>
-#include <sys/types.h>
+#include <cerrno>
+#include <climits>
+#include <numeric>
+#include <random>
+#include <filesystem>
#include <sys/stat.h>
+#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netdb.h>
#endif
-NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(true), desc(descending)
+NumberList::NumberList(const Anope::string &list, bool descending) : desc(descending)
{
Anope::string error;
commasepstream sep(list);
@@ -42,13 +46,12 @@ NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(tr
if (t == Anope::string::npos)
{
- try
+ if (auto num = Anope::TryConvert<unsigned>(token, &error))
{
- unsigned num = convertTo<unsigned>(token, error, false);
if (error.empty())
- numbers.insert(num);
+ numbers.insert(num.value());
}
- catch (const ConvertException &)
+ else
{
error = "1";
}
@@ -65,15 +68,17 @@ NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(tr
else
{
Anope::string error2;
- try
+ auto n1 = Anope::TryConvert<unsigned>(token.substr(0, t), &error);
+ auto n2 = Anope::TryConvert<unsigned>(token.substr(t + 1), &error);
+ if (n1.has_value() && n2.has_value())
{
- unsigned num1 = convertTo<unsigned>(token.substr(0, t), error, false);
- unsigned num2 = convertTo<unsigned>(token.substr(t + 1), error2, false);
+ auto num1 = n1.value();
+ auto num2 = n2.value();
if (error.empty() && error2.empty())
for (unsigned i = num1; i <= num2; ++i)
numbers.insert(i);
}
- catch (const ConvertException &)
+ else
{
error = "1";
}
@@ -90,10 +95,6 @@ NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(tr
} while (sep.GetToken(token));
}
-NumberList::~NumberList()
-{
-}
-
void NumberList::Process()
{
if (!is_valid)
@@ -106,8 +107,8 @@ void NumberList::Process()
}
else
{
- for (std::set<unsigned>::iterator it = numbers.begin(), it_end = numbers.end(); it != it_end; ++it)
- this->HandleNumber(*it);
+ for (unsigned int number : numbers)
+ this->HandleNumber(number);
}
}
@@ -145,29 +146,30 @@ void ListFormatter::Process(std::vector<Anope::string> &buffer)
std::vector<Anope::string> tcolumns;
std::map<Anope::string, size_t> lengths;
std::set<Anope::string> breaks;
- for (unsigned i = 0; i < this->columns.size(); ++i)
+ for (const auto &column : this->columns)
{
- tcolumns.push_back(Language::Translate(this->nc, this->columns[i].c_str()));
- lengths[this->columns[i]] = tcolumns[i].length();
+ tcolumns.emplace_back(Language::Translate(this->nc, column.c_str()));
+ lengths[column] = column.length();
}
- for (unsigned i = 0; i < this->entries.size(); ++i)
+ for (auto &entry : this->entries)
{
- ListEntry &e = this->entries[i];
- for (unsigned j = 0; j < this->columns.size(); ++j)
- if (e[this->columns[j]].length() > lengths[this->columns[j]])
- lengths[this->columns[j]] = e[this->columns[j]].length();
+ for (const auto &column : this->columns)
+ {
+ if (entry[column].length() > lengths[column])
+ lengths[column] = entry[column].length();
+ }
}
- unsigned length = 0;
- for (std::map<Anope::string, size_t>::iterator it = lengths.begin(), it_end = lengths.end(); it != it_end; ++it)
+ unsigned total_length = 0;
+ for (const auto &[column, length] : lengths)
{
/* Break lines at 80 chars */
- if (length > 80)
+ if (total_length > 80)
{
- breaks.insert(it->first);
- length = 0;
+ breaks.insert(column);
+ total_length = 0;
}
else
- length += it->second;
+ total_length += length;
}
/* Only put a list header if more than 1 column */
@@ -191,10 +193,8 @@ void ListFormatter::Process(std::vector<Anope::string> &buffer)
buffer.push_back(s);
}
- for (unsigned i = 0; i < this->entries.size(); ++i)
+ for (auto &entry : this->entries)
{
- ListEntry &e = this->entries[i];
-
Anope::string s;
for (unsigned j = 0; j < this->columns.size(); ++j)
{
@@ -205,16 +205,16 @@ void ListFormatter::Process(std::vector<Anope::string> &buffer)
}
else if (!s.empty())
s += " ";
- s += e[this->columns[j]];
+ s += entry[this->columns[j]];
if (j + 1 != this->columns.size())
- for (unsigned k = e[this->columns[j]].length(); k < lengths[this->columns[j]]; ++k)
+ for (unsigned k = entry[this->columns[j]].length(); k < lengths[this->columns[j]]; ++k)
s += " ";
}
buffer.push_back(s);
}
}
-InfoFormatter::InfoFormatter(NickCore *acc) : nc(acc), longest(0)
+InfoFormatter::InfoFormatter(NickCore *acc) : nc(acc)
{
}
@@ -222,23 +222,23 @@ void InfoFormatter::Process(std::vector<Anope::string> &buffer)
{
buffer.clear();
- for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = this->replies.begin(), it_end = this->replies.end(); it != it_end; ++it)
+ for (const auto &[key, value] : this->replies)
{
Anope::string s;
- for (unsigned i = it->first.length(); i < this->longest; ++i)
+ for (unsigned i = key.length(); i < this->longest; ++i)
s += " ";
- s += it->first + ": " + Language::Translate(this->nc, it->second.c_str());
+ s += key + ": " + Language::Translate(this->nc, value.c_str());
buffer.push_back(s);
}
}
-Anope::string& InfoFormatter::operator[](const Anope::string &key)
+Anope::string &InfoFormatter::operator[](const Anope::string &key)
{
Anope::string tkey = Language::Translate(this->nc, key.c_str());
if (tkey.length() > this->longest)
this->longest = tkey.length();
- this->replies.push_back(std::make_pair(tkey, ""));
+ this->replies.emplace_back(tkey, "");
return this->replies.back().second;
}
@@ -246,11 +246,11 @@ void InfoFormatter::AddOption(const Anope::string &opt)
{
Anope::string options = Language::Translate(this->nc, "Options");
Anope::string *optstr = NULL;
- for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = this->replies.begin(), it_end = this->replies.end(); it != it_end; ++it)
+ for (auto &[option, value] : this->replies)
{
- if (it->first == options)
+ if (option == options)
{
- optstr = &it->second;
+ optstr = &value;
break;
}
}
@@ -265,10 +265,7 @@ void InfoFormatter::AddOption(const Anope::string &opt)
bool Anope::IsFile(const Anope::string &filename)
{
struct stat fileinfo;
- if (!stat(filename.c_str(), &fileinfo))
- return true;
-
- return false;
+ return stat(filename.c_str(), &fileinfo) == 0;
}
time_t Anope::DoTime(const Anope::string &s)
@@ -276,37 +273,28 @@ time_t Anope::DoTime(const Anope::string &s)
if (s.empty())
return 0;
- int amount = 0;
Anope::string end;
-
- try
+ auto amount = Anope::Convert<int>(s, -1, &end);
+ if (!end.empty())
{
- amount = convertTo<int>(s, end, false);
- if (!end.empty())
+ switch (end[0])
{
- switch (end[0])
- {
- case 's':
- return amount;
- case 'm':
- return amount * 60;
- case 'h':
- return amount * 3600;
- case 'd':
- return amount * 86400;
- case 'w':
- return amount * 86400 * 7;
- case 'y':
- return amount * 86400 * 365;
- default:
- break;
- }
+ case 's':
+ return amount;
+ case 'm':
+ return amount * 60;
+ case 'h':
+ return amount * 3600;
+ case 'd':
+ return amount * 86400;
+ case 'w':
+ return amount * 86400 * 7;
+ case 'y':
+ return amount * 86400 * 365;
+ default:
+ break;
}
}
- catch (const ConvertException &)
- {
- amount = -1;
- }
return amount;
}
@@ -320,43 +308,39 @@ Anope::string Anope::Duration(time_t t, const NickCore *nc)
time_t minutes = (t / 60) % 60;
time_t seconds = (t) % 60;
- if (!years && !days && !hours && !minutes)
- return stringify(seconds) + " " + (seconds != 1 ? Language::Translate(nc, _("seconds")) : Language::Translate(nc, _("second")));
- else
+ Anope::string buffer;
+ if (years)
{
- bool need_comma = false;
- Anope::string buffer;
- if (years)
- {
- buffer = stringify(years) + " " + (years != 1 ? Language::Translate(nc, _("years")) : Language::Translate(nc, _("year")));
- need_comma = true;
- }
- if (days)
- {
- buffer += need_comma ? ", " : "";
- buffer += stringify(days) + " " + (days != 1 ? Language::Translate(nc, _("days")) : Language::Translate(nc, _("day")));
- need_comma = true;
- }
- if (hours)
- {
- buffer += need_comma ? ", " : "";
- buffer += stringify(hours) + " " + (hours != 1 ? Language::Translate(nc, _("hours")) : Language::Translate(nc, _("hour")));
- need_comma = true;
- }
- if (minutes)
- {
- buffer += need_comma ? ", " : "";
- buffer += stringify(minutes) + " " + (minutes != 1 ? Language::Translate(nc, _("minutes")) : Language::Translate(nc, _("minute")));
- }
- return buffer;
+ buffer = Anope::printf(Language::Translate(nc, years, N_("%lld year", "%lld years")), (long long)years);
}
+ if (days)
+ {
+ buffer += buffer.empty() ? "" : ", ";
+ buffer += Anope::printf(Language::Translate(nc, days, N_("%lld day", "%lld days")), (long long)days);
+ }
+ if (hours)
+ {
+ buffer += buffer.empty() ? "" : ", ";
+ buffer += Anope::printf(Language::Translate(nc, hours, N_("%lld hour", "%lld hours")), (long long)hours);
+ }
+ if (minutes)
+ {
+ buffer += buffer.empty() ? "" : ", ";
+ buffer += Anope::printf(Language::Translate(nc, minutes, N_("%lld minute", "%lld minutes")), (long long)minutes);
+ }
+ if (seconds || buffer.empty())
+ {
+ buffer += buffer.empty() ? "" : ", ";
+ buffer += Anope::printf(Language::Translate(nc, seconds, N_("%lld second", "%lld seconds")), (long long)seconds);
+ }
+ return buffer;
}
Anope::string Anope::strftime(time_t t, const NickCore *nc, bool short_output)
{
tm tm = *localtime(&t);
char buf[BUFSIZE];
- strftime(buf, sizeof(buf), Language::Translate(nc, _("%b %d %H:%M:%S %Y %Z")), &tm);
+ strftime(buf, sizeof(buf), Language::Translate(nc, _("%b %d %Y %H:%M:%S %Z")), &tm);
if (short_output)
return buf;
if (t < Anope::CurTime)
@@ -371,36 +355,28 @@ Anope::string Anope::Expires(time_t expires, const NickCore *nc)
{
if (!expires)
return Language::Translate(nc, NO_EXPIRE);
- else if (expires <= Anope::CurTime)
+
+ if (expires <= Anope::CurTime)
return Language::Translate(nc, _("expires momentarily"));
- else
- {
- char buf[256];
- time_t diff = expires - Anope::CurTime + 59;
- if (diff >= 86400)
- {
- int days = diff / 86400;
- snprintf(buf, sizeof(buf), Language::Translate(nc, days == 1 ? _("expires in %d day") : _("expires in %d days")), days);
- }
- else
- {
- if (diff <= 3600)
- {
- int minutes = diff / 60;
- snprintf(buf, sizeof(buf), Language::Translate(nc, minutes == 1 ? _("expires in %d minute") : _("expires in %d minutes")), minutes);
- }
- else
- {
- int hours = diff / 3600, minutes;
- diff -= hours * 3600;
- minutes = diff / 60;
- snprintf(buf, sizeof(buf), Language::Translate(nc, hours == 1 && minutes == 1 ? _("expires in %d hour, %d minute") : (hours == 1 && minutes != 1 ? _("expires in %d hour, %d minutes") : (hours != 1 && minutes == 1 ? _("expires in %d hours, %d minute") : _("expires in %d hours, %d minutes")))), hours, minutes);
- }
- }
+ // This will get inlined when compiled with optimisations.
+ auto nearest = [](auto timeleft, auto roundto) {
+ if ((timeleft % roundto) <= (roundto / 2))
+ return timeleft - (timeleft % roundto);
+ return timeleft - (timeleft % roundto) + roundto;
+ };
- return buf;
- }
+ // In order to get a shorter result we round to the nearest period.
+ auto timeleft = expires - Anope::CurTime;
+ if (timeleft >= 31536000)
+ timeleft = nearest(timeleft, 86400); // Nearest day if its more than a year
+ else if (timeleft >= 86400)
+ timeleft = nearest(timeleft, 3600); // Nearest hour if its more than a day
+ else if (timeleft >= 3600)
+ timeleft = nearest(timeleft, 60); // Nearest minute if its more than an hour
+
+ auto duration = Anope::Duration(timeleft, nc);
+ return Anope::printf(Language::Translate(nc, _("expires in %s")), duration.c_str());
}
bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive, bool use_regex)
@@ -507,29 +483,11 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case
return m == mask_len;
}
-void Anope::Encrypt(const Anope::string &src, Anope::string &dest)
+bool Anope::Encrypt(const Anope::string &src, Anope::string &dest)
{
EventReturn MOD_RESULT;
FOREACH_RESULT(OnEncrypt, MOD_RESULT, (src, dest));
- static_cast<void>(MOD_RESULT);
-}
-
-bool Anope::Decrypt(const Anope::string &src, Anope::string &dest)
-{
- size_t pos = src.find(':');
- if (pos == Anope::string::npos)
- {
- Log() << "Error: Anope::Decrypt() called with invalid password string (" << src << ")";
- return false;
- }
- Anope::string hashm(src.begin(), src.begin() + pos);
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnDecrypt, MOD_RESULT, (hashm, src, dest));
- if (MOD_RESULT == EVENT_ALLOW)
- return true;
-
- return false;
+ return MOD_RESULT == EVENT_ALLOW &&!dest.empty();
}
Anope::string Anope::printf(const char *fmt, ...)
@@ -602,7 +560,7 @@ int Anope::LastErrorCode()
#endif
}
-const Anope::string Anope::LastError()
+Anope::string Anope::LastError()
{
#ifndef _WIN32
return strerror(errno);
@@ -619,27 +577,27 @@ const Anope::string Anope::LastError()
Anope::string Anope::Version()
{
#ifdef VERSION_GIT
- return stringify(VERSION_MAJOR) + "." + stringify(VERSION_MINOR) + "." + stringify(VERSION_PATCH) + VERSION_EXTRA + " (" + VERSION_GIT + ")";
+ return Anope::ToString(VERSION_MAJOR) + "." + Anope::ToString(VERSION_MINOR) + "." + Anope::ToString(VERSION_PATCH) + VERSION_EXTRA + " (" + VERSION_GIT + ")";
#else
- return stringify(VERSION_MAJOR) + "." + stringify(VERSION_MINOR) + "." + stringify(VERSION_PATCH) + VERSION_EXTRA;
+ return Anope::ToString(VERSION_MAJOR) + "." + Anope::ToString(VERSION_MINOR) + "." + Anope::ToString(VERSION_PATCH) + VERSION_EXTRA;
#endif
}
Anope::string Anope::VersionShort()
{
- return stringify(VERSION_MAJOR) + "." + stringify(VERSION_MINOR) + "." + stringify(VERSION_PATCH);
+ return Anope::ToString(VERSION_MAJOR) + "." + Anope::ToString(VERSION_MINOR) + "." + Anope::ToString(VERSION_PATCH);
}
Anope::string Anope::VersionBuildString()
{
#ifdef REPRODUCIBLE_BUILD
- Anope::string s = "build #" + stringify(BUILD);
+ Anope::string s = "build #" + Anope::ToString(BUILD);
#else
- Anope::string s = "build #" + stringify(BUILD) + ", compiled " + Anope::compiled;
+ Anope::string s = "build #" + Anope::ToString(BUILD) + ", compiled " + Anope::compiled;
#endif
Anope::string flags;
-#ifdef DEBUG_BUILD
+#if DEBUG_BUILD
flags += "D";
#endif
#ifdef VERSION_GIT
@@ -770,6 +728,145 @@ Anope::string Anope::Random(size_t len)
};
Anope::string buf;
for (size_t i = 0; i < len; ++i)
- buf.append(chars[rand() % sizeof(chars)]);
+ buf.append(chars[Anope::RandomNumber() % sizeof(chars)]);
return buf;
}
+
+int Anope::RandomNumber()
+{
+ static std::random_device device;
+ static std::mt19937 engine(device());
+ static std::uniform_int_distribution<int> dist(INT_MIN, INT_MAX);
+ return dist(engine);
+}
+
+// Implementation of https://en.wikipedia.org/wiki/Levenshtein_distance
+size_t Anope::Distance(const Anope::string &s1, const Anope::string &s2)
+{
+ if (s1.empty())
+ return s2.length();
+ if (s2.empty())
+ return s1.length();
+
+ std::vector<size_t> costs(s2.length() + 1);
+ std::iota(costs.begin(), costs.end(), 0);
+
+ size_t i = 0;
+ for (const auto c1 : s1)
+ {
+ costs[0] = i + 1;
+ size_t corner = i;
+ size_t j = 0;
+ for (const auto &c2 : s2)
+ {
+ size_t upper = costs[j + 1];
+ if (c1 == c2)
+ costs[j + 1] = corner;
+ else
+ {
+ size_t t = upper < corner ? upper : corner;
+ costs[j + 1] = (costs[j] < t ? costs[j] : t) + 1;
+ }
+ corner = upper;
+ j++;
+ }
+ i++;
+ }
+ return costs[s2.length()];
+}
+
+void Anope::UpdateTime()
+{
+#ifdef _WIN32
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+
+ CurTime = time(nullptr);
+ CurTimeNs = st.wMilliseconds;
+#elif HAVE_CLOCK_GETTIME
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ CurTime = ts.tv_sec;
+ CurTimeNs = ts.tv_nsec;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, nullptr);
+
+ CurTime = tv.tv_sec;
+ CurTimeNs = tv.tv_usec * 1000;
+#endif
+}
+
+Anope::string Anope::Expand(const Anope::string &base, const Anope::string &fragment)
+{
+ if (fragment.empty())
+ return ""; // We can't expand an empty fragment.
+
+ // The fragment is an absolute path, don't modify it.
+ if (std::filesystem::path(fragment.str()).is_absolute())
+ return fragment;
+
+#ifdef _WIN32
+ static constexpr const char separator = '\\';
+#else
+ static constexpr const char separator = '/';
+#endif
+
+ // The fragment is relative to a home directory, expand that.
+ if (!fragment.compare(0, 2, "~/", 2))
+ {
+ const auto *homedir = getenv("HOME");
+ if (homedir && *homedir)
+ return Anope::printf("%s%c%s", homedir, separator, fragment.c_str() + 2);
+ }
+
+ return Anope::printf("%s%c%s", base.c_str(), separator, fragment.c_str());
+}
+
+Anope::string Anope::FormatCTCP(const Anope::string &name, const Anope::string &value)
+{
+ if (value.empty())
+ return Anope::printf("\1%s\1", name.c_str());
+
+ return Anope::printf("\1%s %s\1", name.c_str(), value.c_str());
+}
+
+bool Anope::ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body)
+{
+ // According to draft-oakley-irc-ctcp-02 a valid CTCP must begin with SOH and
+ // contain at least one octet which is not NUL, SOH, CR, LF, or SPACE. As most
+ // of these are restricted at the protocol level we only need to check for SOH
+ // and SPACE.
+ if (text.length() < 2 || text[0] != '\x1' || text[1] == '\x1' || text[1] == ' ')
+ {
+ name.clear();
+ body.clear();
+ return false;
+ }
+
+ auto end_of_name = text.find(' ', 2);
+ auto end_of_ctcp = *text.rbegin() == '\x1' ? 1 : 0;
+ if (end_of_name == std::string::npos)
+ {
+ // The CTCP only contains a name.
+ name = text.substr(1, text.length() - 1 - end_of_ctcp);
+ body.clear();
+ return true;
+ }
+
+ // The CTCP contains a name and a body.
+ name = text.substr(1, end_of_name - 1);
+
+ auto start_of_body = text.find_first_not_of(' ', end_of_name + 1);
+ if (start_of_body == std::string::npos)
+ {
+ // The CTCP body is provided but empty.
+ body.clear();
+ return true;
+ }
+
+ // The CTCP body provided was non-empty.
+ body = text.substr(start_of_body, text.length() - start_of_body - end_of_ctcp);
+ return true;
+}
diff --git a/src/modes.cpp b/src/modes.cpp
index 0bd2019c7..fdaae7716 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -39,16 +39,14 @@ static std::vector<ChannelModeStatus *> ChannelModesByStatus;
/* Number of generic modes we support */
unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0;
-struct StackerInfo
+struct StackerInfo final
{
/* Modes to be added */
std::list<std::pair<Mode *, Anope::string> > AddModes;
/* Modes to be deleted */
std::list<std::pair<Mode *, Anope::string> > DelModes;
/* Bot this is sent from */
- BotInfo *bi;
-
- StackerInfo() : bi(NULL) { }
+ BotInfo *bi = nullptr;
/** Add a mode to this object
* @param mode The mode
@@ -58,10 +56,6 @@ struct StackerInfo
void AddMode(Mode *mode, bool set, const Anope::string &param);
};
-ChannelStatus::ChannelStatus()
-{
-}
-
ChannelStatus::ChannelStatus(const Anope::string &m) : modes(m)
{
}
@@ -101,9 +95,9 @@ Anope::string ChannelStatus::BuildModePrefixList() const
{
Anope::string ret;
- for (size_t i = 0; i < modes.length(); ++i)
+ for (auto mode : modes)
{
- ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
if (cm != NULL && cm->type == MODE_STATUS)
{
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
@@ -118,10 +112,6 @@ Mode::Mode(const Anope::string &mname, ModeClass mcl, char mch, ModeType mt) : n
{
}
-Mode::~Mode()
-{
-}
-
bool Mode::CanSet(User *u) const
{
return true;
@@ -154,9 +144,9 @@ ChannelMode *ChannelMode::Wrap(Anope::string &param)
ChannelMode *ChannelMode::Unwrap(Anope::string &param)
{
- for (unsigned i = 0; i < listeners.size(); ++i)
+ for (auto *listener : listeners)
{
- ChannelMode *cm = listeners[i]->Unwrap(this, param);
+ ChannelMode *cm = listener->Unwrap(this, param);
if (cm != this)
return cm;
}
@@ -243,10 +233,7 @@ bool UserModeNoone::CanSet(User *u) const
bool ChannelModeKey::IsValid(Anope::string &value) const
{
- if (!value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos)
- return true;
-
- return false;
+ return !value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos;
}
bool ChannelModeOperOnly::CanSet(User *u) const
@@ -307,13 +294,14 @@ void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string &param)
}
/* Add this mode and its param to our list */
- list->push_back(std::make_pair(mode, param));
+ list->emplace_back(mode, param);
}
-static class ModePipe : public Pipe
+static class ModePipe final
+ : public Pipe
{
- public:
- void OnNotify()
+public:
+ void OnNotify() override
{
ModeManager::ProcessModes();
}
@@ -330,7 +318,7 @@ static StackerInfo *GetInfo(List &l, Object *o)
if (it != l.end())
return it->second;
- StackerInfo *s = new StackerInfo();
+ auto *s = new StackerInfo();
l[o] = s;
return s;
}
@@ -339,27 +327,33 @@ static StackerInfo *GetInfo(List &l, Object *o)
* @param info The stacker info for a channel or user
* @return a list of strings
*/
-static std::list<Anope::string> BuildModeStrings(StackerInfo *info)
+static auto BuildModeStrings(StackerInfo *info)
{
- std::list<Anope::string> ret;
+ std::list<std::pair<Anope::string, std::vector<Anope::string>>> ret;
std::list<std::pair<Mode *, Anope::string> >::iterator it, it_end;
- Anope::string buf = "+", parambuf;
+ Anope::string buf = "+";
+ std::vector<Anope::string> parambuf;
unsigned NModes = 0;
+ size_t paramlen = 0;
for (it = info->AddModes.begin(), it_end = info->AddModes.end(); it != it_end; ++it)
{
- if (++NModes > IRCD->MaxModes || (buf.length() + parambuf.length() > IRCD->MaxLine - 100)) // Leave room for command, channel, etc
+ if ((IRCD->MaxModes && ++NModes > IRCD->MaxModes) || (IRCD->MaxLine && buf.length() + paramlen > IRCD->MaxLine - 100)) // Leave room for command, channel, etc
{
- ret.push_back(buf + parambuf);
+ ret.push_back({buf, parambuf});
buf = "+";
parambuf.clear();
+ paramlen = 0;
NModes = 1;
}
buf += it->first->mchar;
if (!it->second.empty())
- parambuf += " " + it->second;
+ {
+ parambuf.push_back(it->second);
+ paramlen += it->second.length() + 1;
+ }
}
if (buf[buf.length() - 1] == '+')
@@ -368,25 +362,29 @@ static std::list<Anope::string> BuildModeStrings(StackerInfo *info)
buf += "-";
for (it = info->DelModes.begin(), it_end = info->DelModes.end(); it != it_end; ++it)
{
- if (++NModes > IRCD->MaxModes || (buf.length() + parambuf.length() > IRCD->MaxLine - 100)) // Leave room for command, channel, etc
+ if ((IRCD->MaxModes && ++NModes > IRCD->MaxModes) || (IRCD->MaxLine && buf.length() + paramlen > IRCD->MaxLine - 100)) // Leave room for command, channel, etc
{
- ret.push_back(buf + parambuf);
+ ret.push_back({buf, parambuf});
buf = "-";
parambuf.clear();
+ paramlen = 0;
NModes = 1;
}
buf += it->first->mchar;
if (!it->second.empty())
- parambuf += " " + it->second;
+ {
+ parambuf.push_back(it->second);
+ paramlen += it->second.length() + 1;
+ }
}
if (buf[buf.length() - 1] == '-')
buf.erase(buf.length() - 1);
if (!buf.empty())
- ret.push_back(buf + parambuf);
+ ret.push_back({buf, parambuf});
return ret;
}
@@ -400,7 +398,7 @@ bool ModeManager::AddUserMode(UserMode *um)
if (um->name.empty())
{
- um->name = stringify(++GenericUserModes);
+ um->name = Anope::ToString(++GenericUserModes);
Log() << "ModeManager: Added generic support for user mode " << um->mchar;
}
@@ -427,7 +425,7 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
if (cm->name.empty())
{
- cm->name = stringify(++GenericChannelModes);
+ cm->name = Anope::ToString(++GenericChannelModes);
Log() << "ModeManager: Added generic support for channel mode " << cm->mchar;
}
@@ -456,8 +454,8 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
FOREACH_MOD(OnChannelModeAdd, (cm));
- for (unsigned int i = 0; i < ChannelModes.size(); ++i)
- ChannelModes[i]->Check();
+ for (auto *cmode : ChannelModes)
+ cmode->Check();
return true;
}
@@ -589,7 +587,7 @@ const std::vector<ChannelModeStatus *> &ModeManager::GetStatusChannelModesByRank
return ChannelModesByStatus;
}
-static struct StatusSort
+static struct StatusSort final
{
bool operator()(ChannelModeStatus *cm1, ChannelModeStatus *cm2) const
{
@@ -600,10 +598,8 @@ static struct StatusSort
void ModeManager::RebuildStatusModes()
{
ChannelModesByStatus.clear();
- for (unsigned j = 0; j < ChannelModesIdx.size(); ++j)
+ for (auto *cm : ChannelModesIdx)
{
- ChannelMode *cm = ChannelModesIdx[j];
-
if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
ChannelModesByStatus.push_back(anope_dynamic_static_cast<ChannelModeStatus *>(cm));
}
@@ -640,30 +636,22 @@ void ModeManager::ProcessModes()
{
if (!UserStackerObjects.empty())
{
- for (std::map<User *, StackerInfo *>::const_iterator it = UserStackerObjects.begin(), it_end = UserStackerObjects.end(); it != it_end; ++it)
+ for (const auto &[u, s] : UserStackerObjects)
{
- User *u = it->first;
- StackerInfo *s = it->second;
-
- std::list<Anope::string> ModeStrings = BuildModeStrings(s);
- for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
- IRCD->SendMode(s->bi, u, "%s", lit->c_str());
- delete it->second;
+ for (const auto &modestr : BuildModeStrings(s))
+ IRCD->SendModeInternal(s->bi, u, modestr.first, modestr.second);
+ delete s;
}
UserStackerObjects.clear();
}
if (!ChannelStackerObjects.empty())
{
- for (std::map<Channel *, StackerInfo *>::const_iterator it = ChannelStackerObjects.begin(), it_end = ChannelStackerObjects.end(); it != it_end; ++it)
+ for (const auto &[c, s] : ChannelStackerObjects)
{
- Channel *c = it->first;
- StackerInfo *s = it->second;
-
- std::list<Anope::string> ModeStrings = BuildModeStrings(s);
- for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
- IRCD->SendMode(s->bi, c, "%s", lit->c_str());
- delete it->second;
+ for (const auto &modestr : BuildModeStrings(s))
+ IRCD->SendModeInternal(s->bi, c, modestr.first, modestr.second);
+ delete s;
}
ChannelStackerObjects.clear();
}
@@ -676,9 +664,8 @@ static void StackerDel(std::map<T *, StackerInfo *> &map, T *obj)
if (it != map.end())
{
StackerInfo *si = it->second;
- std::list<Anope::string> ModeStrings = BuildModeStrings(si);
- for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit)
- IRCD->SendMode(si->bi, obj, "%s", lit->c_str());
+ for (const auto &modestr : BuildModeStrings(si))
+ IRCD->SendModeInternal(si->bi, obj, modestr.first, modestr.second);
delete si;
map.erase(it);
@@ -742,7 +729,7 @@ void ModeManager::StackerDel(Mode *m)
}
}
-Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0), family(0)
+Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh)
{
Anope::string n, u, h;
@@ -796,22 +783,15 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh
&cidr_range = this->host.substr(sl + 1);
sockaddrs addr(cidr_ip);
-
- try
+ auto range = Anope::TryConvert<unsigned short>(cidr_range);
+ if (addr.valid() && range.has_value())
{
- if (addr.valid() && cidr_range.is_pos_number_only())
- {
- this->cidr_len = convertTo<unsigned short>(cidr_range);
-
- /* If we got here, cidr_len is a valid number. */
-
- this->host = cidr_ip;
- this->family = addr.family();
+ this->cidr_len = range.value();
+ this->host = cidr_ip;
+ this->family = addr.family();
- Log(LOG_DEBUG) << "Ban " << mask << " has cidr " << this->cidr_len;
- }
+ Log(LOG_DEBUG) << "Ban " << mask << " has cidr " << this->cidr_len;
}
- catch (const ConvertException &) { }
}
}
@@ -819,12 +799,12 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh
this->real.clear();
}
-const Anope::string Entry::GetMask() const
+Anope::string Entry::GetMask() const
{
return this->mask;
}
-const Anope::string Entry::GetNUHMask() const
+Anope::string Entry::GetNUHMask() const
{
Anope::string n = nick.empty() ? "*" : nick,
u = user.empty() ? "*" : user,
@@ -835,11 +815,11 @@ const Anope::string Entry::GetNUHMask() const
{
case AF_INET:
if (cidr_len <= 32)
- c = "/" + stringify(cidr_len);
+ c = "/" + Anope::ToString(cidr_len);
break;
case AF_INET6:
if (cidr_len <= 128)
- c = "/" + stringify(cidr_len);
+ c = "/" + Anope::ToString(cidr_len);
break;
}
@@ -855,8 +835,7 @@ bool Entry::Matches(User *u, bool full) const
if (cm != NULL && cm->type == MODE_LIST)
{
ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
- if (cml->Matches(u, this))
- return true;
+ return cml->Matches(u, this);
}
}
diff --git a/src/module.cpp b/src/module.cpp
index ba4076306..6b6a4e36c 100644
--- a/src/module.cpp
+++ b/src/module.cpp
@@ -11,7 +11,7 @@
#include "language.h"
#include "account.h"
-#ifdef GETTEXT_FOUND
+#if HAVE_LOCALIZATION
# include <libintl.h>
#endif
@@ -39,14 +39,14 @@ Module::Module(const Anope::string &modname, const Anope::string &, ModType modt
ModuleManager::Modules.push_back(this);
-#if GETTEXT_FOUND
- for (unsigned i = 0; i < Language::Languages.size(); ++i)
+#if HAVE_LOCALIZATION
+ for (const auto &language : Language::Languages)
{
/* Remove .UTF-8 or any other suffix */
Anope::string lang;
- sepstream(Language::Languages[i], '.').GetToken(lang);
+ sepstream(language, '.').GetToken(lang);
- if (Anope::IsFile(Anope::LocaleDir + "/" + lang + "/LC_MESSAGES/" + modname + ".mo"))
+ if (Anope::IsFile(Anope::ExpandLocale(lang + "/LC_MESSAGES/" + modname + ".mo")))
{
if (!bindtextdomain(this->name.c_str(), Anope::LocaleDir.c_str()))
Log() << "Error calling bindtextdomain, " << Anope::LastError();
@@ -75,7 +75,7 @@ Module::~Module()
if (it != ModuleManager::Modules.end())
ModuleManager::Modules.erase(it);
-#if GETTEXT_FOUND
+#if HAVE_LOCALIZATION
std::vector<Anope::string>::iterator dit = std::find(Language::Domains.begin(), Language::Domains.end(), this->name);
if (dit != Language::Domains.end())
Language::Domains.erase(dit);
diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp
index 3ea0b2fa4..07dea3228 100644
--- a/src/modulemanager.cpp
+++ b/src/modulemanager.cpp
@@ -15,39 +15,33 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifndef _WIN32
-#include <dirent.h>
#include <sys/types.h>
#include <dlfcn.h>
#endif
+#include <filesystem>
+
std::list<Module *> ModuleManager::Modules;
std::vector<Module *> ModuleManager::EventHandlers[I_SIZE];
#ifdef _WIN32
void ModuleManager::CleanupRuntimeDirectory()
{
- Anope::string dirbuf = Anope::DataDir + "/runtime";
+ Anope::string dirbuf = Anope::ExpandData("runtime");
Log(LOG_DEBUG) << "Cleaning out Module run time directory (" << dirbuf << ") - this may take a moment, please wait";
-
- DIR *dirp = opendir(dirbuf.c_str());
- if (!dirp)
+ try
{
- Log(LOG_DEBUG) << "Cannot open directory (" << dirbuf << ")";
- return;
+ for (const auto &entry : std::filesystem::directory_iterator(dirbuf.str()))
+ {
+ if (entry.is_regular_file())
+ std::filesystem::remove(entry);
+ }
}
-
- for (dirent *dp; (dp = readdir(dirp));)
+ catch (const std::filesystem::filesystem_error &err)
{
- if (!dp->d_ino)
- continue;
- if (Anope::string(dp->d_name).equals_cs(".") || Anope::string(dp->d_name).equals_cs(".."))
- continue;
- Anope::string filebuf = dirbuf + "/" + dp->d_name;
- unlink(filebuf.c_str());
+ Log(LOG_DEBUG) << "Cannot open directory (" << dirbuf << "): " << err.what();
}
-
- closedir(dirp);
}
/**
@@ -61,7 +55,7 @@ void ModuleManager::CleanupRuntimeDirectory()
*/
static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &output)
{
- Anope::string input = Anope::ModuleDir + "/modules/" + name + ".so";
+ const auto input = Anope::ExpandModule(name + DLL_EXT);
struct stat s;
if (stat(input.c_str(), &s) == -1)
@@ -139,7 +133,7 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
#ifdef _WIN32
/* Generate the filename for the temporary copy of the module */
- Anope::string pbuf = Anope::DataDir + "/runtime/" + modname + ".so.XXXXXX";
+ auto pbuf = Anope::ExpandData("runtime/" + modname + DLL_EXT ".XXXXXX");
/* Don't skip return value checking! -GD */
ModuleReturn ret = moduleCopyFile(modname, pbuf);
@@ -152,7 +146,7 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
return ret;
}
#else
- Anope::string pbuf = Anope::ModuleDir + "/modules/" + modname + ".so";
+ const auto pbuf = Anope::ExpandModule(modname + DLL_EXT);
#endif
dlerror();
@@ -273,8 +267,8 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
Log(LOG_DEBUG) << "Module " << modname << " loaded.";
/* Attach module to all events */
- for (unsigned i = 0; i < I_SIZE; ++i)
- EventHandlers[i].push_back(m);
+ for (auto &mods : EventHandlers)
+ mods.push_back(m);
m->Prioritize();
@@ -313,10 +307,8 @@ ModuleReturn ModuleManager::UnloadModule(Module *m, User *u)
Module *ModuleManager::FindModule(const Anope::string &name)
{
- for (std::list<Module *>::const_iterator it = Modules.begin(), it_end = Modules.end(); it != it_end; ++it)
+ for (auto *m : Modules)
{
- Module *m = *it;
-
if (m->name.equals_ci(name))
return m;
}
@@ -326,10 +318,8 @@ Module *ModuleManager::FindModule(const Anope::string &name)
Module *ModuleManager::FindFirstOf(ModType type)
{
- for (std::list<Module *>::const_iterator it = Modules.begin(), it_end = Modules.end(); it != it_end; ++it)
+ for (auto *m : Modules)
{
- Module *m = *it;
-
if (m->type & type)
return m;
}
@@ -358,7 +348,7 @@ void ModuleManager::RequireVersion(int major, int minor, int patch)
}
}
- throw ModuleException("This module requires version " + stringify(major) + "." + stringify(minor) + "." + stringify(patch) + " - this is " + Anope::VersionShort());
+ throw ModuleException("This module requires version " + Anope::ToString(major) + "." + Anope::ToString(minor) + "." + Anope::ToString(patch) + " - this is " + Anope::VersionShort());
}
ModuleReturn ModuleManager::DeleteModule(Module *m)
@@ -395,9 +385,8 @@ ModuleReturn ModuleManager::DeleteModule(Module *m)
void ModuleManager::DetachAll(Module *mod)
{
- for (unsigned i = 0; i < I_SIZE; ++i)
+ for (auto &mods : EventHandlers)
{
- std::vector<Module *> &mods = EventHandlers[i];
std::vector<Module *>::iterator it2 = std::find(mods.begin(), mods.end(), mod);
if (it2 != mods.end())
mods.erase(it2);
@@ -446,43 +435,62 @@ bool ModuleManager::SetPriority(Module *mod, Implementation i, Priority s, Modul
{
/* Dummy value */
case PRIORITY_DONTCARE:
+ {
swap = false;
break;
+ }
/* Module wants to be first, sod everything else */
case PRIORITY_FIRST:
+ {
swap_pos = 0;
break;
+ }
/* Module is submissive and wants to be last... awww. */
case PRIORITY_LAST:
+ {
if (EventHandlers[i].empty())
swap_pos = 0;
else
swap_pos = EventHandlers[i].size() - 1;
break;
+ }
/* Place this module after a set of other modules */
case PRIORITY_AFTER:
+ {
/* Find the latest possible position */
swap_pos = 0;
swap = false;
for (size_t x = 0, end = EventHandlers[i].size(); x != end; ++x)
+ {
for (size_t n = 0; n < sz; ++n)
+ {
if (modules[n] && EventHandlers[i][x] == modules[n] && x >= swap_pos && source <= swap_pos)
{
swap_pos = x;
swap = true;
}
+ }
+ }
break;
+ }
/* Place this module before a set of other modules */
case PRIORITY_BEFORE:
+ {
swap_pos = EventHandlers[i].size() - 1;
swap = false;
for (size_t x = 0, end = EventHandlers[i].size(); x != end; ++x)
+ {
for (size_t n = 0; n < sz; ++n)
+ {
if (modules[n] && EventHandlers[i][x] == modules[n] && x <= swap_pos && source >= swap_pos)
{
swap = true;
swap_pos = x;
}
+ }
+ }
+ break;
+ }
}
/* Do we need to swap? */
@@ -510,16 +518,17 @@ void ModuleManager::UnloadAll()
{
std::vector<Anope::string> modules;
for (size_t i = 1, j = 0; i != MT_END; j |= i, i <<= 1)
- for (std::list<Module *>::iterator it = Modules.begin(), it_end = Modules.end(); it != it_end; ++it)
+ {
+ for (auto *m : Modules)
{
- Module *m = *it;
if ((m->type & j) == m->type)
modules.push_back(m->name);
}
+ }
- for (unsigned i = 0; i < modules.size(); ++i)
+ for (auto &module : modules)
{
- Module *m = FindModule(modules[i]);
+ Module *m = FindModule(module);
if (m != NULL)
UnloadModule(m, NULL);
}
diff --git a/src/nickalias.cpp b/src/nickalias.cpp
index 68cf165e6..ca311166e 100644
--- a/src/nickalias.cpp
+++ b/src/nickalias.cpp
@@ -20,22 +20,22 @@
Serialize::Checker<nickalias_map> NickAliasList("NickAlias");
-NickAlias::NickAlias(const Anope::string &nickname, NickCore* nickcore) : Serializable("NickAlias")
+NickAlias::NickAlias(const Anope::string &nickname, NickCore *nickcore)
+ : Serializable("NickAlias")
+ , nick(nickname)
+ , nc(nickcore)
{
if (nickname.empty())
throw CoreException("Empty nick passed to NickAlias constructor");
else if (!nickcore)
throw CoreException("Empty nickcore passed to NickAlias constructor");
- this->time_registered = this->last_seen = Anope::CurTime;
- this->nick = nickname;
- this->nc = nickcore;
nickcore->aliases->push_back(this);
+ if (this->nick.equals_ci(nickcore->display))
+ nickcore->na = this;
- size_t old = NickAliasList->size();
- (*NickAliasList)[this->nick] = this;
- if (old == NickAliasList->size())
- Log(LOG_DEBUG) << "Duplicate nick " << nickname << " in nickalias table";
+ if (!NickAliasList->insert_or_assign(this->nick, this).second)
+ Log(LOG_DEBUG) << "Duplicate nick " << this->nick << " in NickAlias table";
if (this->nc->o == NULL)
{
@@ -78,7 +78,7 @@ NickAlias::~NickAlias()
NickAliasList->erase(this->nick);
}
-void NickAlias::SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created)
+void NickAlias::SetVHost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created)
{
this->vhost_ident = ident;
this->vhost_host = host;
@@ -86,7 +86,7 @@ void NickAlias::SetVhost(const Anope::string &ident, const Anope::string &host,
this->vhost_created = created;
}
-void NickAlias::RemoveVhost()
+void NickAlias::RemoveVHost()
{
this->vhost_ident.clear();
this->vhost_host.clear();
@@ -94,27 +94,35 @@ void NickAlias::RemoveVhost()
this->vhost_created = 0;
}
-bool NickAlias::HasVhost() const
+bool NickAlias::HasVHost() const
{
return !this->vhost_host.empty();
}
-const Anope::string &NickAlias::GetVhostIdent() const
+const Anope::string &NickAlias::GetVHostIdent() const
{
return this->vhost_ident;
}
-const Anope::string &NickAlias::GetVhostHost() const
+const Anope::string &NickAlias::GetVHostHost() const
{
return this->vhost_host;
}
-const Anope::string &NickAlias::GetVhostCreator() const
+Anope::string NickAlias::GetVHostMask() const
+{
+ if (this->GetVHostIdent().empty())
+ return this->GetVHostHost();
+
+ return this->GetVHostIdent() + "@" + this->GetVHostHost();
+}
+
+const Anope::string &NickAlias::GetVHostCreator() const
{
return this->vhost_creator;
}
-time_t NickAlias::GetVhostCreated() const
+time_t NickAlias::GetVHostCreated() const
{
return this->vhost_created;
}
@@ -133,27 +141,27 @@ NickAlias *NickAlias::Find(const Anope::string &nick)
void NickAlias::Serialize(Serialize::Data &data) const
{
- data["nick"] << this->nick;
- data["last_quit"] << this->last_quit;
- data["last_realname"] << this->last_realname;
- data["last_usermask"] << this->last_usermask;
- data["last_realhost"] << this->last_realhost;
- data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
- data.SetType("last_seen", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
- data["nc"] << this->nc->display;
-
- if (this->HasVhost())
+ data.Store("nick", this->nick);
+ data.Store("last_quit", this->last_quit);
+ data.Store("last_realname", this->last_realname);
+ data.Store("last_usermask", this->last_usermask);
+ data.Store("last_realhost", this->last_realhost);
+ data.Store("time_registered", this->time_registered);
+ data.Store("last_seen", this->last_seen);
+ data.Store("nc", this->nc->display);
+
+ if (this->HasVHost())
{
- data["vhost_ident"] << this->GetVhostIdent();
- data["vhost_host"] << this->GetVhostHost();
- data["vhost_creator"] << this->GetVhostCreator();
- data["vhost_time"] << this->GetVhostCreated();
+ data.Store("vhost_ident", this->GetVHostIdent());
+ data.Store("vhost_host", this->GetVHostHost());
+ data.Store("vhost_creator", this->GetVHostCreator());
+ data.Store("vhost_time", this->GetVHostCreated());
}
Extensible::ExtensibleSerialize(this, this, data);
}
-Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string snc, snick;
@@ -200,7 +208,7 @@ Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
data["vhost_creator"] >> vhost_creator;
data["vhost_time"] >> vhost_time;
- na->SetVhost(vhost_ident, vhost_host, vhost_creator, vhost_time);
+ na->SetVHost(vhost_ident, vhost_host, vhost_creator, vhost_time);
Extensible::ExtensibleUnserialize(na, na, data);
@@ -210,6 +218,9 @@ Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
data["extensible:NO_EXPIRE"] >> b;
if (b)
na->Extend<bool>("NS_NO_EXPIRE");
+
+ if (na->time_registered < na->nc->time_registered)
+ na->nc->time_registered = na->time_registered;
/* end compat */
return na;
diff --git a/src/nickcore.cpp b/src/nickcore.cpp
index 5bc15cf50..756b40d83 100644
--- a/src/nickcore.cpp
+++ b/src/nickcore.cpp
@@ -16,27 +16,24 @@
#include <climits>
Serialize::Checker<nickcore_map> NickCoreList("NickCore");
-nickcoreid_map NickCoreIdList;
+Serialize::Checker<nickcoreid_map> NickCoreIdList("NickCore");
-NickCore::NickCore(const Anope::string &coredisplay, uint64_t coreid) : Serializable("NickCore"), chanaccess("ChannelInfo"), aliases("NickAlias")
+NickCore::NickCore(const Anope::string &coredisplay, uint64_t coreid)
+ : Serializable("NickCore")
+ , chanaccess("ChannelInfo")
+ , id(coreid)
+ , display(coredisplay)
+ , aliases("NickAlias")
{
if (coredisplay.empty())
throw CoreException("Empty display passed to NickCore constructor");
- this->o = NULL;
- this->channelcount = 0;
- this->lastmail = 0;
+ if (!NickCoreList->insert_or_assign(this->display, this).second)
+ Log(LOG_DEBUG) << "Duplicate account " << this->display << " in NickCore table";
- this->display = coredisplay;
- this->id = coreid;
-
- size_t old = NickCoreList->size();
- (*NickCoreList)[this->display] = this;
- if (old == NickCoreList->size())
- Log(LOG_DEBUG) << "Duplicate account " << coredisplay << " in nickcore table?";
-
- if (this->id)
- NickCoreIdList[this->id] = this;
+ // Upgrading users may not have an account identifier.
+ if (this->id && !NickCoreIdList->insert_or_assign(this->id, this).second)
+ Log(LOG_DEBUG) << "Duplicate account id " << this->id << " in NickCore table";
FOREACH_MOD(OnNickCoreCreate, (this));
}
@@ -59,9 +56,7 @@ NickCore::~NickCore()
NickCoreList->erase(this->display);
if (this->id)
- NickCoreIdList.erase(this->id);
-
- this->ClearAccess();
+ NickCoreIdList->erase(this->id);
if (!this->memos.memos->empty())
{
@@ -73,20 +68,24 @@ NickCore::~NickCore()
void NickCore::Serialize(Serialize::Data &data) const
{
- data["display"] << this->display;
- data["uniqueid"] << this->id;
- data["pass"] << this->pass;
- data["email"] << this->email;
- data["language"] << this->language;
- for (unsigned i = 0; i < this->access.size(); ++i)
- data["access"] << this->access[i] << " ";
- data["memomax"] << this->memos.memomax;
- for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
- data["memoignores"] << this->memos.ignores[i] << " ";
+ data.Store("display", this->display);
+ data.Store("uniqueid", this->id);
+ data.Store("pass", this->pass);
+ data.Store("email", this->email);
+ data.Store("language", this->language);
+ data.Store("lastmail", this->lastmail);
+ data.Store("time_registered", this->time_registered);
+ data.Store("memomax", this->memos.memomax);
+
+ std::ostringstream oss;
+ for (const auto &ignore : this->memos.ignores)
+ oss << ignore << " ";
+ data.Store("memoignores", oss.str());
+
Extensible::ExtensibleSerialize(this, this, data);
}
-Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
{
NickCore *nc;
@@ -104,14 +103,8 @@ Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
data["pass"] >> nc->pass;
data["email"] >> nc->email;
data["language"] >> nc->language;
- {
- Anope::string buf;
- data["access"] >> buf;
- spacesepstream sep(buf);
- nc->access.clear();
- while (sep.GetToken(buf))
- nc->access.push_back(buf);
- }
+ data["lastmail"] >> nc->lastmail;
+ data["time_registered"] >> nc->time_registered;
data["memomax"] >> nc->memos.memomax;
{
Anope::string buf;
@@ -127,10 +120,6 @@ Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
/* compat */
bool b;
b = false;
- data["extensible:SECURE"] >> b;
- if (b)
- nc->Extend<bool>("NS_SECURE");
- b = false;
data["extensible:PRIVATE"] >> b;
if (b)
nc->Extend<bool>("NS_PRIVATE");
@@ -163,7 +152,7 @@ Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
return nc;
}
-void NickCore::SetDisplay(const NickAlias *na)
+void NickCore::SetDisplay(NickAlias *na)
{
if (na->nc != this || na->nick == this->display)
return;
@@ -171,13 +160,14 @@ void NickCore::SetDisplay(const NickAlias *na)
FOREACH_MOD(OnChangeCoreDisplay, (this, na->nick));
/* this affects the serialized aliases */
- for (unsigned i = 0; i < aliases->size(); ++i)
- aliases->at(i)->QueueUpdate();
+ for (auto *alias : *aliases)
+ alias->QueueUpdate();
/* Remove the core from the list */
NickCoreList->erase(this->display);
this->display = na->nick;
+ this->na = na;
(*NickCoreList)[this->display] = this;
}
@@ -187,67 +177,6 @@ bool NickCore::IsServicesOper() const
return this->o != NULL;
}
-void NickCore::AddAccess(const Anope::string &entry)
-{
- this->access.push_back(entry);
- FOREACH_MOD(OnNickAddAccess, (this, entry));
-}
-
-Anope::string NickCore::GetAccess(unsigned entry) const
-{
- if (this->access.empty() || entry >= this->access.size())
- return "";
- return this->access[entry];
-}
-
-unsigned NickCore::GetAccessCount() const
-{
- return this->access.size();
-}
-
-bool NickCore::FindAccess(const Anope::string &entry)
-{
- for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- if (this->access[i] == entry)
- return true;
-
- return false;
-}
-
-void NickCore::EraseAccess(const Anope::string &entry)
-{
- for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- if (this->access[i] == entry)
- {
- FOREACH_MOD(OnNickEraseAccess, (this, entry));
- this->access.erase(this->access.begin() + i);
- break;
- }
-}
-
-void NickCore::ClearAccess()
-{
- FOREACH_MOD(OnNickClearAccess, (this));
- this->access.clear();
-}
-
-bool NickCore::IsOnAccess(const User *u) const
-{
- Anope::string buf = u->GetIdent() + "@" + u->host, buf2, buf3;
- if (!u->vhost.empty())
- buf2 = u->GetIdent() + "@" + u->vhost;
- if (!u->GetCloakedHost().empty())
- buf3 = u->GetIdent() + "@" + u->GetCloakedHost();
-
- for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- {
- Anope::string a = this->GetAccess(i);
- if (Anope::Match(buf, a) || (!buf2.empty() && Anope::Match(buf2, a)) || (!buf3.empty() && Anope::Match(buf3, a)))
- return true;
- }
- return false;
-}
-
void NickCore::AddChannelReference(ChannelInfo *ci)
{
++(*this->chanaccess)[ci];
@@ -255,7 +184,7 @@ void NickCore::AddChannelReference(ChannelInfo *ci)
void NickCore::RemoveChannelReference(ChannelInfo *ci)
{
- int& i = (*this->chanaccess)[ci];
+ int &i = (*this->chanaccess)[ci];
if (--i <= 0)
this->chanaccess->erase(ci);
}
@@ -263,11 +192,11 @@ void NickCore::RemoveChannelReference(ChannelInfo *ci)
void NickCore::GetChannelReferences(std::deque<ChannelInfo *> &queue)
{
queue.clear();
- for (std::map<ChannelInfo *, int>::iterator it = this->chanaccess->begin(), it_end = this->chanaccess->end(); it != it_end; ++it)
- queue.push_back(it->first);
+ for (const auto &[ci, _] : *this->chanaccess)
+ queue.push_back(ci);
}
-NickCore* NickCore::Find(const Anope::string &nick)
+NickCore *NickCore::Find(const Anope::string &nick)
{
nickcore_map::const_iterator it = NickCoreList->find(nick);
if (it != NickCoreList->end())
@@ -284,31 +213,18 @@ uint64_t NickCore::GetId()
if (this->id)
return this->id;
- NickAlias *na = NickAlias::Find(this->display);
- if (!na)
- {
- Log(LOG_DEBUG) << "Unable to find the display NickAlias for NickCore: " << this->display;
- return 0;
- }
-
- Anope::string secretid = this->display + "\0" + stringify(na->time_registered);
-
- // Generate the account id. This should almost always only have one
- // iteration but in the rare case that we generate a duplicate id we try
- // again with a new key.
+ // We base the account identifier on the account display at registration and
+ // when the account was first registered. This should be unique enough that
+ // it never collides. In the extremely rare case that it does generate a
+ // duplicate id we try with a new suffix.
+ uint64_t attempt = 0;
while (!this->id)
{
- // Generate a random key for SipHash.
- char key[16];
- for (size_t i = 0; i < sizeof(key); ++i)
- key[i] = rand() % CHAR_MAX;
-
- uint64_t newid = Anope::SipHash24(secretid.c_str(), secretid.length(), key);
- nickcoreid_map::const_iterator it = NickCoreIdList.find(newid);
- if (it == NickCoreIdList.end())
+ const auto newidstr = this->display + "\0" + Anope::ToString(this->time_registered) + "\0" + Anope::ToString(attempt++);
+ const auto newid = Anope::hash_cs()(newidstr);
+ if (NickCoreIdList->emplace(newid, this).second)
{
this->id = newid;
- NickCoreIdList[this->id] = this;
this->QueueUpdate();
break;
}
diff --git a/src/opertype.cpp b/src/opertype.cpp
index 026e5ae3d..d1a1256b3 100644
--- a/src/opertype.cpp
+++ b/src/opertype.cpp
@@ -13,7 +13,7 @@
std::vector<Oper *> Oper::opers;
-Oper::Oper(const Anope::string &n, OperType *o) : name(n), ot(o), require_oper(true)
+Oper::Oper(const Anope::string &n, OperType *o) : name(n), ot(o)
{
opers.push_back(this);
}
@@ -27,10 +27,8 @@ Oper::~Oper()
Oper *Oper::Find(const Anope::string &name)
{
- for (unsigned i = 0; i < opers.size(); ++i)
+ for (auto *o : opers)
{
- Oper *o = opers[i];
-
if (o->name.equals_ci(name))
return o;
}
@@ -40,10 +38,8 @@ Oper *Oper::Find(const Anope::string &name)
OperType *OperType::Find(const Anope::string &name)
{
- for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i)
+ for (auto *ot : Config->MyOperTypes)
{
- OperType *ot = Config->MyOperTypes[i];
-
if (ot->GetName() == name)
return ot;
}
@@ -57,19 +53,15 @@ OperType::OperType(const Anope::string &nname) : name(nname)
bool OperType::HasCommand(const Anope::string &cmdstr) const
{
- for (std::list<Anope::string>::const_iterator it = this->commands.begin(), it_end = this->commands.end(); it != it_end; ++it)
+ for (const auto &command : this->commands)
{
- const Anope::string &s = *it;
-
- if (!s.find('~') && Anope::Match(cmdstr, s.substr(1)))
+ if (!command.find('~') && Anope::Match(cmdstr, command.substr(1)))
return false;
- else if (Anope::Match(cmdstr, s))
+ else if (Anope::Match(cmdstr, command))
return true;
}
- for (std::set<OperType *>::const_iterator iit = this->inheritances.begin(), iit_end = this->inheritances.end(); iit != iit_end; ++iit)
+ for (auto *ot : this->inheritances)
{
- OperType *ot = *iit;
-
if (ot->HasCommand(cmdstr))
return true;
}
@@ -79,19 +71,15 @@ bool OperType::HasCommand(const Anope::string &cmdstr) const
bool OperType::HasPriv(const Anope::string &privstr) const
{
- for (std::list<Anope::string>::const_iterator it = this->privs.begin(), it_end = this->privs.end(); it != it_end; ++it)
+ for (const auto &priv : this->privs)
{
- const Anope::string &s = *it;
-
- if (!s.find('~') && Anope::Match(privstr, s.substr(1)))
+ if (!priv.find('~') && Anope::Match(privstr, priv.substr(1)))
return false;
- else if (Anope::Match(privstr, s))
+ else if (Anope::Match(privstr, priv))
return true;
}
- for (std::set<OperType *>::const_iterator iit = this->inheritances.begin(), iit_end = this->inheritances.end(); iit != iit_end; ++iit)
+ for (auto *ot : this->inheritances)
{
- OperType *ot = *iit;
-
if (ot->HasPriv(privstr))
return true;
}
@@ -120,28 +108,24 @@ void OperType::Inherits(OperType *ot)
this->inheritances.insert(ot);
}
-const std::list<Anope::string> OperType::GetCommands() const
+std::list<Anope::string> OperType::GetCommands() const
{
std::list<Anope::string> cmd_list = this->commands;
- for (std::set<OperType *>::const_iterator it = this->inheritances.begin(), it_end = this->inheritances.end(); it != it_end; ++it)
+ for (auto *ot : this->inheritances)
{
- OperType *ot = *it;
- std::list<Anope::string> cmds = ot->GetCommands();
- for (std::list<Anope::string>::const_iterator it2 = cmds.begin(), it2_end = cmds.end(); it2 != it2_end; ++it2)
- cmd_list.push_back(*it2);
+ for (const auto &cmd : ot->GetCommands())
+ cmd_list.push_back(cmd);
}
return cmd_list;
}
-const std::list<Anope::string> OperType::GetPrivs() const
+std::list<Anope::string> OperType::GetPrivs() const
{
std::list<Anope::string> priv_list = this->privs;
- for (std::set<OperType *>::const_iterator it = this->inheritances.begin(), it_end = this->inheritances.end(); it != it_end; ++it)
+ for (auto *ot : this->inheritances)
{
- OperType *ot = *it;
- std::list<Anope::string> priv = ot->GetPrivs();
- for (std::list<Anope::string>::const_iterator it2 = priv.begin(), it2_end = priv.end(); it2 != it2_end; ++it2)
- priv_list.push_back(*it2);
+ for (const auto &priv : ot->GetPrivs())
+ priv_list.push_back(priv);
}
return priv_list;
}
diff --git a/src/pipeengine.cpp b/src/pipeengine.cpp
index 4072b6df0..5bca3d1ab 100644
--- a/src/pipeengine.cpp
+++ b/src/pipeengine.cpp
@@ -60,7 +60,7 @@ void Pipe::Write(const char *data, size_t sz)
write(this->write_pipe, data, sz);
}
-int Pipe::Read(char *data, size_t sz)
+ssize_t Pipe::Read(char *data, size_t sz)
{
return read(this->GetFD(), data, sz);
}
diff --git a/src/process.cpp b/src/process.cpp
index fdc854f47..9f2794ad6 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -18,61 +18,81 @@
void Anope::Process(const Anope::string &buffer)
{
- /* If debugging, log the buffer */
- Log(LOG_RAWIO) << "Received: " << buffer;
-
if (buffer.empty())
return;
Anope::map<Anope::string> tags;
Anope::string source, command;
std::vector<Anope::string> params;
-
if (!IRCD->Parse(buffer, tags, source, command, params))
return;
+ Log(LOG_RAWIO) << "Received " << buffer;
if (Anope::ProtocolDebug)
{
if (tags.empty())
- Log() << "No tags";
+ Log() << "\tNo tags";
else
- for (Anope::map<Anope::string>::const_iterator it = tags.begin(); it != tags.end(); ++it)
- Log() << "tags " << it->first << ": " << it->second;
+ {
+ for (const auto &[tname, tvalue] : tags)
+ Log() << "\tTag " << tname << ": " << tvalue;
+ }
- Log() << "Source : " << (source.empty() ? "No source" : source);
- Log() << "Command: " << command;
+ if (source.empty())
+ Log() << "\tNo source";
+ else
+ Log() << "\tSource: " << source;
+
+ Log() << "\tCommand: " << command;
if (params.empty())
- Log() << "No params";
+ Log() << "\tNo params";
else
- for (unsigned i = 0; i < params.size(); ++i)
- Log() << "params " << i << ": " << params[i];
+ {
+ for (size_t i = 0; i < params.size(); ++i)
+ Log() << "\tParam " << i << ": " << params[i];
+ }
}
- static const Anope::string proto_name = ModuleManager::FindFirstOf(PROTOCOL) ? ModuleManager::FindFirstOf(PROTOCOL)->name : "";
-
MessageSource src(source);
-
EventReturn MOD_RESULT;
- FOREACH_RESULT(OnMessage, MOD_RESULT, (src, command, params));
+ FOREACH_RESULT(OnMessage, MOD_RESULT, (src, command, params, tags));
if (MOD_RESULT == EVENT_STOP)
return;
+ ProcessInternal(src, command, params, tags);
+}
+
+void Anope::ProcessInternal(MessageSource &src, const Anope::string &command, const std::vector<Anope::string> &params, const Anope::map<Anope::string> & tags)
+{
+ static const Anope::string proto_name = ModuleManager::FindFirstOf(PROTOCOL) ? ModuleManager::FindFirstOf(PROTOCOL)->name : "";
ServiceReference<IRCDMessage> m("IRCDMessage", proto_name + "/" + command.lower());
if (!m)
{
- Log(LOG_DEBUG) << "unknown message from server (" << buffer << ")";
+ Log(LOG_DEBUG) << "unknown message from server: " << command;
return;
}
- if (m->HasFlag(IRCDMESSAGE_SOFT_LIMIT) ? (params.size() < m->GetParamCount()) : (params.size() != m->GetParamCount()))
+ if (m->HasFlag(IRCDMessage::FLAG_SOFT_LIMIT) ? (params.size() < m->GetParamCount()) : (params.size() != m->GetParamCount()))
Log(LOG_DEBUG) << "invalid parameters for " << command << ": " << params.size() << " != " << m->GetParamCount();
- else if (m->HasFlag(IRCDMESSAGE_REQUIRE_USER) && !src.GetUser())
- Log(LOG_DEBUG) << "unexpected non-user source " << source << " for " << command;
- else if (m->HasFlag(IRCDMESSAGE_REQUIRE_SERVER) && !source.empty() && !src.GetServer())
- Log(LOG_DEBUG) << "unexpected non-server source " << source << " for " << command;
+ else if (m->HasFlag(IRCDMessage::FLAG_REQUIRE_USER) && !src.GetUser())
+ Log(LOG_DEBUG) << "unexpected non-user source " << src.GetSource() << " for " << command;
+ else if (m->HasFlag(IRCDMessage::FLAG_REQUIRE_SERVER) && !src.GetSource().empty() && !src.GetServer())
+ Log(LOG_DEBUG) << "unexpected non-server source " << src.GetSource() << " for " << command;
else
- m->Run(src, params, tags);
+ {
+ try
+ {
+ m->Run(src, params, tags);
+ }
+ catch (const ProtocolException &err)
+ {
+ IRCD->SendError(err.GetReason());
+ Anope::QuitReason = "Protocol error: " + err.GetReason();
+ Anope::Quitting = true;
+ Anope::ReturnValue = EXIT_FAILURE;
+ }
+ }
}
bool IRCDProto::Parse(const Anope::string &buffer, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> &params)
@@ -123,17 +143,76 @@ bool IRCDProto::Parse(const Anope::string &buffer, Anope::map<Anope::string> &ta
return true;
}
-Anope::string IRCDProto::Format(const Anope::string &source, const Anope::string &message)
+bool IRCDProto::Format(Anope::string &message, const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params)
{
- if (!source.empty())
- return ":" + source + " " + message;
- else
- return message;
+ std::stringstream buffer;
+ if (!tags.empty())
+ {
+ char separator = '@';
+ for (const auto &[tname, tvalue] : tags)
+ {
+ if (IRCD->IsTagValid(tname, tvalue))
+ {
+ buffer << separator << tname;
+ if (!tvalue.empty())
+ buffer << '=' << tvalue;
+ separator = ';';
+ }
+ }
+ if (separator != '@')
+ buffer << ' ';
+ }
+
+ if (source.GetServer())
+ {
+ const auto *s = source.GetServer();
+ if (s != Me && !s->IsJuped())
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << s->GetName() << " who is not from me";
+ return false;
+ }
+
+ buffer << ':' << s->GetSID() << ' ';
+ }
+ else if (source.GetUser())
+ {
+ const auto *u = source.GetUser();
+ if (u->server != Me && !u->server->IsJuped())
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << u->nick << " who is not from me";
+ return false;
+ }
+
+ const auto *bi = source.GetBot();
+ if (bi && !bi->introduced)
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << bi->nick << " when not introduced";
+ return false;
+ }
+
+ buffer << ':' << u->GetUID() << ' ';
+ }
+
+ buffer << command;
+ if (!params.empty())
+ {
+ buffer << ' ';
+ for (auto it = params.begin(); it != params.end() - 1; ++it)
+ buffer << *it << ' ';
+
+
+ const auto &last = params.back();
+ if (last.empty() || last[0] == ':' || last.find(' ') != Anope::string::npos)
+ buffer << ':';
+ buffer << last;
+ }
+
+ message = buffer.str();
+ return true;
}
MessageTokenizer::MessageTokenizer(const Anope::string &msg)
: message(msg)
- , position(0)
{
}
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 26a248a95..c66f87653 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -18,17 +18,18 @@
#include "uplink.h"
#include "bots.h"
#include "channels.h"
+#include "numeric.h"
IRCDProto *IRCD = NULL;
-IRCDProto::IRCDProto(Module *creator, const Anope::string &p) : Service(creator, "IRCDProto", creator->name), proto_name(p)
+IRCDProto::IRCDProto(Module *creator, const Anope::string &p)
+ : Service(creator, "IRCDProto", creator->name)
+ , proto_name(p)
+ , MaxChannel(Config->GetBlock("networkinfo")->Get<unsigned>("chanlen", "32"))
+ , MaxHost(Config->GetBlock("networkinfo")->Get<unsigned>("hostlen", "64"))
+ , MaxNick(Config->GetBlock("networkinfo")->Get<unsigned>("nicklen", "31"))
+ , MaxUser(Config->GetBlock("networkinfo")->Get<unsigned>("userlen", "10"))
{
- DefaultPseudoclientModes = "+io";
- CanSVSNick = CanSVSJoin = CanSetVHost = CanSetVIdent = CanSNLine = CanSQLine = CanSQLineChannel
- = CanSZLine = CanSVSHold = CanSVSO = CanCertFP = RequiresID = AmbiguousID = false;
- MaxModes = 3;
- MaxLine = 512;
-
if (IRCD == NULL)
IRCD = this;
}
@@ -39,11 +40,6 @@ IRCDProto::~IRCDProto()
IRCD = NULL;
}
-const Anope::string &IRCDProto::GetProtocolName()
-{
- return this->proto_name;
-}
-
static inline char nextID(int pos, Anope::string &buf)
{
char &c = buf[pos];
@@ -94,179 +90,112 @@ Anope::string IRCDProto::SID_Retrieve()
return current_sid;
}
+time_t IRCDProto::ExtractTimestamp(const Anope::string &str)
+{
+ auto ts = Anope::TryConvert<time_t>(str);
+ if (!ts.has_value())
+ throw ProtocolException("Invalid timestamp: " + str);
+ return ts.value();
+}
+
+void IRCDProto::SendError(const Anope::string &reason)
+{
+ Uplink::Send("ERROR", reason);
+}
+
void IRCDProto::SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason)
{
- UplinkSocket::Message(source) << "KILL " << target << " :" << reason;
+ Uplink::Send(source, "KILL", target, reason);
}
-void IRCDProto::SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf)
+void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "KILL " << user->GetUID() << " :" << buf;
+ Uplink::Send(source, "KILL", user->GetUID(), buf);
}
-void IRCDProto::SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf)
+void IRCDProto::SendModeInternal(const MessageSource &source, Channel *chan, const Anope::string &modes, const std::vector<Anope::string> &values)
{
- UplinkSocket::Message(source) << "MODE " << dest->name << " " << buf;
+ auto params = values;
+ params.insert(params.begin(), { chan->name, modes });
+ Uplink::SendInternal({}, source, "MODE", params);
}
-void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &buf)
+void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &modes, const std::vector<Anope::string> &values)
{
- UplinkSocket::Message(source) << "MODE " << dest->GetUID() << " " << buf;
+ auto params = values;
+ params.insert(params.begin(), { dest->GetUID(), modes });
+ Uplink::SendInternal({}, source, "MODE", params);
}
-void IRCDProto::SendKickInternal(const MessageSource &source, const Channel *c, User *u, const Anope::string &r)
+void IRCDProto::SendKick(const MessageSource &source, const Channel *c, User *u, const Anope::string &r)
{
if (!r.empty())
- UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID() << " :" << r;
+ Uplink::Send(source, "KICK", c->name, u->GetUID(), r);
else
- UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID();
+ Uplink::Send(source, "KICK", c->name, u->GetUID());
}
-void IRCDProto::SendNoticeInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &msg)
+void IRCDProto::SendNotice(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags)
{
- UplinkSocket::Message(source) << "NOTICE " << dest << " :" << msg;
+ Uplink::Send(tags, source, "NOTICE", dest, msg.empty() ? " " : msg);
}
-void IRCDProto::SendPrivmsgInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf)
+void IRCDProto::SendPrivmsg(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags)
{
- UplinkSocket::Message(source) << "PRIVMSG " << dest << " :" << buf;
+ Uplink::Send(tags, source, "PRIVMSG", dest, msg.empty() ? " " : msg);
}
-void IRCDProto::SendQuitInternal(User *u, const Anope::string &buf)
+void IRCDProto::SendTagmsg(const MessageSource &source, const Anope::string &dest, const Anope::map<Anope::string> &tags)
{
- if (!buf.empty())
- UplinkSocket::Message(u) << "QUIT :" << buf;
- else
- UplinkSocket::Message(u) << "QUIT";
+ if (CanTagMessage)
+ Uplink::Send(tags, source, "TAGMSG", dest);
}
-void IRCDProto::SendPartInternal(User *u, const Channel *chan, const Anope::string &buf)
+void IRCDProto::SendQuit(User *u, const Anope::string &buf)
{
if (!buf.empty())
- UplinkSocket::Message(u) << "PART " << chan->name << " :" << buf;
+ Uplink::Send(u, "QUIT", buf);
else
- UplinkSocket::Message(u) << "PART " << chan->name;
+ Uplink::Send(u, "QUIT");
}
-void IRCDProto::SendGlobopsInternal(const MessageSource &source, const Anope::string &buf)
+void IRCDProto::SendPart(User *u, const Channel *chan, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "GLOBOPS :" << buf;
+ if (!buf.empty())
+ Uplink::Send(u, "PART", chan->name, buf);
+ else
+ Uplink::Send(u, "PART", chan->name);
}
-void IRCDProto::SendCTCPInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf)
+void IRCDProto::SendGlobops(const MessageSource &source, const Anope::string &message)
{
- Anope::string s = Anope::NormalizeBuffer(buf);
- this->SendNoticeInternal(source, dest, "\1" + s + "\1");
+ Uplink::Send(source, "GLOBOPS", message);
}
-void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf)
+void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, const std::vector<Anope::string> &params)
{
- Anope::string n = stringify(numeric);
+ Anope::string n = Anope::ToString(numeric);
if (numeric < 10)
n = "0" + n;
if (numeric < 100)
n = "0" + n;
- UplinkSocket::Message(Me) << n << " " << dest << " " << buf;
-}
-
-void IRCDProto::SendTopic(const MessageSource &source, Channel *c)
-{
- UplinkSocket::Message(source) << "TOPIC " << c->name << " :" << c->topic;
-}
-void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...)
-{
- if (!user || !fmt)
- return;
-
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendSVSKillInternal(source, user, buf);
-}
-
-void IRCDProto::SendMode(const MessageSource &source, const Channel *dest, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendModeInternal(source, dest, buf);
-}
-
-void IRCDProto::SendMode(const MessageSource &source, User *u, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendModeInternal(source, u, buf);
-}
-
-void IRCDProto::SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt, ...)
-{
- if (!chan || !user)
- return;
-
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendKickInternal(source, chan, user, buf);
-}
-
-void IRCDProto::SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendNoticeInternal(source, dest, buf);
-}
-
-void IRCDProto::SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- Anope::string actionbuf = Anope::string("\1ACTION ") + buf + '\1';
- SendPrivmsgInternal(source, dest, actionbuf);
+ auto newparams = params;
+ newparams.insert(newparams.begin(), dest);
+ Uplink::SendInternal({}, Me, n, newparams);
}
-void IRCDProto::SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendPrivmsgInternal(source, dest, buf);
-}
-
-void IRCDProto::SendQuit(User *u, const char *fmt, ...)
+void IRCDProto::SendTopic(const MessageSource &source, Channel *c)
{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendQuitInternal(u, buf);
+ Uplink::Send(source, "TOPIC", c->name, c->topic);
}
void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who)
{
if (servname.empty())
- UplinkSocket::Message(Me) << "PING " << who;
+ Uplink::Send("PING", who);
else
- UplinkSocket::Message(Me) << "PING " << servname << " " << who;
+ Uplink::Send("PING", servname, who);
}
/**
@@ -278,74 +207,29 @@ void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who
void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who)
{
if (servname.empty())
- UplinkSocket::Message(Me) << "PONG " << who;
+ Uplink::Send("PONG", who);
else
- UplinkSocket::Message(Me) << "PONG " << servname << " " << who;
+ Uplink::Send("PONG", servname, who);
}
void IRCDProto::SendInvite(const MessageSource &source, const Channel *c, User *u)
{
- UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name;
-}
-
-void IRCDProto::SendPart(User *user, const Channel *chan, const char *fmt, ...)
-{
- if (fmt)
- {
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendPartInternal(user, chan, buf);
- }
- else
- SendPartInternal(user, chan, "");
-}
-
-void IRCDProto::SendGlobops(const MessageSource &source, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendGlobopsInternal(source, buf);
+ Uplink::Send(source, "INVITE", u->GetUID(), c->name);
}
void IRCDProto::SendSquit(Server *s, const Anope::string &message)
{
- UplinkSocket::Message() << "SQUIT " << s->GetSID() << " :" << message;
+ Uplink::Send("SQUIT", s->GetSID(), message);
}
void IRCDProto::SendNickChange(User *u, const Anope::string &newnick)
{
- UplinkSocket::Message(u) << "NICK " << newnick << " " << Anope::CurTime;
+ Uplink::Send(u, "NICK", newnick, Anope::CurTime);
}
void IRCDProto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when)
{
- UplinkSocket::Message() << "SVSNICK " << u->GetUID() << " " << newnick << " " << when;
-}
-
-void IRCDProto::SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendCTCPInternal(source, dest, buf);
-}
-
-void IRCDProto::SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, fmt, args);
- va_end(args);
- SendNumericInternal(numeric, dest, buf);
+ Uplink::Send("SVSNICK", u->GetUID(), newnick, when);
}
bool IRCDProto::IsNickValid(const Anope::string &nick)
@@ -364,10 +248,10 @@ bool IRCDProto::IsNickValid(const Anope::string &nick)
Anope::string special = "[]\\`_^{|}";
for (unsigned i = 0; i < nick.length(); ++i)
- if (!(nick[i] >= 'A' && nick[i] <= 'Z') && !(nick[i] >= 'a' && nick[i] <= 'z')
+ if ((nick[i] < 'A' || nick[i] > 'Z') && (nick[i] < 'a' || nick[i] > 'z')
&& special.find(nick[i]) == Anope::string::npos
&& (Config && Config->NickChars.find(nick[i]) == Anope::string::npos)
- && (!i || (!(nick[i] >= '0' && nick[i] <= '9') && nick[i] != '-')))
+ && (!i || ((nick[i] < '0' || nick[i] > '9') && nick[i] != '-')))
return false;
return true;
@@ -375,7 +259,7 @@ bool IRCDProto::IsNickValid(const Anope::string &nick)
bool IRCDProto::IsChannelValid(const Anope::string &chan)
{
- if (chan.empty() || chan[0] != '#' || chan.length() > Config->GetBlock("networkinfo")->Get<unsigned>("chanlen"))
+ if (chan.empty() || chan[0] != '#' || chan.length() > IRCD->MaxChannel)
return false;
if (chan.find_first_of(" ,") != Anope::string::npos)
@@ -386,13 +270,11 @@ bool IRCDProto::IsChannelValid(const Anope::string &chan)
bool IRCDProto::IsIdentValid(const Anope::string &ident)
{
- if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
+ if (ident.empty() || ident.length() > IRCD->MaxUser)
return false;
- for (unsigned i = 0; i < ident.length(); ++i)
+ for (auto c : ident)
{
- const char &c = ident[i];
-
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
continue;
@@ -404,7 +286,7 @@ bool IRCDProto::IsIdentValid(const Anope::string &ident)
bool IRCDProto::IsHostValid(const Anope::string &host)
{
- if (host.empty() || host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
+ if (host.empty() || host.length() > IRCD->MaxHost)
return false;
const Anope::string &vhostdisablebe = Config->GetBlock("networkinfo")->Get<const Anope::string>("disallow_start_or_end"),
@@ -416,11 +298,11 @@ bool IRCDProto::IsHostValid(const Anope::string &host)
return false;
int dots = 0;
- for (unsigned i = 0; i < host.length(); ++i)
+ for (auto chr : host)
{
- if (host[i] == '.')
+ if (chr == '.')
++dots;
- if (vhostchars.find_first_of(host[i]) == Anope::string::npos)
+ if (vhostchars.find_first_of(chr) == Anope::string::npos)
return false;
}
@@ -429,18 +311,13 @@ bool IRCDProto::IsHostValid(const Anope::string &host)
void IRCDProto::SendOper(User *u)
{
- SendNumericInternal(381, u->GetUID(), ":You are now an IRC operator (set by services)");
+ SendNumeric(RPL_YOUREOPER, u->GetUID(), "You are now an IRC operator (set by services)");
u->SetMode(NULL, "OPER");
}
-unsigned IRCDProto::GetMaxListFor(Channel *c)
-{
- return c->HasMode("LBAN") ? 0 : Config->GetBlock("networkinfo")->Get<int>("modelistsize");
-}
-
-unsigned IRCDProto::GetMaxListFor(Channel *c, ChannelMode *cm)
+size_t IRCDProto::GetMaxListFor(Channel *c, ChannelMode *cm)
{
- return GetMaxListFor(c);
+ return c->HasMode("LBAN") ? 0 : Config->GetBlock("networkinfo")->Get<size_t>("modelistsize", "100");
}
Anope::string IRCDProto::NormalizeMask(const Anope::string &mask)
@@ -450,7 +327,21 @@ Anope::string IRCDProto::NormalizeMask(const Anope::string &mask)
return Entry("", mask).GetNUHMask();
}
-MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s(NULL)
+void IRCDProto::SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg)
+{
+ IRCD->SendNotice(bi, target->GetUID(), Anope::printf("[%s] %s", context->name.c_str(), msg.c_str()), {
+ { "+draft/channel-context", context->name },
+ });
+}
+
+void IRCDProto::SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg)
+{
+ IRCD->SendPrivmsg(bi, target->GetUID(), Anope::printf("[%s] %s", context->name.c_str(), msg.c_str()), {
+ { "+draft/channel-context", context->name },
+ });
+}
+
+MessageSource::MessageSource(const Anope::string &src) : source(src)
{
/* no source for incoming message is our uplink */
if (src.empty())
@@ -461,11 +352,11 @@ MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s
this->u = User::Find(src);
}
-MessageSource::MessageSource(User *_u) : source(_u ? _u->nick : ""), u(_u), s(NULL)
+MessageSource::MessageSource(User *_u) : source(_u ? _u->nick : ""), u(_u)
{
}
-MessageSource::MessageSource(Server *_s) : source(_s ? _s->GetName() : ""), u(NULL), s(_s)
+MessageSource::MessageSource(Server *_s) : source(_s ? _s->GetName() : ""), s(_s)
{
}
@@ -499,18 +390,9 @@ Server *MessageSource::GetServer() const
return this->s;
}
-IRCDMessage::IRCDMessage(Module *o, const Anope::string &n, unsigned p) : Service(o, "IRCDMessage", o->name + "/" + n.lower()), name(n), param_count(p)
-{
-}
-
-unsigned IRCDMessage::GetParamCount() const
+IRCDMessage::IRCDMessage(Module *o, const Anope::string &n, size_t pc)
+ : Service(o, "IRCDMessage", o->name + "/" + n.lower())
+ , name(n)
+ , param_count(pc)
{
- return this->param_count;
}
-
-void IRCDMessage::Run(MessageSource &source, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags)
-{
- // Most IRCds don't support message tags yet so use the tagless variant.
- Run(source, params);
-}
-
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index 6dbd9df55..9e450830b 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -40,18 +40,18 @@ AutoKick::~AutoKick()
void AutoKick::Serialize(Serialize::Data &data) const
{
- data["ci"] << this->ci->name;
+ data.Store("ci", this->ci->name);
if (this->nc)
- data["nc"] << this->nc->display;
+ data.Store("nc", this->nc->display);
else
- data["mask"] << this->mask;
- data["reason"] << this->reason;
- data["creator"] << this->creator;
- data.SetType("addtime", Serialize::Data::DT_INT); data["addtime"] << this->addtime;
- data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
+ data.Store("mask", this->mask);
+ data.Store("reason", this->reason);
+ data.Store("creator", this->creator);
+ data.Store("addtime", this->addtime);
+ data.Store("last_used", this->last_used);
}
-Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sci, snc;
@@ -180,35 +180,38 @@ ChannelInfo::~ChannelInfo()
void ChannelInfo::Serialize(Serialize::Data &data) const
{
- data["name"] << this->name;
+ data.Store("name", this->name);
if (this->founder)
- data["founder"] << this->founder->display;
+ data.Store("founder", this->founder->display);
if (this->successor)
- data["successor"] << this->successor->display;
- data["description"] << this->desc;
- data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
- data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
- data["last_topic"] << this->last_topic;
- data["last_topic_setter"] << this->last_topic_setter;
- data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time;
- data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype;
+ data.Store("successor", this->successor->display);
+ data.Store("description", this->desc);
+ data.Store("time_registered", this->time_registered);
+ data.Store("last_used", this->last_used);
+ data.Store("last_topic", this->last_topic);
+ data.Store("last_topic_setter", this->last_topic_setter);
+ data.Store("last_topic_time", this->last_topic_time);
+ data.Store("bantype", this->bantype);
{
Anope::string levels_buffer;
- for (Anope::map<int16_t>::const_iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it)
- levels_buffer += it->first + " " + stringify(it->second) + " ";
- data["levels"] << levels_buffer;
+ for (const auto &[name, level] : this->levels)
+ levels_buffer += name + " " + Anope::ToString(level) + " ";
+ data.Store("levels", levels_buffer);
}
if (this->bi)
- data["bi"] << this->bi->nick;
- data.SetType("banexpire", Serialize::Data::DT_INT); data["banexpire"] << this->banexpire;
- data["memomax"] << this->memos.memomax;
- for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
- data["memoignores"] << this->memos.ignores[i] << " ";
+ data.Store("bi", this->bi->nick);
+ data.Store("banexpire", this->banexpire);
+ data.Store("memomax", this->memos.memomax);
+
+ std::ostringstream oss;
+ for (const auto &ignore : this->memos.ignores)
+ oss << ignore << " ";
+ data.Store("memoignores", oss.str());
Extensible::ExtensibleSerialize(this, this, data);
}
-Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string sname, sfounder, ssuccessor, slevels, sbi;
@@ -238,11 +241,14 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
std::vector<Anope::string> v;
spacesepstream(slevels).GetTokens(v);
for (unsigned i = 0; i + 1 < v.size(); i += 2)
- try
- {
- ci->levels[v[i]] = convertTo<int16_t>(v[i + 1]);
- }
- catch (const ConvertException &) { }
+ {
+ // Begin 2.0 database compatibility.
+ if (v[i] == "FANTASIA")
+ v[i] = "FANTASY";
+ // End 2.0 database compatibility.
+ if (auto level = Anope::TryConvert<int16_t>(v[i + 1]))
+ ci->levels[v[i]] = level.value();
+ }
}
BotInfo *bi = BotInfo::Find(sbi, true);
if (*ci->bi != bi)
@@ -268,10 +274,6 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
/* compat */
bool b;
b = false;
- data["extensible:SECURE"] >> b;
- if (b)
- ci->Extend<bool>("CS_SECURE");
- b = false;
data["extensible:PRIVATE"] >> b;
if (b)
ci->Extend<bool>("CS_PRIVATE");
@@ -423,18 +425,10 @@ AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed)
if (u == NULL)
return group;
- const NickCore *nc = u->Account();
- if (nc == NULL && !this->HasExt("NS_SECURE") && u->IsRecognized())
- {
- const NickAlias *na = NickAlias::Find(u->nick);
- if (na != NULL)
- nc = na->nc;
- }
-
group.super_admin = u->super_admin;
group.founder = IsFounder(u, this);
group.ci = this;
- group.nc = nc;
+ group.nc = u->Account();
FindMatches(group, this, u, u->Account());
@@ -443,12 +437,10 @@ AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed)
if (updateLastUsed)
this->last_used = Anope::CurTime;
- for (unsigned i = 0; i < group.paths.size(); ++i)
+ for (auto &p : group.paths)
{
- ChanAccess::Path &p = group.paths[i];
-
- for (unsigned int j = 0; j < p.size(); ++j)
- p[j]->last_seen = Anope::CurTime;
+ for (auto *ca : p)
+ ca->last_seen = Anope::CurTime;
}
}
@@ -527,7 +519,7 @@ void ChannelInfo::ClearAccess()
AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t, time_t lu)
{
- AutoKick *autokick = new AutoKick();
+ auto *autokick = new AutoKick();
autokick->ci = this;
autokick->nc = akicknc;
autokick->reason = reason;
@@ -544,7 +536,7 @@ AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, co
AutoKick *ChannelInfo::AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t, time_t lu)
{
- AutoKick *autokick = new AutoKick();
+ auto *autokick = new AutoKick();
autokick->ci = this;
autokick->mask = mask;
autokick->nc = NULL;
@@ -646,7 +638,7 @@ Anope::string ChannelInfo::GetIdealBan(User *u) const
}
}
-ChannelInfo* ChannelInfo::Find(const Anope::string &name)
+ChannelInfo *ChannelInfo::Find(const Anope::string &name)
{
registered_channel_map::const_iterator it = RegisteredChannelList->find(name);
if (it != RegisteredChannelList->end())
@@ -688,6 +680,6 @@ void ChannelInfo::RemoveChannelReference(const Anope::string &what)
void ChannelInfo::GetChannelReferences(std::deque<Anope::string> &chans)
{
chans.clear();
- for (Anope::map<int>::iterator it = references.begin(); it != references.end(); ++it)
- chans.push_back(it->first);
+ for (auto &[chan, _] : references)
+ chans.push_back(chan);
}
diff --git a/src/serialize.cpp b/src/serialize.cpp
index faf8d0e4a..4da86a0ad 100644
--- a/src/serialize.cpp
+++ b/src/serialize.cpp
@@ -34,14 +34,13 @@ void Serialize::RegisterTypes()
void Serialize::CheckTypes()
{
- for (std::map<Anope::string, Serialize::Type *>::const_iterator it = Serialize::Type::GetTypes().begin(), it_end = Serialize::Type::GetTypes().end(); it != it_end; ++it)
+ for (const auto &[_, t] : Serialize::Type::GetTypes())
{
- Serialize::Type *t = it->second;
t->Check();
}
}
-Serializable::Serializable(const Anope::string &serialize_type) : last_commit(0), last_commit_time(0), id(0), redis_ignore(0)
+Serializable::Serializable(const Anope::string &serialize_type)
{
if (SerializableItems == NULL)
SerializableItems = new std::list<Serializable *>();
@@ -55,7 +54,7 @@ Serializable::Serializable(const Anope::string &serialize_type) : last_commit(0)
FOREACH_MOD(OnSerializableConstruct, (this));
}
-Serializable::Serializable(const Serializable &other) : last_commit(0), last_commit_time(0), id(0), redis_ignore(0)
+Serializable::Serializable(const Serializable &other)
{
SerializableItems->push_back(this);
this->s_iter = SerializableItems->end();
@@ -112,7 +111,7 @@ const std::list<Serializable *> &Serializable::GetItems()
return *SerializableItems;
}
-Type::Type(const Anope::string &n, unserialize_func f, Module *o) : name(n), unserialize(f), owner(o), timestamp(0)
+Type::Type(const Anope::string &n, unserialize_func f, Module *o) : name(n), unserialize(f), owner(o)
{
TypeOrder.push_back(this->name);
Types[this->name] = this;
@@ -124,13 +123,13 @@ Type::~Type()
{
/* null the type of existing serializable objects of this type */
if (Serializable::SerializableItems != NULL)
- for (std::list<Serializable *>::iterator it = Serializable::SerializableItems->begin(); it != Serializable::SerializableItems->end(); ++it)
+ {
+ for (auto *s : *Serializable::SerializableItems)
{
- Serializable *s = *it;
-
if (s->s_type == this)
s->s_type = NULL;
}
+ }
std::vector<Anope::string>::iterator it = std::find(TypeOrder.begin(), TypeOrder.end(), this->name);
if (it != TypeOrder.end())
diff --git a/src/servers.cpp b/src/servers.cpp
index a945d1642..9f98aeb07 100644
--- a/src/servers.cpp
+++ b/src/servers.cpp
@@ -27,7 +27,7 @@ Anope::map<Server *> Servers::ByID;
std::set<Anope::string> Servers::Capab;
-Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Anope::string &desc, const Anope::string &ssid, bool jupe) : name(sname), hops(shops), description(desc), sid(ssid), uplink(up), users(0)
+Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Anope::string &desc, const Anope::string &ssid, bool jupe) : name(sname), hops(shops), description(desc), sid(ssid), uplink(up)
{
syncing = true;
juped = jupe;
@@ -48,27 +48,32 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
if (Me == this->uplink && !juped)
{
/* Now do mode related stuff as we know what modes exist .. */
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ for (auto &[_, bi] : *BotListByNick)
{
- BotInfo *bi = it->second;
- Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : IRCD->DefaultPseudoclientModes;
+ spacesepstream modesep(bi->botmodes.empty() ? IRCD->DefaultPseudoclientModes : "+" + bi->botmodes);
- bi->SetModesInternal(bi, modes.c_str());
- for (unsigned i = 0; i < bi->botchannels.size(); ++i)
+ Anope::string modechars;
+ modesep.GetToken(modechars);
+
+ std::vector<Anope::string> modeparams;
+ modesep.GetTokens(modeparams);
+
+ bi->SetModesInternal(bi, modechars, modeparams);
+ for (const auto &botchannel : bi->botchannels)
{
- size_t h = bi->botchannels[i].find('#');
+ size_t h = botchannel.find('#');
if (h == Anope::string::npos)
continue;
- Anope::string chname = bi->botchannels[i].substr(h);
+ Anope::string chname = botchannel.substr(h);
Channel *c = Channel::Find(chname);
if (c && c->FindUser(bi))
{
- Anope::string want_modes = bi->botchannels[i].substr(0, h);
- for (unsigned j = 0; j < want_modes.length(); ++j)
+ Anope::string want_modes = botchannel.substr(0, h);
+ for (char want_mode : want_modes)
{
- ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]);
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(want_mode);
if (cm == NULL)
- cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
+ cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_mode));
if (cm && cm->type == MODE_STATUS)
{
MessageSource ms = bi;
@@ -81,19 +86,15 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
IRCD->SendBOB();
- for (unsigned i = 0; i < Me->GetLinks().size(); ++i)
+ for (auto *link : Me->GetLinks())
{
- Server *s = Me->GetLinks()[i];
-
- if (s->juped)
- IRCD->SendServer(s);
+ if (link->juped)
+ IRCD->SendServer(link);
}
/* We make the bots go online */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u] : UserListByNick)
{
- User *u = it->second;
-
BotInfo *bi = BotInfo::Find(u->GetUID());
if (bi)
{
@@ -106,22 +107,22 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
bi->introduced = true;
}
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
+ for (const auto &[_, c] : ChannelList)
{
- Channel *c = it->second;
-
if (c->users.empty())
IRCD->SendChannel(c);
else
- for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit)
- IRCD->SendJoin(cit->second->user, c, &cit->second->status);
+ {
+ for (const auto &[_, uc] : c->users)
+ IRCD->SendJoin(uc->user, c, &uc->status);
+ }
- for (Channel::ModeList::const_iterator it2 = c->GetModes().begin(); it2 != c->GetModes().end(); ++it2)
+ for (const auto &[mode, value] : c->GetModes())
{
- ChannelMode *cm = ModeManager::FindChannelModeByName(it2->first);
+ ChannelMode *cm = ModeManager::FindChannelModeByName(mode);
if (!cm || cm->type != MODE_LIST)
continue;
- ModeManager::StackerAdd(c->WhoSends(), c, cm, true, it2->second);
+ ModeManager::StackerAdd(c->WhoSends(), c, cm, true, value);
}
if (!c->topic.empty() && !c->topic_setter.empty())
@@ -139,10 +140,8 @@ Server::~Server()
{
Log(this, "quit") << "quit from " << (this->uplink ? this->uplink->GetName() : "no uplink") << " for " << this->quit_reason;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u] : UserListByNick)
{
- User *u = it->second;
-
if (u->server == this)
{
u->Quit(this->quit_reason);
@@ -259,8 +258,8 @@ void Server::Sync(bool sync_links)
if (sync_links && !this->links.empty())
{
- for (unsigned i = 0, j = this->links.size(); i < j; ++i)
- this->links[i]->Sync(true);
+ for (auto *link : this->links)
+ link->Sync(true);
}
bool me = this->GetUplink() && this->GetUplink() == Me;
@@ -309,9 +308,11 @@ bool Server::IsULined() const
if (this == Me)
return true;
- for (unsigned i = 0; i < Config->Ulines.size(); ++i)
- if (Config->Ulines[i].equals_ci(this->GetName()))
+ for (const auto &uline : Config->Ulines)
+ {
+ if (uline.equals_ci(this->GetName()))
return true;
+ }
return false;
}
@@ -327,7 +328,7 @@ bool Server::IsQuitting() const
void Server::Notice(BotInfo *source, const Anope::string &message)
{
- if (Config->UsePrivmsg && Config->DefPrivmsg)
+ if (Config->DefPrivmsg)
IRCD->SendGlobalPrivmsg(source, this, message);
else
IRCD->SendGlobalNotice(source, this, message);
@@ -351,10 +352,12 @@ Server *Server::Find(const Anope::string &name, bool name_only)
return NULL;
}
-Server* Servers::GetUplink()
+Server *Servers::GetUplink()
{
- for (unsigned i = 0; Me && i < Me->GetLinks().size(); ++i)
- if (!Me->GetLinks()[i]->IsJuped())
- return Me->GetLinks()[i];
+ for (auto *link : Me->GetLinks())
+ {
+ if (!link->IsJuped())
+ return link;
+ }
return NULL;
}
diff --git a/src/siphash.cpp b/src/siphash.cpp
deleted file mode 100644
index 78571c390..000000000
--- a/src/siphash.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/* SipHash-2-4 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.
- */
-
-/* <MIT License>
- Copyright (c) 2013 Marek Majkowski <marek@popcount.org>
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- </MIT License>
- Original location:
- https://github.com/majek/csiphash/
- Solution inspired by code from:
- Samuel Neves (supercop/crypto_auth/siphash24/little)
- djb (supercop/crypto_auth/siphash24/little2)
- Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c)
-*/
-
-#include "services.h"
-#include "anope.h"
-
-// WARNING: This ifdef maze could be a lot simpler but unfortunately
-// that will cause find_includes to be unable to parse it.
-
-#ifdef __APPLE__
-# include <libkern/OSByteOrder.h>
-# define _le64toh(x) OSSwapLittleToHostInt64(x)
-#endif
-
-#ifdef __FreeBSD__
-# include <sys/endian.h>
-# define _le64toh(x) le64toh(x)
-#endif
-
-#ifdef __linux__
-# include <endian.h>
-#endif
-
-#ifdef __NetBSD__
-# include <sys/endian.h>
-# define _le64toh(x) le64toh(x)
-#endif
-
-#ifdef __OpenBSD__
-# include <sys/endian.h>
-# define _le64toh(x) le64toh(x)
-#endif
-
-// Windows is always little endian.
-#ifdef _WIN32
-# define _le64toh(x) ((uint64_t)(x))
-#endif
-
-// Attempt to work on unenumerated platforms.
-#if defined(le64toh) && !defined(_le64toh)
-# define _le64toh le64toh
-#endif
-
-// We can't do anything about this.
-#ifndef _le64toh
-# error Please define _le64toh for your platform!
-#endif
-
-#define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
-
-#define HALF_ROUND(a,b,c,d,s,t) \
- a += b; c += d; \
- b = ROTATE(b, s) ^ a; \
- d = ROTATE(d, t) ^ c; \
- a = ROTATE(a, 32);
-
-#define DOUBLE_ROUND(v0,v1,v2,v3) \
- HALF_ROUND(v0,v1,v2,v3,13,16); \
- HALF_ROUND(v2,v1,v0,v3,17,21); \
- HALF_ROUND(v0,v1,v2,v3,13,16); \
- HALF_ROUND(v2,v1,v0,v3,17,21);
-
-
-uint64_t Anope::SipHash24(const void *src, unsigned long src_sz, const char key[16])
-{
- const uint64_t *_key = (uint64_t *)key;
- uint64_t k0 = _le64toh(_key[0]);
- uint64_t k1 = _le64toh(_key[1]);
- uint64_t b = (uint64_t)src_sz << 56;
- const uint64_t *in = (uint64_t*)src;
-
- uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;
- uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;
- uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;
- uint64_t v3 = k1 ^ 0x7465646279746573ULL;
-
- while (src_sz >= 8)
- {
- uint64_t mi = _le64toh(*in);
- in += 1; src_sz -= 8;
- v3 ^= mi;
- DOUBLE_ROUND(v0,v1,v2,v3);
- v0 ^= mi;
- }
-
- uint64_t t = 0; uint8_t *pt = (uint8_t *)&t; uint8_t *m = (uint8_t *)in;
- switch (src_sz)
- {
- case 7: pt[6] = m[6];
- case 6: pt[5] = m[5];
- case 5: pt[4] = m[4];
- case 4: *((uint32_t*)&pt[0]) = *((uint32_t*)&m[0]); break;
- case 3: pt[2] = m[2];
- case 2: pt[1] = m[1];
- case 1: pt[0] = m[0];
- }
- b |= _le64toh(t);
-
- v3 ^= b;
- DOUBLE_ROUND(v0,v1,v2,v3);
- v0 ^= b; v2 ^= 0xff;
- DOUBLE_ROUND(v0,v1,v2,v3);
- DOUBLE_ROUND(v0,v1,v2,v3);
- return (v0 ^ v1) ^ (v2 ^ v3);
-}
diff --git a/src/socket_clients.cpp b/src/socket_clients.cpp
index 5316be226..1df727efc 100644
--- a/src/socket_clients.cpp
+++ b/src/socket_clients.cpp
@@ -14,7 +14,7 @@
#include "logger.h"
#include "sockets.h"
-#include <errno.h>
+#include <cerrno>
void ConnectionSocket::Connect(const Anope::string &TargetHost, int Port)
{
diff --git a/src/socket_transport.cpp b/src/socket_transport.cpp
index 287e60450..621b2bce4 100644
--- a/src/socket_transport.cpp
+++ b/src/socket_transport.cpp
@@ -13,14 +13,6 @@
#include "sockets.h"
#include "socketengine.h"
-BufferedSocket::BufferedSocket()
-{
-}
-
-BufferedSocket::~BufferedSocket()
-{
-}
-
bool BufferedSocket::ProcessRead()
{
char tbuffer[NET_BUFSIZE];
@@ -55,7 +47,7 @@ bool BufferedSocket::ProcessWrite()
return true;
}
-const Anope::string BufferedSocket::GetLine()
+Anope::string BufferedSocket::GetLine()
{
size_t s = this->read_buffer.find('\n');
if (s == Anope::string::npos)
@@ -115,14 +107,6 @@ BinarySocket::DataBlock::~DataBlock()
delete [] this->orig;
}
-BinarySocket::BinarySocket()
-{
-}
-
-BinarySocket::~BinarySocket()
-{
-}
-
bool BinarySocket::ProcessRead()
{
char tbuffer[NET_BUFSIZE];
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/epoll.cpp
index 93f558299..f5cd7c090 100644
--- a/src/socketengines/socketengine_epoll.cpp
+++ b/src/socketengines/epoll.cpp
@@ -15,9 +15,9 @@
#include "socketengine.h"
#include "config.h"
+#include <cerrno>
#include <sys/epoll.h>
#include <ulimit.h>
-#include <errno.h>
static int EngineHandle;
static std::vector<epoll_event> events;
@@ -53,7 +53,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
memset(&ev, 0, sizeof(ev));
- ev.events = (s->flags[SF_READABLE] ? EPOLLIN : 0) | (s->flags[SF_WRITABLE] ? EPOLLOUT : 0);
+ ev.events = (s->flags[SF_READABLE] ? EPOLLIN : 0u) | (s->flags[SF_WRITABLE] ? EPOLLOUT : 0u);
ev.data.fd = s->GetFD();
int mod;
@@ -67,7 +67,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
return;
if (epoll_ctl(EngineHandle, mod, ev.data.fd, &ev) == -1)
- throw SocketException("Unable to epoll_ctl() fd " + stringify(ev.data.fd) + " to epoll: " + Anope::LastError());
+ throw SocketException("Unable to epoll_ctl() fd " + Anope::ToString(ev.data.fd) + " to epoll: " + Anope::LastError());
}
void SocketEngine::Process()
@@ -76,7 +76,7 @@ void SocketEngine::Process()
events.resize(events.size() * 2);
int total = epoll_wait(EngineHandle, &events.front(), events.size(), Config->ReadTimeout * 1000);
- Anope::CurTime = time(NULL);
+ Anope::UpdateTime();
/* EINTR can be given if the read timeout expires */
if (total == -1)
diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/kqueue.cpp
index 9b3943d72..271f5a49d 100644
--- a/src/socketengines/socketengine_kqueue.cpp
+++ b/src/socketengines/kqueue.cpp
@@ -77,7 +77,7 @@ void SocketEngine::Process()
static timespec kq_timespec = { Config->ReadTimeout, 0 };
int total = kevent(kq_fd, &change_events.front(), change_count, &event_events.front(), event_events.size(), &kq_timespec);
change_count = 0;
- Anope::CurTime = time(NULL);
+ Anope::UpdateTime();
/* EINTR can be given if the read timeout expires */
if (total == -1)
diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/poll.cpp
index 0c728a055..05b1f3ef5 100644
--- a/src/socketengines/socketengine_poll.cpp
+++ b/src/socketengines/poll.cpp
@@ -71,7 +71,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
{
std::map<int, unsigned>::iterator pos = socket_positions.find(s->GetFD());
if (pos == socket_positions.end())
- throw SocketException("Unable to remove fd " + stringify(s->GetFD()) + " from poll, it does not exist?");
+ throw SocketException("Unable to remove fd " + Anope::ToString(s->GetFD()) + " from poll, it does not exist?");
if (pos->second != events.size() - 1)
{
@@ -90,7 +90,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
{
std::map<int, unsigned>::iterator pos = socket_positions.find(s->GetFD());
if (pos == socket_positions.end())
- throw SocketException("Unable to modify fd " + stringify(s->GetFD()) + " in poll, it does not exist?");
+ throw SocketException("Unable to modify fd " + Anope::ToString(s->GetFD()) + " in poll, it does not exist?");
pollfd &ev = events[pos->second];
ev.events = (s->flags[SF_READABLE] ? POLLIN : 0) | (s->flags[SF_WRITABLE] ? POLLOUT : 0);
@@ -100,7 +100,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
void SocketEngine::Process()
{
int total = poll(&events.front(), events.size(), Config->ReadTimeout * 1000);
- Anope::CurTime = time(NULL);
+ Anope::UpdateTime();
/* EINTR can be given if the read timeout expires */
if (total < 0)
diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/select.cpp
index c29d971c5..5b895cd9d 100644
--- a/src/socketengines/socketengine_select.cpp
+++ b/src/socketengines/select.cpp
@@ -16,10 +16,7 @@
#include "logger.h"
#include "config.h"
-#ifdef _AIX
-# undef FD_ZERO
-# define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
-#endif /* _AIX */
+#include <thread>
static int MaxFD;
static unsigned FDCount;
@@ -97,13 +94,13 @@ void SocketEngine::Process()
*/
if (FDCount == 0)
{
- sleep(tval.tv_sec);
+ std::this_thread::sleep_for(std::chrono::seconds(tval.tv_sec));
return;
}
#endif
int sresult = select(MaxFD + 1, &rfdset, &wfdset, &efdset, &tval);
- Anope::CurTime = time(NULL);
+ Anope::UpdateTime();
if (sresult == -1)
{
diff --git a/src/sockets.cpp b/src/sockets.cpp
index 2227ba607..908bf34f6 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -16,7 +16,7 @@
#ifndef _WIN32
#include <arpa/inet.h>
-#include <errno.h>
+#include <cerrno>
#include <fcntl.h>
#endif
@@ -52,6 +52,8 @@ size_t sockaddrs::size() const
return sizeof(sa4);
case AF_INET6:
return sizeof(sa6);
+ case AF_UNIX:
+ return sizeof(saun);
default:
break;
}
@@ -67,6 +69,8 @@ int sockaddrs::port() const
return ntohs(sa4.sin_port);
case AF_INET6:
return ntohs(sa6.sin6_port);
+ case AF_UNIX:
+ return 0;
default:
break;
}
@@ -76,18 +80,51 @@ int sockaddrs::port() const
Anope::string sockaddrs::addr() const
{
- char address[INET6_ADDRSTRLEN];
-
switch (sa.sa_family)
{
case AF_INET:
- if (inet_ntop(AF_INET, &sa4.sin_addr, address, sizeof(address)))
- return address;
+ {
+ char v4address[INET_ADDRSTRLEN];
+ if (inet_ntop(AF_INET, &sa4.sin_addr, v4address, sizeof(v4address)))
+ return v4address;
break;
+ }
case AF_INET6:
- if (inet_ntop(AF_INET6, &sa6.sin6_addr, address, sizeof(address)))
- return address;
+ {
+ char v6address[INET6_ADDRSTRLEN];
+ if (inet_ntop(AF_INET6, &sa6.sin6_addr, v6address, sizeof(v6address)))
+ return v6address;
break;
+ }
+ case AF_UNIX:
+ return saun.sun_path;
+ default:
+ break;
+ }
+
+ return "";
+}
+
+Anope::string sockaddrs::str() const
+{
+ switch (sa.sa_family)
+ {
+ case AF_INET:
+ {
+ char v4address[INET_ADDRSTRLEN];
+ if (!inet_ntop(AF_INET, &sa4.sin_addr, v4address, sizeof(v4address)))
+ strcpy(v4address, "0.0.0.0");
+ return Anope::printf("%s:%u", v4address, sa4.sin_port);
+ }
+ case AF_INET6:
+ {
+ char v6address[INET6_ADDRSTRLEN];
+ if (!inet_ntop(AF_INET6, &sa6.sin6_addr, v6address, sizeof(v6address)))
+ strcpy(v6address, "0:0:0:0:0:0:0:0");
+ return Anope::printf("[%s]:%u", v6address, sa6.sin6_port);
+ }
+ case AF_UNIX:
+ return saun.sun_path;
default:
break;
}
@@ -187,6 +224,15 @@ void sockaddrs::pton(int type, const Anope::string &address, int pport)
}
break;
}
+ case AF_UNIX:
+ {
+ if (address.length() < sizeof(saun.sun_path))
+ {
+ saun.sun_family = AF_UNIX;
+ memcpy(&saun.sun_path, address.c_str(), address.length() + 1);
+ }
+ break;
+ }
default:
break;
}
@@ -236,13 +282,7 @@ cidr::cidr(const Anope::string &ip)
Anope::string cidr_range = ip.substr(sl + 1);
this->cidr_ip = real_ip;
- this->cidr_len = ipv6 ? 128 : 32;
- try
- {
- if (cidr_range.is_pos_number_only())
- this->cidr_len = convertTo<unsigned int>(cidr_range);
- }
- catch (const ConvertException &) { }
+ this->cidr_len = Anope::Convert<unsigned int>(cidr_range, ipv6 ? 128 : 32);
this->addr.pton(ipv6 ? AF_INET6 : AF_INET, real_ip);
}
}
@@ -306,7 +346,7 @@ bool cidr::match(const sockaddrs &other)
byte = len % 8;
if (byte)
{
- uint8_t m = ~0 << (8 - byte);
+ uint8_t m = ~0u << (8 - byte);
return (*ip & m) == (*their_ip & m);
}
@@ -386,23 +426,23 @@ size_t cidr::hash::operator()(const cidr &s) const
}
}
-int SocketIO::Recv(Socket *s, char *buf, size_t sz)
+ssize_t SocketIO::Recv(Socket *s, char *buf, size_t sz)
{
- int i = recv(s->GetFD(), buf, sz, 0);
+ ssize_t i = recv(s->GetFD(), buf, sz, 0);
if (i > 0)
TotalRead += i;
return i;
}
-int SocketIO::Send(Socket *s, const char *buf, size_t sz)
+ssize_t SocketIO::Send(Socket *s, const char *buf, size_t sz)
{
- int i = send(s->GetFD(), buf, sz, 0);
+ ssize_t i = send(s->GetFD(), buf, sz, 0);
if (i > 0)
TotalWritten += i;
return i;
}
-int SocketIO::Send(Socket *s, const Anope::string &buf)
+ssize_t SocketIO::Send(Socket *s, const Anope::string &buf)
{
return this->Send(s, buf.c_str(), buf.length());
}
@@ -432,7 +472,7 @@ SocketFlag SocketIO::FinishAccept(ClientSocket *cs)
void SocketIO::Bind(Socket *s, const Anope::string &ip, int port)
{
- s->bindaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, ip, port);
+ s->bindaddr.pton(s->GetFamily(), ip, port);
if (bind(s->GetFD(), &s->bindaddr.sa, s->bindaddr.size()) == -1)
throw SocketException("Unable to bind to address: " + Anope::LastError());
}
@@ -440,7 +480,7 @@ void SocketIO::Bind(Socket *s, const Anope::string &ip, int port)
void SocketIO::Connect(ConnectionSocket *s, const Anope::string &target, int port)
{
s->flags[SF_CONNECTING] = s->flags[SF_CONNECTED] = false;
- s->conaddr.pton(s->IsIPv6() ? AF_INET6 : AF_INET, target, port);
+ s->conaddr.pton(s->GetFamily(), target, port);
int c = connect(s->GetFD(), &s->conaddr.sa, s->conaddr.size());
if (c == -1)
{
@@ -488,12 +528,12 @@ Socket::Socket()
throw CoreException("Socket::Socket() ?");
}
-Socket::Socket(int s, bool i, int type)
+Socket::Socket(int s, int f, int type)
{
this->io = &NormalSocketIO;
- this->ipv6 = i;
+ this->family = f;
if (s == -1)
- this->sock = socket(this->ipv6 ? AF_INET6 : AF_INET, type, 0);
+ this->sock = socket(this->family, type, 0);
else
this->sock = s;
this->SetBlocking(false);
@@ -510,14 +550,14 @@ Socket::~Socket()
SocketEngine::Sockets.erase(this->sock);
}
-int Socket::GetFD() const
+int Socket::GetFamily() const
{
- return sock;
+ return family;
}
-bool Socket::IsIPv6() const
+int Socket::GetFD() const
{
- return ipv6;
+ return sock;
}
bool Socket::SetBlocking(bool state)
@@ -567,10 +607,6 @@ ListenSocket::ListenSocket(const Anope::string &bindip, int port, bool i)
throw SocketException("Unable to listen: " + Anope::LastError());
}
-ListenSocket::~ListenSocket()
-{
-}
-
bool ListenSocket::ProcessRead()
{
try
diff --git a/src/threadengine.cpp b/src/threadengine.cpp
index b26463f53..729f3e5ec 100644
--- a/src/threadengine.cpp
+++ b/src/threadengine.cpp
@@ -13,49 +13,21 @@
#include "threadengine.h"
#include "anope.h"
-#ifndef _WIN32
-#include <pthread.h>
-#endif
-
-static inline pthread_attr_t *get_engine_attr()
-{
- /* Threadengine attributes used by this thread engine */
- static pthread_attr_t attr;
- static bool inited = false;
-
- if (inited == false)
- {
- if (pthread_attr_init(&attr))
- throw CoreException("Error calling pthread_attr_init");
- if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE))
- throw CoreException("Unable to mark threads as joinable");
- inited = true;
- }
-
- return &attr;
-}
+#include <stdexcept>
static void *entry_point(void *parameter)
{
Thread *thread = static_cast<Thread *>(parameter);
thread->Run();
thread->SetExitState();
- pthread_exit(0);
return NULL;
}
-Thread::Thread() : exit(false)
-{
-}
-
-Thread::~Thread()
-{
-}
-
void Thread::Join()
{
this->SetExitState();
- pthread_join(handle, NULL);
+ if (this->handle)
+ this->handle->join();
}
void Thread::SetExitState()
@@ -67,15 +39,19 @@ void Thread::SetExitState()
void Thread::Exit()
{
this->SetExitState();
- pthread_exit(0);
}
void Thread::Start()
{
- if (pthread_create(&this->handle, get_engine_attr(), entry_point, this))
+ try
+ {
+ if (!this->handle)
+ this->handle = std::make_unique<std::thread>(entry_point, this);
+ }
+ catch (const std::system_error &err)
{
this->flags[SF_DEAD] = true;
- throw CoreException("Unable to create thread: " + Anope::LastError());
+ throw CoreException("Unable to create thread: " + Anope::string(err.what()));
}
}
@@ -89,48 +65,3 @@ void Thread::OnNotify()
this->Join();
this->flags[SF_DEAD] = true;
}
-
-Mutex::Mutex()
-{
- pthread_mutex_init(&mutex, NULL);
-}
-
-Mutex::~Mutex()
-{
- pthread_mutex_destroy(&mutex);
-}
-
-void Mutex::Lock()
-{
- pthread_mutex_lock(&mutex);
-}
-
-void Mutex::Unlock()
-{
- pthread_mutex_unlock(&mutex);
-}
-
-bool Mutex::TryLock()
-{
- return pthread_mutex_trylock(&mutex) == 0;
-}
-
-Condition::Condition() : Mutex()
-{
- pthread_cond_init(&cond, NULL);
-}
-
-Condition::~Condition()
-{
- pthread_cond_destroy(&cond);
-}
-
-void Condition::Wakeup()
-{
- pthread_cond_signal(&cond);
-}
-
-void Condition::Wait()
-{
- pthread_cond_wait(&cond, &mutex);
-}
diff --git a/src/timers.cpp b/src/timers.cpp
index db20dcd8b..e280434ab 100644
--- a/src/timers.cpp
+++ b/src/timers.cpp
@@ -11,26 +11,23 @@
std::multimap<time_t, Timer *> TimerManager::Timers;
-Timer::Timer(long time_from_now, time_t now, bool repeating)
+Timer::Timer(time_t time_from_now, bool repeating)
+ : trigger(Anope::CurTime + std::abs(time_from_now))
+ , secs(time_from_now)
+ , repeat(repeating)
{
- owner = NULL;
- trigger = now + time_from_now;
- secs = time_from_now;
- repeat = repeating;
- settime = now;
-
- TimerManager::AddTimer(this);
+ if (time_from_now)
+ TimerManager::AddTimer(this);
}
-Timer::Timer(Module *creator, long time_from_now, time_t now, bool repeating)
+Timer::Timer(Module *creator, time_t time_from_now, bool repeating)
+ : owner(creator)
+ , trigger(Anope::CurTime + std::abs(time_from_now))
+ , secs(time_from_now)
+ , repeat(repeating)
{
- owner = creator;
- trigger = now + time_from_now;
- secs = time_from_now;
- repeat = repeating;
- settime = now;
-
- TimerManager::AddTimer(this);
+ if (time_from_now)
+ TimerManager::AddTimer(this);
}
Timer::~Timer()
@@ -55,11 +52,6 @@ bool Timer::GetRepeat() const
return repeat;
}
-time_t Timer::GetSetTime() const
-{
- return settime;
-}
-
void Timer::SetSecs(time_t t)
{
TimerManager::DelTimer(this);
@@ -80,7 +72,7 @@ Module *Timer::GetOwner() const
void TimerManager::AddTimer(Timer *t)
{
- Timers.insert(std::make_pair(t->GetTimer(), t));
+ Timers.emplace(t->GetTimer(), t);
}
void TimerManager::DelTimer(Timer *t)
@@ -96,20 +88,20 @@ void TimerManager::DelTimer(Timer *t)
}
}
-void TimerManager::TickTimers(time_t ctime)
+void TimerManager::TickTimers()
{
while (!Timers.empty())
{
std::multimap<time_t, Timer *>::iterator it = Timers.begin();
Timer *t = it->second;
- if (t->GetTimer() > ctime)
+ if (t->GetTimer() > Anope::CurTime)
break;
- t->Tick(ctime);
+ t->Tick();
if (t->GetRepeat())
- t->SetTimer(ctime + t->GetSecs());
+ t->SetTimer(Anope::CurTime + t->GetSecs());
else
delete t;
}
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 3e00b981d..c029f9177 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -1,6 +1,6 @@
# Find all the *.cpp files within the current source directory, and sort the list
file(GLOB TOOLS_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
-sort_list(TOOLS_SRCS)
+list(SORT TOOLS_SRCS)
# Set all the files to use C++ as well as set their compile flags
set_source_files_properties(${TOOLS_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
@@ -9,34 +9,34 @@ set_source_files_properties(${TOOLS_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS
foreach(SRC ${TOOLS_SRCS})
# Convert the source file extension to have no extension
string(REGEX REPLACE "\\.cpp$" "" EXE ${SRC})
- # Calculate the header file dependencies for the given source file
- calculate_depends(${SRC})
# Only continue if this file isn't skipped
if(NOT SKIP)
# Generate the executable and set its linker flags, also set it to depend on the main Anope executable to be built beforehand
add_executable(${EXE} ${SRC})
set_target_properties(${EXE} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}")
add_dependencies(${EXE} ${PROGRAM_NAME})
- # Only for Windows, set anopesmtp to require the wsock32 library
- if(WIN32 AND ${EXE} STREQUAL anopesmtp)
- target_link_libraries(${EXE} wsock32)
- endif(WIN32 AND ${EXE} STREQUAL anopesmtp)
- if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" AND ${EXE} STREQUAL anopesmtp)
- target_link_libraries(${EXE} socket nsl)
- endif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" AND ${EXE} STREQUAL anopesmtp)
# Set the executable to be installed to the bin directory under the main directory
install(TARGETS ${EXE}
DESTINATION ${BIN_DIR}
+ RUNTIME
)
# Add the executable to the list of files for CPack to ignore
- get_target_property(EXE_BINARY ${EXE} LOCATION)
+ set(EXE_BINARY "$<TARGET_FILE:${EXE}>")
get_filename_component(EXE_BINARY ${EXE_BINARY} NAME)
add_to_cpack_ignored_files("${EXE_BINARY}$" TRUE)
- endif(NOT SKIP)
-endforeach(SRC)
+ endif()
+endforeach()
# If not on Windows, generate anoperc and install it along with mydbgen
if(NOT WIN32)
+ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+ configure_file(${Anope_SOURCE_DIR}/src/tools/anope.service.in ${Anope_BINARY_DIR}/src/tools/anope.service)
+ install(
+ PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/anope.service
+ DESTINATION ${BIN_DIR}
+ )
+ endif()
+
configure_file(${Anope_SOURCE_DIR}/src/tools/anoperc.in ${Anope_BINARY_DIR}/src/tools/anoperc)
install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/anoperc
DESTINATION ${BIN_DIR}
@@ -44,9 +44,9 @@ if(NOT WIN32)
install (PROGRAMS geoipupdate.sh
DESTINATION ${BIN_DIR}
)
-endif(NOT WIN32)
+endif()
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the tools directory
if(NOT WIN32 AND RUNGROUP)
install(CODE "execute_process(COMMAND ${CHMOD} 2770 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin\")")
-endif(NOT WIN32 AND RUNGROUP)
+endif()
diff --git a/src/tools/anope.service.in b/src/tools/anope.service.in
new file mode 100644
index 000000000..6fe8f652d
--- /dev/null
+++ b/src/tools/anope.service.in
@@ -0,0 +1,17 @@
+[Unit]
+After=network.target
+Description=Anope IRC Services
+Documentation=https://wiki.anope.org/
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+ExecReload=/bin/kill -HUP $MAINPID
+ExecStart=@BIN_DIR@/@PROGRAM_NAME@ --nofork
+Restart=on-failure
+Type=simple
+WorkingDirectory=@CMAKE_INSTALL_PREFIX@
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/src/tools/anoperc.in b/src/tools/anoperc.in
index 0d3b2d07d..24fc77e83 100644
--- a/src/tools/anoperc.in
+++ b/src/tools/anoperc.in
@@ -1,8 +1,8 @@
#!/bin/sh
#
-# Configuration script for Services
+# Configuration script for Anope
#
-# (C) 2003-2024 Anope Team
+# (C) 2003-2025 Anope Team
# Contact us at team@anope.org
#
# Please read COPYING and README for further details.
@@ -14,8 +14,8 @@
-ANOPEPID="@INSTDIR@/data/services.pid"
-ANOPROG="@INSTDIR@/bin/services"
+ANOPEPID="@INSTDIR@/data/anope.pid"
+ANOPROG="@INSTDIR@/bin/anope"
LOG="@INSTDIR@/logs/"
ARCVERSION="2"
diff --git a/src/tools/anopesmtp.cpp b/src/tools/anopesmtp.cpp
deleted file mode 100644
index d1c3f7b64..000000000
--- a/src/tools/anopesmtp.cpp
+++ /dev/null
@@ -1,535 +0,0 @@
-/* smtp stuff handler for win32.
- *
- * (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.
- *
- * Written by Dominick Meglio <codemastr@unrealircd.com>
- * *nix port by Trystan Scott Lee <trystan@nomadirc.net>
- */
-
-#include "sysconf.h"
-
-/* Some Linux boxes (or maybe glibc includes) require this for the
- * prototype of strsignal(). */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <string>
-#include <vector>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <cerrno>
-#include <iostream>
-#include <fstream>
-
-#ifndef _WIN32
-# include <unistd.h>
-# include <netdb.h>
-# include <netinet/in.h>
-# include <sys/socket.h>
-# include <arpa/inet.h>
-# include <sys/time.h>
-#else
-# include <winsock.h>
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#include <sys/types.h>
-
-#ifdef _AIX
-extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, size_t);
-# if 0 /* These break on some AIX boxes (4.3.1 reported). */
-extern int socket(int, int, int);
-extern int connect(int, struct sockaddr *, int);
-# endif
-#endif /* _AIX */
-
-/* Some SUN fixs */
-#ifdef __sun
-/* Solaris specific code, types that do not exist in Solaris'
- * * sys/types.h
- * **/
-# ifndef INADDR_NONE
-# define INADDR_NONE (-1)
-# endif
-#endif
-
-#ifdef _WIN32
-typedef SOCKET ano_socket_t;
-#define ano_sockclose(fd) closesocket(fd)
-#define ano_sockread(fd, buf, len) recv(fd, buf, len, 0)
-#define ano_sockwrite(fd, buf, len) send(fd, buf, len, 0)
-#else
-typedef int ano_socket_t;
-#define ano_sockclose(fd) close(fd)
-#define ano_sockread(fd, buf, len) read(fd, buf, len)
-#define ano_sockwrite(fd, buf, len) write(fd, buf, len)
-#define SOCKET_ERROR -1
-#endif
-
-/* Data structures */
-struct smtp_message
-{
- std::vector<std::string> smtp_headers;
- std::vector<std::string> smtp_body;
- std::string from;
- std::string to;
- ano_socket_t sock;
-};
-
-int smtp_debug = 0;
-
-struct smtp_message smail;
-
-static std::string get_logname(struct tm *tm = NULL)
-{
- char timestamp[32];
-
- if (!tm)
- {
- time_t t = time(NULL);
- tm = localtime(&t);
- }
-
- strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
- std::string name = std::string("anopesmtp.") + timestamp;
- return name;
-}
-
-/* TimeStamp for Email Header */
-static std::string GetTimeStamp()
-{
- char tbuf[256];
- time_t t = time(NULL);
- struct tm *tm = gmtime(&t);
-
- strftime(tbuf, sizeof(tbuf) - 1, "%a, %d %b %Y %H:%M:%S +0000", tm);
-
- return tbuf;
-}
-
-/* Log stuff to the log file with a datestamp. Note that errno is
- * preserved by this routine and log_perror().
- */
-
-void alog(const char *fmt, ...)
-{
- if (!smtp_debug || !fmt)
- return;
-
- std::fstream file;
- file.open(get_logname().c_str(), std::ios_base::out | std::ios_base::app);
-
- if (!file.is_open())
- return;
-
- va_list args;
- va_start(args, fmt);
-
- time_t t = time(NULL);
- struct tm *tm = localtime(&t);
-
- char buf[256];
- strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", tm);
- file << buf;
- vsnprintf(buf, sizeof(buf), fmt, args);
- file << buf << std::endl;
- va_end(args);
- va_end(args);
-
- file.close();
-}
-
-/* Remove a trailing \r\n */
-std::string strip(const std::string &buf)
-{
- std::string newbuf = buf;
- char c = newbuf[newbuf.size() - 1];
- while (c == '\n' || c == '\r')
- {
- newbuf.erase(newbuf.end() - 1);
- c = newbuf[newbuf.size() - 1];
- }
- return newbuf;
-}
-
-/* Is the buffer a header? */
-bool smtp_is_header(const std::string &buf)
-{
- size_t tmp = buf.find(' ');
-
- if (tmp == std::string::npos)
- return false;
-
- if (tmp > 0 && buf[tmp - 1] == ':')
- return true;
- return false;
-}
-
-/* Parse a header into a name and value */
-void smtp_parse_header(const std::string &buf, std::string &header, std::string &value)
-{
- std::string newbuf = strip(buf);
-
- size_t space = newbuf.find(' ');
- if (space != std::string::npos)
- {
- header = newbuf.substr(0, space);
- value = newbuf.substr(space + 1);
- }
- else
- {
- header = newbuf;
- value = "";
- }
-}
-
-/* Have we reached the end of input? */
-bool smtp_is_end(const std::string &buf)
-{
- if (buf[0] == '.')
- if (buf[1] == '\r' || buf[1] == '\n')
- return true;
-
- return false;
-}
-
-/* Set who the email is to */
-void smtp_set_to(const std::string &to)
-{
- smail.to = to;
- size_t c = smail.to.rfind('<');
- if (c != std::string::npos && c + 1 < smail.to.size())
- {
- smail.to = smail.to.substr(c + 1);
- smail.to.erase(smail.to.end() - 1);
- }
-}
-
-/* Establish a connection to the SMTP server */
-int smtp_connect(const char *host, unsigned short port)
-{
- struct sockaddr_in addr;
-
- if ((smail.sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
- return 0;
-
- if ((addr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
- {
- struct hostent *hent;
- if (!(hent = gethostbyname(host)))
- return 0;
- memcpy(&addr.sin_addr, hent->h_addr, hent->h_length);
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port ? port : 25);
- if (connect(smail.sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(struct sockaddr_in)) == SOCKET_ERROR)
- {
- ano_sockclose(smail.sock);
- return 0;
- }
-
- return 1;
-}
-
-/* Send a line of text */
-int smtp_send(const char *text)
-{
- int result = ano_sockwrite(smail.sock, text, strlen(text));
-
- alog("SMTP: sent %s",text);
-
- if (result == SOCKET_ERROR)
- ano_sockclose(smail.sock);
-
- return result;
-}
-
-/* Read a line of text */
-int smtp_read(char *buf, int len)
-{
- int result;
-
- memset(buf, 0, len);
- result = ano_sockread(smail.sock, buf, len);
-
- if (result == SOCKET_ERROR)
- ano_sockclose(smail.sock);
-
- return result;
-}
-
-/* Retrieve a response code */
-int smtp_get_code(const std::string &text)
-{
- size_t tmp = text.find(' ');
-
- if (tmp == std::string::npos)
- return 0;
-
- return atol(text.substr(0, tmp).c_str());
-}
-
-/* Send the email */
-int smtp_send_email()
-{
- char buf[1024];
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- int code = smtp_get_code(buf);
- if (code != 220)
- {
- alog("SMTP: error expected code 220 got %d",code);
- return 0;
- }
-
- if (!smtp_send("HELO anope\r\n"))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 250)
- {
- alog("SMTP: error expected code 250 got %d",code);
- return 0;
- }
-
- strcpy(buf, "MAIL FROM: <");
- strcat(buf, smail.from.c_str());
- strcat(buf, ">\r\n");
-
- if (!smtp_send(buf))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 250)
- return 0;
-
- strcpy(buf, "RCPT TO: <");
- strcat(buf, smail.to.c_str());
- strcat(buf, ">\r\n");
-
- if (!smtp_send(buf))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (smtp_get_code(buf) != 250)
- {
- alog("SMTP: error expected code 250 got %d",code);
- return 0;
- }
-
- if (!smtp_send("DATA\r\n"))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 354)
- {
- alog("SMTP: error expected code 354 got %d",code);
- return 0;
- }
-
- for (std::vector<std::string>::const_iterator it = smail.smtp_headers.begin(), it_end = smail.smtp_headers.end(); it != it_end; ++it)
- if (!smtp_send(it->c_str()))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- if (!smtp_send("\r\n"))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- bool skip_done = false;
- for (std::vector<std::string>::const_iterator it = smail.smtp_body.begin(), it_end = smail.smtp_body.end(); it != it_end; ++it)
- if (skip_done)
- {
- if (!smtp_send(it->c_str()))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
- }
- else
- skip_done = true;
-
- if (!smtp_send("\r\n.\r\n"))
- {
- alog("SMTP: error writing to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 250)
- {
- alog("SMTP: error expected code 250 got %d",code);
- return 0;
- }
-
- return 1;
-}
-
-void smtp_disconnect()
-{
- char buf[1024];
-
- if (!smtp_send("QUIT\r\n"))
- {
- alog("SMTP: error writing to socket");
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- }
-
- int code = smtp_get_code(buf);
- if (code != 221)
- {
- alog("SMTP: error expected code 221 got %d",code);
- }
-
- ano_sockclose(smail.sock);
-}
-
-int main(int argc, char *argv[])
-{
- /* Win32 stuff */
-#ifdef _WIN32
- WSADATA wsa;
-#endif
-
- if (argc == 1)
- return 0;
-
- if (argc == 3 && !strcmp(argv[2], "--debug"))
- smtp_debug = 1;
-
- char *server = strtok(argv[1], ":"), *aport;
- short port;
- if ((aport = strtok(NULL, "")))
- port = atoi(aport);
- else
- port = 25;
-
- if (!server)
- {
- alog("No Server");
- /* Bad, bad, bad. This was a return from main with no value! -GD */
- return 0;
- }
- else
- alog("SMTP: server %s port %d",server,port);
-
- /* The WSAStartup function initiates use of WS2_32.DLL by a process. */
- /* guessing we can skip it under *nix */
-#ifdef _WIN32
- if (WSAStartup(MAKEWORD(1, 1), &wsa))
- return 0;
-#endif
-
- char buf[8192];
- bool headers_done = false;
- /* Read the message and parse it */
- while (fgets(buf, 8192, stdin))
- {
- if (smtp_is_header(buf) && !headers_done)
- {
- smail.smtp_headers.push_back(strip(buf) + "\r\n");
- std::string header, value;
- smtp_parse_header(buf, header, value);
- if (header == "From:")
- {
- alog("SMTP: from: %s", value.c_str());
- smail.from = value;
- }
- else if (header == "To:")
- {
- alog("SMTP: to: %s", value.c_str());
- smtp_set_to(value);
- }
- else if (smtp_is_end(buf))
- break;
- else
- {
- smail.smtp_headers.push_back("Date: " + GetTimeStamp() + "\r\n");
- headers_done = true;
- smail.smtp_body.push_back(strip(buf) + "\r\n");
- }
- }
- else
- smail.smtp_body.push_back(strip(buf) + "\r\n");
- }
-
- if (!smtp_connect(server, port))
- {
- alog("SMTP: failed to connect to %s:%d", server, port);
- return 0;
- }
- if (!smtp_send_email())
- {
- alog("SMTP: error during sending of mail");
- return 0;
- }
- smtp_disconnect();
-
- return 1;
-}
diff --git a/src/uplink.cpp b/src/uplink.cpp
index f1b524dd1..c032d6118 100644
--- a/src/uplink.cpp
+++ b/src/uplink.cpp
@@ -17,12 +17,16 @@
UplinkSocket *UplinkSock = NULL;
-class ReconnectTimer : public Timer
+class ReconnectTimer final
+ : public Timer
{
- public:
- ReconnectTimer(int wait) : Timer(wait) { }
+public:
+ ReconnectTimer(time_t wait)
+ : Timer(wait)
+ {
+ }
- void Tick(time_t)
+ void Tick() override
{
try
{
@@ -43,7 +47,7 @@ void Uplink::Connect()
return;
}
- if (static_cast<unsigned>(++Anope::CurrentUplink) >= Config->Uplinks.size())
+ if (++Anope::CurrentUplink >= Config->Uplinks.size())
Anope::CurrentUplink = 0;
Configuration::Uplink &u = Config->Uplinks[Anope::CurrentUplink];
@@ -52,12 +56,54 @@ void Uplink::Connect()
if (!Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost").empty())
UplinkSock->Bind(Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost"));
FOREACH_MOD(OnPreServerConnect, ());
- Anope::string ip = Anope::Resolve(u.host, u.ipv6 ? AF_INET6 : AF_INET);
+ Anope::string ip = Anope::Resolve(u.host, u.protocol);
Log(LOG_TERMINAL) << "Attempting to connect to uplink #" << (Anope::CurrentUplink + 1) << " " << u.host << " (" << ip << '/' << u.port << ") with protocol " << IRCD->GetProtocolName();
UplinkSock->Connect(ip, u.port);
}
-UplinkSocket::UplinkSocket() : Socket(-1, Config->Uplinks[Anope::CurrentUplink].ipv6), ConnectionSocket(), BufferedSocket()
+void Uplink::SendInternal(const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params)
+{
+ if (!UplinkSock)
+ {
+ Log(LOG_DEBUG) << "Attempted to send \"" << command << "\" from " << source.GetName() << " with a null uplink socket";
+ return;
+ }
+
+ Anope::string message;
+ if (!IRCD->Format(message, tags, source, command, params))
+ return;
+
+ UplinkSock->Write(message);
+
+ Log(LOG_RAWIO) << "Sent " << message;
+ if (Anope::ProtocolDebug)
+ {
+ if (tags.empty())
+ Log() << "\tNo tags";
+ else
+ {
+ for (const auto &[tname, tvalue] : tags)
+ Log() << "\tTag " << tname << ": " << tvalue;
+ }
+
+ if (source.GetSource().empty())
+ Log() << "\tNo source";
+ else
+ Log() << "\tSource: " << source.GetSource();
+
+ Log() << "\tCommand: " << command;
+
+ if (params.empty())
+ Log() << "\tNo params";
+ else
+ {
+ for (size_t i = 0; i < params.size(); ++i)
+ Log() << "\tParam " << i << ": " << params[i];
+ }
+ }
+}
+
+UplinkSocket::UplinkSocket() : Socket(-1, Config->Uplinks[Anope::CurrentUplink].protocol), ConnectionSocket(), BufferedSocket()
{
error = false;
UplinkSock = this;
@@ -79,15 +125,13 @@ UplinkSocket::~UplinkSocket()
{
FOREACH_MOD(OnServerDisconnect, ());
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ for (const auto &[_, u] : UserListByNick)
{
- User *u = it->second;
-
if (u->server == Me)
{
/* Don't use quitmsg here, it may contain information you don't want people to see */
IRCD->SendQuit(u, "Shutting down");
- BotInfo* bi = BotInfo::Find(u->GetUID());
+ BotInfo *bi = BotInfo::Find(u->GetUID());
if (bi != NULL)
bi->introduced = false;
}
@@ -130,7 +174,7 @@ UplinkSocket::~UplinkSocket()
bool UplinkSocket::ProcessRead()
{
bool b = BufferedSocket::ProcessRead();
- for (Anope::string buf; (buf = this->GetLine()).empty() == false;)
+ for (Anope::string buf; !(buf = this->GetLine()).empty();)
{
Anope::Process(buf);
User::QuitUsers();
@@ -152,61 +196,3 @@ void UplinkSocket::OnError(const Anope::string &err)
Log(LOG_TERMINAL) << what << " uplink #" << (Anope::CurrentUplink + 1) << " (" << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port << ")" << (!err.empty() ? (": " + err) : "");
error |= !err.empty();
}
-
-UplinkSocket::Message::Message() : source(Me)
-{
-}
-
-UplinkSocket::Message::Message(const MessageSource &src) : source(src)
-{
-}
-
-UplinkSocket::Message::~Message()
-{
- Anope::string message_source;
-
- if (this->source.GetServer() != NULL)
- {
- const Server *s = this->source.GetServer();
-
- if (s != Me && !s->IsJuped())
- {
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << s->GetName() << " who is not from me?";
- return;
- }
-
- message_source = s->GetSID();
- }
- else if (this->source.GetUser() != NULL)
- {
- const User *u = this->source.GetUser();
-
- if (u->server != Me && !u->server->IsJuped())
- {
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << u->nick << " who is not from me?";
- return;
- }
-
- const BotInfo *bi = this->source.GetBot();
- if (bi != NULL && bi->introduced == false)
- {
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced";
- return;
- }
-
- message_source = u->GetUID();
- }
-
- if (!UplinkSock)
- {
- if (!message_source.empty())
- Log(LOG_DEBUG) << "Attempted to send \"" << message_source << " " << this->buffer.str() << "\" with UplinkSock NULL";
- else
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" with UplinkSock NULL";
- return;
- }
-
- Anope::string sent = IRCD->Format(message_source, this->buffer.str());
- UplinkSock->Write(sent);
- Log(LOG_RAWIO) << "Sent: " << sent;
-}
diff --git a/src/users.cpp b/src/users.cpp
index 13a19c0ef..f6a4adb37 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -31,7 +31,8 @@ time_t MaxUserTime = 0;
std::list<User *> User::quitting_users;
-User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *account) : ip(uip)
+User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const std::vector<Anope::string> &smodeparams, const Anope::string &suid, NickCore *account)
+ : ip(uip)
{
if (snick.empty() || sident.empty() || shost.empty())
throw CoreException("Bad args passed to User::User");
@@ -40,7 +41,6 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
quit = false;
server = NULL;
invalid_pw_count = invalid_pw_time = lastmemosend = lastnickreg = lastmail = 0;
- on_access = false;
this->nick = snick;
this->ident = sident;
@@ -50,7 +50,7 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
this->server = sserver;
this->realname = srealname;
this->timestamp = this->signon = ts;
- this->SetModesInternal(sserver, "%s", smodes.c_str());
+ this->SetModesInternal(sserver, smodes, smodeparams);
this->uid = suid;
this->super_admin = false;
this->nc = NULL;
@@ -93,7 +93,7 @@ static void CollideKill(User *target, const Anope::string &reason)
else
{
// Be sure my user is really dead
- IRCD->SendQuit(target, "%s", reason.c_str());
+ IRCD->SendQuit(target, reason);
// Reintroduce my client
if (BotInfo *bi = dynamic_cast<BotInfo *>(target))
@@ -111,7 +111,7 @@ static void Collide(User *u, const Anope::string &id, const Anope::string &type)
CollideKill(u, type);
}
-User* User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc)
+User *User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc, const std::vector<Anope::string> &smodeparams)
{
// How IRCds handle collisions varies a lot, for safety well just always kill both sides
// With properly set qlines, this can almost never happen anyway
@@ -133,7 +133,7 @@ User* User::OnIntroduce(const Anope::string &snick, const Anope::string &sident,
}
}
- return new User(snick, sident, shost, svhost, sip, sserver, srealname, ts, smodes, suid, nc);
+ return new User(snick, sident, shost, svhost, sip, sserver, srealname, ts, smodes, smodeparams, suid, nc);
}
void User::ChangeNick(const Anope::string &newnick, time_t ts)
@@ -153,14 +153,14 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts)
else
{
NickAlias *old_na = NickAlias::Find(this->nick);
- if (old_na && (this->IsIdentified(true) || this->IsRecognized()))
+ if (old_na && this->IsIdentified(true))
old_na->last_seen = Anope::CurTime;
UserListByNick.erase(this->nick);
this->nick = newnick;
- User* &other = UserListByNick[this->nick];
+ User *&other = UserListByNick[this->nick];
if (other)
{
CollideKill(this, "Nick collision");
@@ -169,11 +169,7 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts)
}
other = this;
- on_access = false;
NickAlias *na = NickAlias::Find(this->nick);
- if (na)
- on_access = na->nc->IsOnAccess(this);
-
if (na && na->nc == this->Account())
{
na->last_seen = Anope::CurTime;
@@ -282,7 +278,7 @@ void User::SetRealname(const Anope::string &srealname)
this->realname = srealname;
NickAlias *na = NickAlias::Find(this->nick);
- if (na && (this->IsIdentified(true) || this->IsRecognized()))
+ if (na && this->IsIdentified(true))
na->last_realname = srealname;
Log(this, "realname") << "changed realname to " << srealname;
@@ -332,26 +328,52 @@ void User::SendMessage(BotInfo *source, const char *fmt, ...)
va_end(args);
}
-void User::SendMessage(BotInfo *source, const Anope::string &msg)
+void User::SendMessage(BotInfo *source, int count, const char *singular, const char *plural, ...)
{
- const char *translated_message = Language::Translate(this, msg.c_str());
+ va_list args;
+ char buf[BUFSIZE] = "";
+
+ const char *translated_message = Language::Translate(this, count, singular, plural);
- /* Send privmsg instead of notice if:
- * - UsePrivmsg is enabled
- * - The user is not registered and NSDefMsg is enabled
- * - The user is registered and has set /ns set msg on
- */
- bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasExt("MSG")));
- sepstream sep(translated_message, '\n', true);
- for (Anope::string tok; sep.GetToken(tok);)
+ va_start(args, plural);
+ vsnprintf(buf, BUFSIZE - 1, translated_message, args);
+
+ this->SendMessage(source, Anope::string(buf));
+
+ va_end(args);
+}
+
+namespace
+{
+ void SendMessageInternal(BotInfo *source, User *target, const Anope::string &msg, const Anope::map<Anope::string> &tags)
{
- if (send_privmsg)
- IRCD->SendPrivmsg(source, this->GetUID(), "%s", tok.c_str());
- else
- IRCD->SendNotice(source, this->GetUID(), "%s", tok.c_str());
+ const char *translated_message = Language::Translate(target, msg.c_str());
+
+ sepstream sep(translated_message, '\n', true);
+ for (Anope::string tok; sep.GetToken(tok);)
+ {
+ if (target->ShouldPrivmsg())
+ IRCD->SendPrivmsg(source, target->GetUID(), tok, tags);
+ else
+ IRCD->SendNotice(source, target->GetUID(), tok, tags);
+ }
}
}
+void User::SendMessage(BotInfo *source, const Anope::string &msg)
+{
+ SendMessageInternal(source, this, msg, {});
+}
+
+void User::SendMessage(CommandSource &source, const Anope::string &msg)
+{
+ Anope::map<Anope::string> tags;
+ if (!source.msgid.empty())
+ tags["+draft/reply"] = source.msgid;
+
+ SendMessageInternal(*source.service, this, msg, tags);
+}
+
void User::Identify(NickAlias *na)
{
if (this->nick.equals_ci(na->nick))
@@ -372,17 +394,18 @@ void User::Identify(NickAlias *na)
{
if (!this->nc->o->ot->modes.empty())
{
- this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str());
- this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str());
- UserMode *um = ModeManager::FindUserModeByName("OPER");
+ auto *um = ModeManager::FindUserModeByName("OPER");
if (um && !this->HasMode("OPER") && this->nc->o->ot->modes.find(um->mchar) != Anope::string::npos)
IRCD->SendOper(this);
+
+ this->SetModes(NULL, this->nc->o->ot->modes);
+ this->SendMessage(NULL, _("Changing your usermodes to \002%s\002"), this->nc->o->ot->modes.c_str());
}
if (IRCD->CanSetVHost && !this->nc->o->vhost.empty())
{
- this->SendMessage(NULL, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str());
+ this->SendMessage(NULL, _("Changing your vhost to \002%s\002"), this->nc->o->vhost.c_str());
this->SetDisplayedHost(this->nc->o->vhost);
- IRCD->SendVhost(this, "", this->nc->o->vhost);
+ IRCD->SendVHost(this, "", this->nc->o->vhost);
}
}
}
@@ -424,6 +447,11 @@ NickCore *User::Account() const
return this->nc;
}
+NickAlias *User::AccountNick() const
+{
+ return this->nc ? this->nc->na : nullptr;
+}
+
bool User::IsIdentified(bool check_nick) const
{
if (check_nick && this->nc)
@@ -432,56 +460,58 @@ bool User::IsIdentified(bool check_nick) const
return na && *na->nc == *this->nc;
}
- return this->nc ? true : false;
+ return this->nc;
}
-bool User::IsRecognized(bool check_secure) const
+bool User::IsSecurelyConnected() const
{
- if (check_secure && on_access)
- {
- const NickAlias *na = NickAlias::Find(this->nick);
-
- if (!na || na->nc->HasExt("NS_SECURE"))
- return false;
- }
-
- return on_access;
+ return HasMode("SSL") || HasExt("ssl");
}
bool User::IsServicesOper()
{
if (!this->nc || !this->nc->IsServicesOper())
- // No opertype.
- return false;
- else if (this->nc->o->require_oper && !this->HasMode("OPER"))
- return false;
- else if (!this->nc->o->certfp.empty() && this->fingerprint != this->nc->o->certfp)
- // Certfp mismatch
- return false;
- else if (!this->nc->o->hosts.empty())
+ return false; // Account isn't a services oper.
+
+ auto *oper = this->nc->o;
+ if (oper->require_oper && !this->HasMode("OPER"))
+ return false; // User isn't an ircd oper.
+
+ if (!oper->certfp.empty())
+ {
+ bool match = false;
+ for (const auto &certfp : oper->certfp)
+ {
+ if (this->fingerprint == certfp)
+ {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false; // Wrong TLS fingerprint.
+ }
+
+ if (!oper->hosts.empty())
{
bool match = false;
Anope::string match_host = this->GetIdent() + "@" + this->host;
Anope::string match_ip = this->GetIdent() + "@" + this->ip.addr();
- for (unsigned i = 0; i < this->nc->o->hosts.size(); ++i)
+ for (const auto &userhost : oper->hosts)
{
- const Anope::string &userhost = this->nc->o->hosts[i];
if (Anope::Match(match_host, userhost) || Anope::Match(match_ip, userhost))
{
match = true;
break;
}
}
- if (match == false)
- return false;
+ if (!match)
+ return false; // Wrong user@host/ip.
}
EventReturn MOD_RESULT;
FOREACH_RESULT(IsServicesOper, MOD_RESULT, (this));
- if (MOD_RESULT == EVENT_STOP)
- return false;
-
- return true;
+ return MOD_RESULT != EVENT_STOP;
}
bool User::HasCommand(const Anope::string &command)
@@ -504,11 +534,7 @@ void User::UpdateHost()
return;
NickAlias *na = NickAlias::Find(this->nick);
- on_access = false;
- if (na)
- on_access = na->nc->IsOnAccess(this);
-
- if (na && (this->IsIdentified(true) || this->IsRecognized()))
+ if (na && this->IsIdentified(true))
{
Anope::string last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost();
Anope::string last_realhost = this->GetIdent() + "@" + this->host;
@@ -539,17 +565,18 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop
{
if (!this->nc->o->ot->modes.empty())
{
- this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str());
- this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str());
- UserMode *oper = ModeManager::FindUserModeByName("OPER");
+ auto *oper = ModeManager::FindUserModeByName("OPER");
if (oper && !this->HasMode("OPER") && this->nc->o->ot->modes.find(oper->mchar) != Anope::string::npos)
IRCD->SendOper(this);
+
+ this->SetModes(NULL, this->nc->o->ot->modes);
+ this->SendMessage(NULL, _("Changing your usermodes to \002%s\002"), this->nc->o->ot->modes.c_str());
}
if (IRCD->CanSetVHost && !this->nc->o->vhost.empty())
{
- this->SendMessage(NULL, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str());
+ this->SendMessage(NULL, _("Changing your vhost to \002%s\002"), this->nc->o->vhost.c_str());
this->SetDisplayedHost(this->nc->o->vhost);
- IRCD->SendVhost(this, "", this->nc->o->vhost);
+ IRCD->SendVHost(this, "", this->nc->o->vhost);
}
}
}
@@ -616,19 +643,24 @@ void User::SetModes(BotInfo *bi, const char *umodes, ...)
{
char buf[BUFSIZE] = "";
va_list args;
- Anope::string modebuf, sbuf;
- int add = -1;
va_start(args, umodes);
vsnprintf(buf, BUFSIZE - 1, umodes, args);
va_end(args);
- spacesepstream sep(buf);
+ SetModes(bi, Anope::string(buf));
+}
+
+void User::SetModes(BotInfo *bi, const Anope::string &umodes)
+{
+ Anope::string modebuf, sbuf;
+ int add = -1;
+ spacesepstream sep(umodes);
sep.GetToken(modebuf);
- for (unsigned i = 0, end = modebuf.length(); i < end; ++i)
+ for (auto mode : modebuf)
{
UserMode *um;
- switch (modebuf[i])
+ switch (mode)
{
case '+':
add = 1;
@@ -639,7 +671,7 @@ void User::SetModes(BotInfo *bi, const char *umodes, ...)
default:
if (add == -1)
continue;
- um = ModeManager::FindUserModeByChar(modebuf[i]);
+ um = ModeManager::FindUserModeByChar(mode);
if (!um)
continue;
}
@@ -656,26 +688,18 @@ void User::SetModes(BotInfo *bi, const char *umodes, ...)
}
}
-void User::SetModesInternal(const MessageSource &source, const char *umodes, ...)
+void User::SetModesInternal(const MessageSource &source, const Anope::string &umodes, const std::vector<Anope::string> &umodeparams)
{
- char buf[BUFSIZE] = "";
- va_list args;
- Anope::string modebuf, sbuf;
- int add = -1;
- va_start(args, umodes);
- vsnprintf(buf, BUFSIZE - 1, umodes, args);
- va_end(args);
-
- if (this->server && this->server->IsSynced() && Anope::string(buf) != "+")
- Log(this, "mode") << "changes modes to " << buf;
+ if (this->server && this->server->IsSynced() && Anope::string(umodes) != "+")
+ Log(this, "mode") << "changes modes to " << umodes;
- spacesepstream sep(buf);
- sep.GetToken(modebuf);
- for (unsigned i = 0, end = modebuf.length(); i < end; ++i)
+ int add = -1;
+ auto paramit = umodeparams.begin();
+ for (const auto mode : umodes)
{
UserMode *um;
- switch (modebuf[i])
+ switch (mode)
{
case '+':
add = 1;
@@ -686,15 +710,16 @@ void User::SetModesInternal(const MessageSource &source, const char *umodes, ...
default:
if (add == -1)
continue;
- um = ModeManager::FindUserModeByChar(modebuf[i]);
+ um = ModeManager::FindUserModeByChar(mode);
if (!um)
continue;
}
if (add)
{
- if (um->type == MODE_PARAM && sep.GetToken(sbuf))
- this->SetModeInternal(source, um, sbuf);
+ Anope::string sbuf;
+ if (um->type == MODE_PARAM && paramit != umodeparams.end())
+ this->SetModeInternal(source, um, *paramit++);
else
this->SetModeInternal(source, um);
}
@@ -707,16 +732,16 @@ Anope::string User::GetModes() const
{
Anope::string m, params;
- for (ModeList::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it)
+ for (const auto &[mode, value] : this->modes)
{
- UserMode *um = ModeManager::FindUserModeByName(it->first);
+ UserMode *um = ModeManager::FindUserModeByName(mode);
if (um == NULL)
continue;
m += um->mchar;
- if (!it->second.empty())
- params += " " + it->second;
+ if (!value.empty())
+ params += " " + value;
}
return m + params;
@@ -744,7 +769,7 @@ void User::Kill(const MessageSource &source, const Anope::string &reason)
{
Anope::string real_reason = source.GetName() + " (" + reason + ")";
- IRCD->SendSVSKill(source, this, "%s", real_reason.c_str());
+ IRCD->SendSVSKill(source, this, real_reason);
}
void User::KillInternal(const MessageSource &source, const Anope::string &reason)
@@ -810,14 +835,14 @@ Anope::string User::Mask() const
bool User::BadPassword()
{
- if (!Config->GetBlock("options")->Get<int>("badpasslimit"))
+ if (!Config->GetBlock("options")->Get<unsigned int>("badpasslimit"))
return false;
if (Config->GetBlock("options")->Get<time_t>("badpasstimeout") > 0 && this->invalid_pw_time > 0 && this->invalid_pw_time < Anope::CurTime - Config->GetBlock("options")->Get<time_t>("badpasstimeout"))
this->invalid_pw_count = 0;
++this->invalid_pw_count;
this->invalid_pw_time = Anope::CurTime;
- if (this->invalid_pw_count >= Config->GetBlock("options")->Get<int>("badpasslimit"))
+ if (this->invalid_pw_count >= Config->GetBlock("options")->Get<unsigned int>("badpasslimit"))
{
this->Kill(Me, "Too many invalid passwords");
return true;
@@ -826,7 +851,16 @@ bool User::BadPassword()
return false;
}
-User* User::Find(const Anope::string &name, bool nick_only)
+bool User::ShouldPrivmsg() const
+{
+ // Send a PRIVMSG instead of a NOTICE if:
+ // 1. The user is not registered and msg is in nickserv:defaults.
+ // 2. The user is registered and has set /ns set message on.
+ static ExtensibleRef<bool> msg("MSG");
+ return (!nc && Config->DefPrivmsg) || (nc && msg && msg->HasExt(nc));
+}
+
+User *User::Find(const Anope::string &name, bool nick_only)
{
if (!nick_only && IRCD && IRCD->RequiresID)
{
@@ -847,7 +881,7 @@ User* User::Find(const Anope::string &name, bool nick_only)
void User::QuitUsers()
{
- for (std::list<User *>::iterator it = quitting_users.begin(), it_end = quitting_users.end(); it != it_end; ++it)
- delete *it;
+ for (const auto *quitting_user : quitting_users)
+ delete quitting_user;
quitting_users.clear();
}
diff --git a/src/version.sh b/src/version.sh
index 5be2b116d..fdb133c6f 100644
--- a/src/version.sh
+++ b/src/version.sh
@@ -1,6 +1,6 @@
#!/bin/sh
VERSION_MAJOR=2
-VERSION_MINOR=0
-VERSION_PATCH=18
+VERSION_MINOR=1
+VERSION_PATCH=12
VERSION_EXTRA="-git"
diff --git a/src/win32/Config.cs b/src/win32/Config.cs
index 812700b5e..fc0b5c78f 100644
--- a/src/win32/Config.cs
+++ b/src/win32/Config.cs
@@ -1,7 +1,7 @@
/*
* Config.cs - Windows Configuration
*
- * (C) 2003-2024 Anope Team
+ * (C) 2003-2025 Anope Team
* Contact us at team@anope.org
*
* This program is free but copyrighted software; see the file COPYING for
diff --git a/src/win32/anope_windows.h b/src/win32/anope_windows.h
index 274667bb6..71e896992 100644
--- a/src/win32/anope_windows.h
+++ b/src/win32/anope_windows.h
@@ -29,9 +29,7 @@
# define DllExport __declspec(dllimport)
#endif
-#define MARK_DEPRECATED
-
-#if GETTEXT_FOUND
+#if HAVE_LOCALIZATION
/* Undefine some functions libintl defines */
# undef snprintf
# undef vsnprintf
@@ -53,13 +51,11 @@
#define EINPROGRESS WSAEWOULDBLOCK
#include "socket.h"
-#include "dir/dir.h"
#include "dl/dl.h"
#include "pipe/pipe.h"
-#include "pthread/pthread.h"
#include "sigaction/sigaction.h"
-typedef int ssize_t;
+typedef SSIZE_T ssize_t;
namespace Anope
{
@@ -69,9 +65,6 @@ namespace Anope
extern CoreExport void OnStartup();
extern CoreExport void OnShutdown();
extern CoreExport USHORT WindowsGetLanguage(const Anope::string &lang);
-extern CoreExport int gettimeofday(timeval *tv, void *);
-extern CoreExport Anope::string GetWindowsVersion();
-extern CoreExport bool SupportedWindowsVersion();
extern int setenv(const char *name, const char *value, int overwrite);
extern int unsetenv(const char *name);
extern int mkstemp(char *input);
diff --git a/src/win32/conanfile.txt b/src/win32/conanfile.txt
index ac72eee2a..d0ef69167 100644
--- a/src/win32/conanfile.txt
+++ b/src/win32/conanfile.txt
@@ -1,4 +1,5 @@
[requires]
+argon2/20190702
libmysqlclient/8.1.0
openssl/3.2.1
pcre2/10.42
@@ -7,6 +8,7 @@ gettext/0.21
libgettext/0.22
[options]
+argon2/*:shared=True
libmysqlclient/*:shared=True
openssl/*:shared=True
pcre2/*:shared=True
diff --git a/src/win32/dir/dir.cpp b/src/win32/dir/dir.cpp
deleted file mode 100644
index 944fd92b1..000000000
--- a/src/win32/dir/dir.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/* POSIX emulation layer for Windows.
- *
- * (C) 2008-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "dir.h"
-#include <stdio.h>
-
-DIR *opendir(const char *path)
-{
- char real_path[MAX_PATH];
- _snprintf(real_path, sizeof(real_path), "%s/*", path);
-
- DIR *d = new DIR();
- d->handle = FindFirstFile(real_path, &d->data);
- d->read_first = false;
-
- if (d->handle == INVALID_HANDLE_VALUE)
- {
- delete d;
- return NULL;
- }
-
- return d;
-}
-
-dirent *readdir(DIR *d)
-{
- if (d->read_first == false)
- d->read_first = true;
- else if (!FindNextFile(d->handle, &d->data))
- return NULL;
-
- d->ent.d_ino = 1;
- d->ent.d_name = d->data.cFileName;
-
- return &d->ent;
-}
-
-int closedir(DIR *d)
-{
- FindClose(d->handle);
- delete d;
- return 0;
-}
diff --git a/src/win32/dir/dir.h b/src/win32/dir/dir.h
deleted file mode 100644
index 4f444f672..000000000
--- a/src/win32/dir/dir.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* POSIX emulation layer for Windows.
- *
- * (C) 2008-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include <windows.h>
-
-struct dirent
-{
- int d_ino;
- char *d_name;
-};
-
-struct DIR
-{
- dirent ent;
- HANDLE handle;
- WIN32_FIND_DATA data;
- bool read_first;
-};
-
-DIR *opendir(const char *);
-dirent *readdir(DIR *);
-int closedir(DIR *);
diff --git a/src/win32/dl/dl.cpp b/src/win32/dl/dl.cpp
index 9006c9cc6..464809578 100644
--- a/src/win32/dl/dl.cpp
+++ b/src/win32/dl/dl.cpp
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
diff --git a/src/win32/dl/dl.h b/src/win32/dl/dl.h
index 2c3509020..1907554dd 100644
--- a/src/win32/dl/dl.h
+++ b/src/win32/dl/dl.h
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
diff --git a/src/win32/pipe/pipe.cpp b/src/win32/pipe/pipe.cpp
index d9e81e8eb..fd198e932 100644
--- a/src/win32/pipe/pipe.cpp
+++ b/src/win32/pipe/pipe.cpp
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
diff --git a/src/win32/pipe/pipe.h b/src/win32/pipe/pipe.h
index 81d366d8d..80fbe2a7b 100644
--- a/src/win32/pipe/pipe.h
+++ b/src/win32/pipe/pipe.h
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
diff --git a/src/win32/pthread/pthread.cpp b/src/win32/pthread/pthread.cpp
deleted file mode 100644
index 7b705c9d6..000000000
--- a/src/win32/pthread/pthread.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* POSIX emulation layer for Windows.
- *
- * (C) 2008-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "pthread.h"
-
-struct ThreadInfo
-{
- void *(*entry)(void *);
- void *param;
-};
-
-static DWORD WINAPI entry_point(void *parameter)
-{
- ThreadInfo *ti = static_cast<ThreadInfo *>(parameter);
- ti->entry(ti->param);
- delete ti;
- return 0;
-}
-
-int pthread_attr_init(pthread_attr_t *)
-{
- /* No need for this */
- return 0;
-}
-
-int pthread_attr_setdetachstate(pthread_attr_t *, int)
-{
- /* No need for this */
- return 0;
-}
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *, void *(*entry)(void *), void *param)
-{
- ThreadInfo *ti = new ThreadInfo;
- ti->entry = entry;
- ti->param = param;
-
- *thread = CreateThread(NULL, 0, entry_point, ti, 0, NULL);
- if (!*thread)
- {
- delete ti;
- return -1;
- }
-
- return 0;
-}
-
-int pthread_join(pthread_t thread, void **)
-{
- if (WaitForSingleObject(thread, INFINITE) == WAIT_FAILED)
- return -1;
- CloseHandle(thread);
- return 0;
-}
-
-void pthread_exit(int i)
-{
- ExitThread(i);
-}
-
-int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *)
-{
- InitializeCriticalSection(mutex);
- return 0;
-}
-
-int pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
- DeleteCriticalSection(mutex);
- return 0;
-}
-
-int pthread_mutex_lock(pthread_mutex_t *mutex)
-{
- EnterCriticalSection(mutex);
- return 0;
-}
-
-int pthread_mutex_trylock(pthread_mutex_t *mutex)
-{
- return !TryEnterCriticalSection(mutex);
-}
-
-int pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
- LeaveCriticalSection(mutex);
- return 0;
-}
-
-int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *)
-{
- *cond = CreateEvent(NULL, false, false, NULL);
- if (*cond == NULL)
- return -1;
- return 0;
-}
-
-int pthread_cond_destroy(pthread_cond_t *cond)
-{
- return !CloseHandle(*cond);
-}
-
-int pthread_cond_signal(pthread_cond_t *cond)
-{
- return !PulseEvent(*cond);
-}
-
-int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- LeaveCriticalSection(mutex);
- WaitForSingleObject(*cond, INFINITE);
- EnterCriticalSection(mutex);
- return 0;
-}
diff --git a/src/win32/pthread/pthread.h b/src/win32/pthread/pthread.h
deleted file mode 100644
index 072d66c93..000000000
--- a/src/win32/pthread/pthread.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* POSIX emulation layer for Windows.
- *
- * (C) 2008-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include <Windows.h>
-
-typedef HANDLE pthread_t;
-typedef CRITICAL_SECTION pthread_mutex_t;
-typedef HANDLE pthread_cond_t;
-typedef int pthread_attr_t;
-typedef void pthread_mutexattr_t;
-typedef void pthread_condattr_t;
-
-#define PTHREAD_CREATE_JOINABLE 0
-
-extern int pthread_attr_init(pthread_attr_t *);
-extern int pthread_attr_setdetachstate(pthread_attr_t *, int);
-extern int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
-extern int pthread_join(pthread_t, void **);
-extern void pthread_exit(int);
-
-extern int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
-extern int pthread_mutex_destroy(pthread_mutex_t *);
-extern int pthread_mutex_lock(pthread_mutex_t *);
-extern int pthread_mutex_trylock(pthread_mutex_t *);
-extern int pthread_mutex_unlock(pthread_mutex_t *);
-
-extern int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
-extern int pthread_cond_destroy(pthread_cond_t *);
-extern int pthread_cond_signal(pthread_cond_t *);
-extern int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
diff --git a/src/win32/resource.h b/src/win32/resource.h
index 4c9af7ff2..3d2dfc60b 100644
--- a/src/win32/resource.h
+++ b/src/win32/resource.h
@@ -1,6 +1,6 @@
/*
*
- * (C) 2005-2024 Anope Team
+ * (C) 2005-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
diff --git a/src/win32/sigaction/sigaction.cpp b/src/win32/sigaction/sigaction.cpp
index 829ce6c66..4a3346aaa 100644
--- a/src/win32/sigaction/sigaction.cpp
+++ b/src/win32/sigaction/sigaction.cpp
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
diff --git a/src/win32/sigaction/sigaction.h b/src/win32/sigaction/sigaction.h
index 0492ca0e0..272b82bbe 100644
--- a/src/win32/sigaction/sigaction.h
+++ b/src/win32/sigaction/sigaction.h
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -18,7 +18,7 @@
# define SIGPIPE -1
#endif
-struct sigaction
+struct sigaction final
{
void (*sa_handler)(int);
int sa_flags;
diff --git a/src/win32/socket.cpp b/src/win32/socket.cpp
index 3a7a112d8..972cdbcc6 100644
--- a/src/win32/socket.cpp
+++ b/src/win32/socket.cpp
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -48,87 +48,6 @@ int windows_accept(int fd, struct sockaddr *addr, int *addrlen)
return i;
}
-/** This is inet_pton, but it works on Windows
- * @param af The protocol type, AF_INET or AF_INET6
- * @param src The address
- * @param dst Struct to put results in
- * @return 1 on success, -1 on error
- */
-int windows_inet_pton(int af, const char *src, void *dst)
-{
- int address_length;
- sockaddr_storage sa;
- sockaddr_in *sin = reinterpret_cast<sockaddr_in *>(&sa);
- sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6 *>(&sa);
-
- switch (af)
- {
- case AF_INET:
- address_length = sizeof(sockaddr_in);
- break;
- case AF_INET6:
- address_length = sizeof(sockaddr_in6);
- break;
- default:
- return -1;
- }
-
- if (!WSAStringToAddress(static_cast<LPSTR>(const_cast<char *>(src)), af, NULL, reinterpret_cast<LPSOCKADDR>(&sa), &address_length))
- {
- switch (af)
- {
- case AF_INET:
- memcpy(dst, &sin->sin_addr, sizeof(in_addr));
- break;
- case AF_INET6:
- memcpy(dst, &sin6->sin6_addr, sizeof(in6_addr));
- break;
- }
- return 1;
- }
-
- return 0;
-}
-
-/** This is inet_ntop, but it works on Windows
- * @param af The protocol type, AF_INET or AF_INET6
- * @param src Network address structure
- * @param dst After converting put it here
- * @param size sizeof the dest
- * @return dst
- */
-const char *windows_inet_ntop(int af, const void *src, char *dst, size_t size)
-{
- int address_length;
- DWORD string_length = size;
- sockaddr_storage sa;
- sockaddr_in *sin = reinterpret_cast<sockaddr_in *>(&sa);
- sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6 *>(&sa);
-
- memset(&sa, 0, sizeof(sa));
-
- switch (af)
- {
- case AF_INET:
- address_length = sizeof(sockaddr_in);
- sin->sin_family = af;
- memcpy(&sin->sin_addr, src, sizeof(in_addr));
- break;
- case AF_INET6:
- address_length = sizeof(sockaddr_in6);
- sin6->sin6_family = af;
- memcpy(&sin6->sin6_addr, src, sizeof(in6_addr));
- break;
- default:
- return NULL;
- }
-
- if (!WSAAddressToString(reinterpret_cast<LPSOCKADDR>(&sa), address_length, NULL, dst, &string_length))
- return dst;
-
- return NULL;
-}
-
int fcntl(int fd, int cmd, int arg)
{
if (cmd == F_GETFL)
diff --git a/src/win32/socket.h b/src/win32/socket.h
index 7c20a65ad..1125774a8 100644
--- a/src/win32/socket.h
+++ b/src/win32/socket.h
@@ -1,6 +1,6 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2024 Anope Team
+ * (C) 2008-2025 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -21,12 +21,8 @@ extern CoreExport int read(int fd, char *buf, size_t count);
extern CoreExport int write(int fd, const char *buf, size_t count);
extern CoreExport int windows_close(int fd);
extern CoreExport int windows_accept(int fd, struct sockaddr *addr, int *addrlen);
-extern CoreExport int windows_inet_pton(int af, const char *src, void *dst);
-extern CoreExport const char *windows_inet_ntop(int af, const void *src, char *dst, size_t size);
extern CoreExport int fcntl(int fd, int cmd, int arg);
#ifndef WIN32_NO_OVERRIDE
# define accept windows_accept
-# define inet_pton windows_inet_pton
-# define inet_ntop windows_inet_ntop
#endif
diff --git a/src/win32/win32.rc.cmake b/src/win32/win32.rc.cmake
index c72fe2b49..f0f3f8759 100644
--- a/src/win32/win32.rc.cmake
+++ b/src/win32/win32.rc.cmake
@@ -34,9 +34,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VER_ANOPE VERSIONINFO
FILEVERSION @VERSION_COMMA@
PRODUCTVERSION @VERSION_COMMA@
-#ifndef MINGW
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-#endif
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
@@ -54,7 +52,7 @@ BEGIN
VALUE "FileDescription", "Anope IRC Services"
VALUE "FileVersion", "@VERSION_FULL@"
VALUE "InternalName", "Anope"
- VALUE "LegalCopyright", "Copyright (C) 2003-2024 Anope Team"
+ VALUE "LegalCopyright", "Copyright (C) 2003-2025 Anope Team"
VALUE "OriginalFilename", "anope.exe"
VALUE "ProductName", "Anope"
VALUE "ProductVersion", "@VERSION_DOTTED@"
diff --git a/src/win32/windows.cpp b/src/win32/windows.cpp
index 54ce44202..73045f408 100644
--- a/src/win32/windows.cpp
+++ b/src/win32/windows.cpp
@@ -1,7 +1,7 @@
/* POSIX emulation layer for Windows.
*
* (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
- * (C) 2008-2024 Anope Team <team@anope.org>
+ * (C) 2008-2025 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*
@@ -18,23 +18,20 @@
#include <sys/types.h>
#include <fcntl.h>
-static struct WindowsLanguage
+static struct WindowsLanguage final
{
Anope::string languageName;
USHORT windowsLanguageName;
} WindowsLanguages[] = {
- {"ca_ES", LANG_CATALAN},
{"de_DE", LANG_GERMAN},
{"el_GR", LANG_GREEK},
{"en_US", LANG_ENGLISH},
{"es_ES", LANG_SPANISH},
{"fr_FR", LANG_FRENCH},
- {"hu_HU", LANG_HUNGARIAN},
{"it_IT", LANG_ITALIAN},
{"nl_NL", LANG_DUTCH},
{"pl_PL", LANG_POLISH},
{"pt_PT", LANG_PORTUGUESE},
- {"ru_RU", LANG_RUSSIAN},
{"tr_TR", LANG_TURKISH},
};
@@ -64,172 +61,6 @@ USHORT WindowsGetLanguage(const Anope::string &lang)
return LANG_NEUTRAL;
}
-/** Like gettimeofday(), but it works on Windows.
- * @param tv A timeval struct
- * @param tz Should be NULL, it is not used
- * @return 0 on success
- */
-int gettimeofday(timeval *tv, void *)
-{
- SYSTEMTIME st;
- GetSystemTime(&st);
-
- tv->tv_sec = Anope::CurTime;
- tv->tv_usec = st.wMilliseconds;
-
- return 0;
-}
-
-Anope::string GetWindowsVersion()
-{
- OSVERSIONINFOEX osvi;
- SYSTEM_INFO si;
-
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- ZeroMemory(&si, sizeof(SYSTEM_INFO));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi));
- if (!bOsVersionInfoEx)
- {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)))
- return "";
- }
- GetSystemInfo(&si);
-
- Anope::string buf, extra, cputype;
- /* Determine CPU type 32 or 64 */
- if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- cputype = " 64-bit";
- else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- cputype = " 32-bit";
- else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
- cputype = " Itanium 64-bit";
-
- switch (osvi.dwPlatformId)
- {
- /* test for the Windows NT product family. */
- case VER_PLATFORM_WIN32_NT:
- /* Windows Vista or Windows Server 2008 */
- if (osvi.dwMajorVersion == 6 && !osvi.dwMinorVersion)
- {
- if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- extra = " Enterprise Edition";
- else if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- extra = " Datacenter Edition";
- else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- extra = " Home Premium/Basic";
- if (osvi.dwMinorVersion == 0)
- {
- if (osvi.wProductType & VER_NT_WORKSTATION)
- buf = "Microsoft Windows Vista" + cputype + extra;
- else
- buf = "Microsoft Windows Server 2008" + cputype + extra;
- }
- else if (osvi.dwMinorVersion == 1)
- {
- if (osvi.wProductType & VER_NT_WORKSTATION)
- buf = "Microsoft Windows 7" + cputype + extra;
- else
- buf = "Microsoft Windows Server 2008 R2" + cputype + extra;
- }
- }
- /* Windows 2003 or Windows XP Pro 64 */
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
- {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- extra = " Datacenter Edition";
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- extra = " Enterprise Edition";
-#ifdef VER_SUITE_COMPUTE_SERVER
- else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER)
- extra = " Compute Cluster Edition";
-#endif
- else if (osvi.wSuiteMask == VER_SUITE_BLADE)
- extra = " Web Edition";
- else
- extra = " Standard Edition";
- if (osvi.wProductType & VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
- buf = "Microsoft Windows XP Professional x64 Edition" + extra;
- else
- buf = "Microsoft Windows Server 2003 Family" + cputype + extra;
- }
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
- {
- if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT)
- extra = " Embedded";
- else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
- extra = " Home Edition";
- buf = "Microsoft Windows XP" + extra;
- }
- if (osvi.dwMajorVersion == 5 && !osvi.dwMinorVersion)
- {
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
- extra = " Datacenter Server";
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- extra = " Advanced Server";
- else
- extra = " Server";
- buf = "Microsoft Windows 2000" + extra;
- }
- if (osvi.dwMajorVersion <= 4)
- {
- if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
- extra = " Enterprise Edition";
- buf = "Microsoft Windows NT Server 4.0" + extra;
- }
- break;
- case VER_PLATFORM_WIN32_WINDOWS:
- if (osvi.dwMajorVersion == 4 && !osvi.dwMinorVersion)
- {
- if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B')
- extra = " OSR2";
- buf = "Microsoft Windows 95" + extra;
- }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
- {
- if (osvi.szCSDVersion[1] == 'A')
- extra = "SE";
- buf = "Microsoft Windows 98" + extra;
- }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
- buf = "Microsoft Windows Millennium Edition";
- }
- return buf;
-}
-
-bool SupportedWindowsVersion()
-{
- OSVERSIONINFOEX osvi;
-
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi));
- if (!bOsVersionInfoEx)
- {
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)))
- return false;
- }
-
- switch (osvi.dwPlatformId)
- {
- /* test for the Windows NT product family. */
- case VER_PLATFORM_WIN32_NT:
- /* win nt4 */
- if (osvi.dwMajorVersion <= 4)
- return false;
- /* the rest */
- return true;
- /* win95 win98 winME */
- case VER_PLATFORM_WIN32_WINDOWS:
- return false;
- }
- return false;
-}
-
int setenv(const char *name, const char *value, int overwrite)
{
return SetEnvironmentVariable(name, value);
diff --git a/src/xline.cpp b/src/xline.cpp
index 87279b412..cdfc2d7c4 100644
--- a/src/xline.cpp
+++ b/src/xline.cpp
@@ -86,7 +86,7 @@ void XLine::Init()
}
}
-XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Me->GetName()), created(0), expires(0), reason(r), id(uid)
+XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Me->GetName()), reason(r), id(uid)
{
regex = NULL;
manager = NULL;
@@ -153,17 +153,17 @@ bool XLine::IsRegex() const
void XLine::Serialize(Serialize::Data &data) const
{
- data["mask"] << this->mask;
- data["by"] << this->by;
- data["created"] << this->created;
- data["expires"] << this->expires;
- data["reason"] << this->reason;
- data["uid"] << this->id;
+ data.Store("mask", this->mask);
+ data.Store("by", this->by);
+ data.Store("created", this->created);
+ data.Store("expires", this->expires);
+ data.Store("reason", this->reason);
+ data.Store("uid", this->id);
if (this->manager)
- data["manager"] << this->manager->name;
+ data.Store("manager", this->manager->name);
}
-Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data)
+Serializable *XLine::Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string smanager;
@@ -224,10 +224,8 @@ void XLineManager::UnregisterXLineManager(XLineManager *xlm)
void XLineManager::CheckAll(User *u)
{
- for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it)
+ for (auto *xlm : XLineManagers)
{
- XLineManager *xlm = *it;
-
if (xlm->CheckAllXLines(u))
break;
}
@@ -251,7 +249,7 @@ Anope::string XLineManager::GenerateUID()
{
char c;
do
- c = (rand() % 75) + 48;
+ c = (Anope::RandomNumber() % 75) + 48;
while (!isupper(c) && !isdigit(c));
id += c;
}
@@ -288,7 +286,7 @@ const std::vector<XLine *> &XLineManager::GetList() const
void XLineManager::AddXLine(XLine *x)
{
if (!x->id.empty())
- XLinesByUID->insert(std::make_pair(x->id, x));
+ XLinesByUID->emplace(x->id, x);
this->xlines->push_back(x);
x->manager = this;
}
@@ -346,7 +344,7 @@ bool XLineManager::DelXLine(XLine *x)
return false;
}
-XLine* XLineManager::GetEntry(unsigned index)
+XLine *XLineManager::GetEntry(unsigned index)
{
if (index >= this->xlines->size())
return NULL;
@@ -361,9 +359,8 @@ void XLineManager::Clear()
std::vector<XLine *> xl;
this->xlines->swap(xl);
- for (unsigned i = 0; i < xl.size(); ++i)
+ for (auto *x : xl)
{
- XLine *x = xl[i];
if (!x->id.empty())
XLinesByUID->erase(x->id);
delete x;
@@ -417,7 +414,7 @@ bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time
return true;
}
-XLine* XLineManager::HasEntry(const Anope::string &mask)
+XLine *XLineManager::HasEntry(const Anope::string &mask)
{
std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask);
if (it != XLinesByUID->end())
@@ -427,10 +424,8 @@ XLine* XLineManager::HasEntry(const Anope::string &mask)
it->second->QueueUpdate();
return it->second;
}
- for (unsigned i = 0, end = this->xlines->size(); i < end; ++i)
+ for (auto *x : *this->xlines)
{
- XLine *x = this->xlines->at(i);
-
if (x->mask.equals_ci(mask))
{
x->QueueUpdate();
diff --git a/vendor/README.md b/vendor/README.md
new file mode 100644
index 000000000..fb4210c35
--- /dev/null
+++ b/vendor/README.md
@@ -0,0 +1,43 @@
+# Vendored Libraries
+
+This directory contains vendored dependencies that are shipped with Anope to avoid users needing to install them manually.
+
+## bcrypt
+
+**Author** &mdash; [Solar Designer](mailto:solar@openwall.com)
+
+**License** &mdash; Public Domain
+
+**Version** &mdash; v1.3
+
+**Website** &mdash; [https://www.openwall.com/crypt/](https://www.openwall.com/crypt/)
+
+## md5
+
+**Author** &mdash; [Solar Designer](mailto:solar@openwall.com)
+
+**License** &mdash; Cut-down BSD License
+
+**Version** &mdash; v2.0
+
+**Website** &mdash; [https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5](https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5)
+
+## sha2
+
+**Author** &mdash; [Olivier Gay](mailto:olivier.gay@a3.epfl.ch)
+
+**License** &mdash; 3-clause BSD License
+
+**Version** &mdash; 2007-02-02
+
+**Website** &mdash; [http://www.ouah.org/ogay/sha2/](http://www.ouah.org/ogay/sha2/)
+
+## yyjson
+
+**Author** &mdash; Yaoyuan Guo
+
+**License** &mdash; MIT License
+
+**Version** &mdash; 0.10.0
+
+**Website** &mdash; [https://github.com/ibireme/yyjson](https://github.com/ibireme/yyjson)
diff --git a/vendor/bcrypt/crypt_blowfish.c b/vendor/bcrypt/crypt_blowfish.c
new file mode 100644
index 000000000..9d3f3be82
--- /dev/null
+++ b/vendor/bcrypt/crypt_blowfish.c
@@ -0,0 +1,907 @@
+/*
+ * The crypt_blowfish homepage is:
+ *
+ * http://www.openwall.com/crypt/
+ *
+ * This code comes from John the Ripper password cracker, with reentrant
+ * and crypt(3) interfaces added, but optimizations specific to password
+ * cracking removed.
+ *
+ * Written by Solar Designer <solar at openwall.com> in 1998-2014.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * It is my intent that you should be able to use this on your system,
+ * as part of a software package, or anywhere else to improve security,
+ * ensure compatibility, or for any other purpose. I would appreciate
+ * it if you give credit where it is due and keep your modifications in
+ * the public domain as well, but I don't require that in order to let
+ * you place this code and any modifications you make under a license
+ * of your choice.
+ *
+ * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
+ * "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses
+ * some of his ideas. The password hashing algorithm was designed by David
+ * Mazieres <dm at lcs.mit.edu>. For information on the level of
+ * compatibility for bcrypt hash prefixes other than "$2b$", please refer to
+ * the comments in BF_set_key() below and to the included crypt(3) man page.
+ *
+ * There's a paper on the algorithm that explains its design decisions:
+ *
+ * http://www.usenix.org/events/usenix99/provos.html
+ *
+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's
+ * Blowfish library (I can't be sure if I would think of something if I
+ * hadn't seen his code).
+ */
+
+#include <string.h>
+
+#include <errno.h>
+#ifndef __set_errno
+#define __set_errno(val) errno = (val)
+#endif
+
+/* Just to make sure the prototypes match the actual definitions */
+#include "crypt_blowfish.h"
+
+#ifdef __i386__
+#define BF_ASM 1
+#define BF_SCALE 1
+#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
+#define BF_ASM 0
+#define BF_SCALE 1
+#else
+#define BF_ASM 0
+#define BF_SCALE 0
+#endif
+
+typedef unsigned int BF_word;
+typedef signed int BF_word_signed;
+
+/* Number of Blowfish rounds, this is also hardcoded into a few places */
+#define BF_N 16
+
+typedef BF_word BF_key[BF_N + 2];
+
+typedef struct {
+ BF_word S[4][0x100];
+ BF_key P;
+} BF_ctx;
+
+/*
+ * Magic IV for 64 Blowfish encryptions that we do at the end.
+ * The string is "OrpheanBeholderScryDoubt" on big-endian.
+ */
+static BF_word BF_magic_w[6] = {
+ 0x4F727068, 0x65616E42, 0x65686F6C,
+ 0x64657253, 0x63727944, 0x6F756274
+};
+
+/*
+ * P-box and S-box tables initialized with digits of Pi.
+ */
+static BF_ctx BF_init_state = {
+ {
+ {
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
+ }, {
+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
+ }, {
+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
+ }, {
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
+ }
+ }, {
+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
+ 0x9216d5d9, 0x8979fb1b
+ }
+};
+
+static unsigned char BF_itoa64[64 + 1] =
+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+static unsigned char BF_atoi64[0x60] = {
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
+};
+
+#define BF_safe_atoi64(dst, src) \
+{ \
+ tmp = (unsigned char)(src); \
+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
+ tmp = BF_atoi64[tmp]; \
+ if (tmp > 63) return -1; \
+ (dst) = tmp; \
+}
+
+static int BF_decode(BF_word *dst, const char *src, int size)
+{
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned char *end = dptr + size;
+ const unsigned char *sptr = (const unsigned char *)src;
+ unsigned int tmp, c1, c2, c3, c4;
+
+ do {
+ BF_safe_atoi64(c1, *sptr++);
+ BF_safe_atoi64(c2, *sptr++);
+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c3, *sptr++);
+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
+ if (dptr >= end) break;
+
+ BF_safe_atoi64(c4, *sptr++);
+ *dptr++ = ((c3 & 0x03) << 6) | c4;
+ } while (dptr < end);
+
+ return 0;
+}
+
+static void BF_encode(char *dst, const BF_word *src, int size)
+{
+ const unsigned char *sptr = (const unsigned char *)src;
+ const unsigned char *end = sptr + size;
+ unsigned char *dptr = (unsigned char *)dst;
+ unsigned int c1, c2;
+
+ do {
+ c1 = *sptr++;
+ *dptr++ = BF_itoa64[c1 >> 2];
+ c1 = (c1 & 0x03) << 4;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 4;
+ *dptr++ = BF_itoa64[c1];
+ c1 = (c2 & 0x0f) << 2;
+ if (sptr >= end) {
+ *dptr++ = BF_itoa64[c1];
+ break;
+ }
+
+ c2 = *sptr++;
+ c1 |= c2 >> 6;
+ *dptr++ = BF_itoa64[c1];
+ *dptr++ = BF_itoa64[c2 & 0x3f];
+ } while (sptr < end);
+}
+
+static void BF_swap(BF_word *x, int count)
+{
+ static int endianness_check = 1;
+ char *is_little_endian = (char *)&endianness_check;
+ BF_word tmp;
+
+ if (*is_little_endian)
+ do {
+ tmp = *x;
+ tmp = (tmp << 16) | (tmp >> 16);
+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
+ } while (--count);
+}
+
+#if BF_SCALE
+/* Architectures which can shift addresses left by 2 bits with no extra cost */
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp2 = L >> 8; \
+ tmp2 &= 0xFF; \
+ tmp3 = L >> 16; \
+ tmp3 &= 0xFF; \
+ tmp4 = L >> 24; \
+ tmp1 = data.ctx.S[3][tmp1]; \
+ tmp2 = data.ctx.S[2][tmp2]; \
+ tmp3 = data.ctx.S[1][tmp3]; \
+ tmp3 += data.ctx.S[0][tmp4]; \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#else
+/* Architectures with no complicated addressing modes supported */
+#define BF_INDEX(S, i) \
+ (*((BF_word *)(((unsigned char *)S) + (i))))
+#define BF_ROUND(L, R, N) \
+ tmp1 = L & 0xFF; \
+ tmp1 <<= 2; \
+ tmp2 = L >> 6; \
+ tmp2 &= 0x3FC; \
+ tmp3 = L >> 14; \
+ tmp3 &= 0x3FC; \
+ tmp4 = L >> 22; \
+ tmp4 &= 0x3FC; \
+ tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
+ tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
+ tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
+ tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
+ tmp3 ^= tmp2; \
+ R ^= data.ctx.P[N + 1]; \
+ tmp3 += tmp1; \
+ R ^= tmp3;
+#endif
+
+/*
+ * Encrypt one block, BF_N is hardcoded here.
+ */
+#define BF_ENCRYPT \
+ L ^= data.ctx.P[0]; \
+ BF_ROUND(L, R, 0); \
+ BF_ROUND(R, L, 1); \
+ BF_ROUND(L, R, 2); \
+ BF_ROUND(R, L, 3); \
+ BF_ROUND(L, R, 4); \
+ BF_ROUND(R, L, 5); \
+ BF_ROUND(L, R, 6); \
+ BF_ROUND(R, L, 7); \
+ BF_ROUND(L, R, 8); \
+ BF_ROUND(R, L, 9); \
+ BF_ROUND(L, R, 10); \
+ BF_ROUND(R, L, 11); \
+ BF_ROUND(L, R, 12); \
+ BF_ROUND(R, L, 13); \
+ BF_ROUND(L, R, 14); \
+ BF_ROUND(R, L, 15); \
+ tmp4 = R; \
+ R = L; \
+ L = tmp4 ^ data.ctx.P[BF_N + 1];
+
+#if BF_ASM
+#define BF_body() \
+ _BF_body_r(&data.ctx);
+#else
+#define BF_body() \
+ L = R = 0; \
+ ptr = data.ctx.P; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.P[BF_N + 2]); \
+\
+ ptr = data.ctx.S[0]; \
+ do { \
+ ptr += 2; \
+ BF_ENCRYPT; \
+ *(ptr - 2) = L; \
+ *(ptr - 1) = R; \
+ } while (ptr < &data.ctx.S[3][0xFF]);
+#endif
+
+static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
+ unsigned char flags)
+{
+ const char *ptr = key;
+ unsigned int bug, i, j;
+ BF_word safety, sign, diff, tmp[2];
+
+/*
+ * There was a sign extension bug in older revisions of this function. While
+ * we would have liked to simply fix the bug and move on, we have to provide
+ * a backwards compatibility feature (essentially the bug) for some systems and
+ * a safety measure for some others. The latter is needed because for certain
+ * multiple inputs to the buggy algorithm there exist easily found inputs to
+ * the correct algorithm that produce the same hash. Thus, we optionally
+ * deviate from the correct algorithm just enough to avoid such collisions.
+ * While the bug itself affected the majority of passwords containing
+ * characters with the 8th bit set (although only a percentage of those in a
+ * collision-producing way), the anti-collision safety measure affects
+ * only a subset of passwords containing the '\xff' character (not even all of
+ * those passwords, just some of them). This character is not found in valid
+ * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
+ * Thus, the safety measure is unlikely to cause much annoyance, and is a
+ * reasonable tradeoff to use when authenticating against existing hashes that
+ * are not reliably known to have been computed with the correct algorithm.
+ *
+ * We use an approach that tries to minimize side-channel leaks of password
+ * information - that is, we mostly use fixed-cost bitwise operations instead
+ * of branches or table lookups. (One conditional branch based on password
+ * length remains. It is not part of the bug aftermath, though, and is
+ * difficult and possibly unreasonable to avoid given the use of C strings by
+ * the caller, which results in similar timing leaks anyway.)
+ *
+ * For actual implementation, we set an array index in the variable "bug"
+ * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
+ * variable "safety" (bit 16 is set when the safety measure is requested).
+ * Valid combinations of settings are:
+ *
+ * Prefix "$2a$": bug = 0, safety = 0x10000
+ * Prefix "$2b$": bug = 0, safety = 0
+ * Prefix "$2x$": bug = 1, safety = 0
+ * Prefix "$2y$": bug = 0, safety = 0
+ */
+ bug = (unsigned int)flags & 1;
+ safety = ((BF_word)flags & 2) << 15;
+
+ sign = diff = 0;
+
+ for (i = 0; i < BF_N + 2; i++) {
+ tmp[0] = tmp[1] = 0;
+ for (j = 0; j < 4; j++) {
+ tmp[0] <<= 8;
+ tmp[0] |= (unsigned char)*ptr; /* correct */
+ tmp[1] <<= 8;
+ tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
+/*
+ * Sign extension in the first char has no effect - nothing to overwrite yet,
+ * and those extra 24 bits will be fully shifted out of the 32-bit word. For
+ * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
+ * extension in tmp[1] occurs. Once this flag is set, it remains set.
+ */
+ if (j)
+ sign |= tmp[1] & 0x80;
+ if (!*ptr)
+ ptr = key;
+ else
+ ptr++;
+ }
+ diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
+
+ expanded[i] = tmp[bug];
+ initial[i] = BF_init_state.P[i] ^ tmp[bug];
+ }
+
+/*
+ * At this point, "diff" is zero iff the correct and buggy algorithms produced
+ * exactly the same result. If so and if "sign" is non-zero, which indicates
+ * that there was a non-benign sign extension, this means that we have a
+ * collision between the correctly computed hash for this password and a set of
+ * passwords that could be supplied to the buggy algorithm. Our safety measure
+ * is meant to protect from such many-buggy to one-correct collisions, by
+ * deviating from the correct algorithm in such cases. Let's check for this.
+ */
+ diff |= diff >> 16; /* still zero iff exact match */
+ diff &= 0xffff; /* ditto */
+ diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
+ sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
+ sign &= ~diff & safety; /* action needed? */
+
+/*
+ * If we have determined that we need to deviate from the correct algorithm,
+ * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
+ * let's stick to it now. It came out of the approach we used above, and it's
+ * not any worse than any other choice we could make.)
+ *
+ * It is crucial that we don't do the same to the expanded key used in the main
+ * Eksblowfish loop. By doing it to only one of these two, we deviate from a
+ * state that could be directly specified by a password to the buggy algorithm
+ * (and to the fully correct one as well, but that's a side-effect).
+ */
+ initial[0] ^= sign;
+}
+
+static const unsigned char flags_by_subtype[26] =
+ {2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
+
+static char *BF_crypt(const char *key, const char *setting,
+ char *output, int size,
+ BF_word min)
+{
+#if BF_ASM
+ extern void _BF_body_r(BF_ctx *ctx);
+#endif
+ struct {
+ BF_ctx ctx;
+ BF_key expanded_key;
+ union {
+ BF_word salt[4];
+ BF_word output[6];
+ } binary;
+ } data;
+ BF_word L, R;
+ BF_word tmp1, tmp2, tmp3, tmp4;
+ BF_word *ptr;
+ BF_word count;
+ int i;
+
+ if (size < 7 + 22 + 31 + 1) {
+ __set_errno(ERANGE);
+ return NULL;
+ }
+
+ if (setting[0] != '$' ||
+ setting[1] != '2' ||
+ setting[2] < 'a' || setting[2] > 'z' ||
+ !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
+ setting[3] != '$' ||
+ setting[4] < '0' || setting[4] > '3' ||
+ setting[5] < '0' || setting[5] > '9' ||
+ (setting[4] == '3' && setting[5] > '1') ||
+ setting[6] != '$') {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+
+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
+ if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
+ __set_errno(EINVAL);
+ return NULL;
+ }
+ BF_swap(data.binary.salt, 4);
+
+ BF_set_key(key, data.expanded_key, data.ctx.P,
+ flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
+
+ memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
+
+ L = R = 0;
+ for (i = 0; i < BF_N + 2; i += 2) {
+ L ^= data.binary.salt[i & 2];
+ R ^= data.binary.salt[(i & 2) + 1];
+ BF_ENCRYPT;
+ data.ctx.P[i] = L;
+ data.ctx.P[i + 1] = R;
+ }
+
+ ptr = data.ctx.S[0];
+ do {
+ ptr += 4;
+ L ^= data.binary.salt[(BF_N + 2) & 3];
+ R ^= data.binary.salt[(BF_N + 3) & 3];
+ BF_ENCRYPT;
+ *(ptr - 4) = L;
+ *(ptr - 3) = R;
+
+ L ^= data.binary.salt[(BF_N + 4) & 3];
+ R ^= data.binary.salt[(BF_N + 5) & 3];
+ BF_ENCRYPT;
+ *(ptr - 2) = L;
+ *(ptr - 1) = R;
+ } while (ptr < &data.ctx.S[3][0xFF]);
+
+ do {
+ int done;
+
+ for (i = 0; i < BF_N + 2; i += 2) {
+ data.ctx.P[i] ^= data.expanded_key[i];
+ data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
+ }
+
+ done = 0;
+ do {
+ BF_body();
+ if (done)
+ break;
+ done = 1;
+
+ tmp1 = data.binary.salt[0];
+ tmp2 = data.binary.salt[1];
+ tmp3 = data.binary.salt[2];
+ tmp4 = data.binary.salt[3];
+ for (i = 0; i < BF_N; i += 4) {
+ data.ctx.P[i] ^= tmp1;
+ data.ctx.P[i + 1] ^= tmp2;
+ data.ctx.P[i + 2] ^= tmp3;
+ data.ctx.P[i + 3] ^= tmp4;
+ }
+ data.ctx.P[16] ^= tmp1;
+ data.ctx.P[17] ^= tmp2;
+ } while (1);
+ } while (--count);
+
+ for (i = 0; i < 6; i += 2) {
+ L = BF_magic_w[i];
+ R = BF_magic_w[i + 1];
+
+ count = 64;
+ do {
+ BF_ENCRYPT;
+ } while (--count);
+
+ data.binary.output[i] = L;
+ data.binary.output[i + 1] = R;
+ }
+
+ memcpy(output, setting, 7 + 22 - 1);
+ output[7 + 22 - 1] = BF_itoa64[(int)
+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
+
+/* This has to be bug-compatible with the original implementation, so
+ * only encode 23 of the 24 bytes. :-) */
+ BF_swap(data.binary.output, 6);
+ BF_encode(&output[7 + 22], data.binary.output, 23);
+ output[7 + 22 + 31] = '\0';
+
+ return output;
+}
+
+int _crypt_output_magic(const char *setting, char *output, int size)
+{
+ if (size < 3)
+ return -1;
+
+ output[0] = '*';
+ output[1] = '0';
+ output[2] = '\0';
+
+ if (setting[0] == '*' && setting[1] == '0')
+ output[1] = '1';
+
+ return 0;
+}
+
+/*
+ * Please preserve the runtime self-test. It serves two purposes at once:
+ *
+ * 1. We really can't afford the risk of producing incompatible hashes e.g.
+ * when there's something like gcc bug 26587 again, whereas an application or
+ * library integrating this code might not also integrate our external tests or
+ * it might not run them after every build. Even if it does, the miscompile
+ * might only occur on the production build, but not on a testing build (such
+ * as because of different optimization settings). It is painful to recover
+ * from incorrectly-computed hashes - merely fixing whatever broke is not
+ * enough. Thus, a proactive measure like this self-test is needed.
+ *
+ * 2. We don't want to leave sensitive data from our actual password hash
+ * computation on the stack or in registers. Previous revisions of the code
+ * would do explicit cleanups, but simply running the self-test after hash
+ * computation is more reliable.
+ *
+ * The performance cost of this quick self-test is around 0.6% at the "$2a$08"
+ * setting.
+ */
+char *_crypt_blowfish_rn(const char *key, const char *setting,
+ char *output, int size)
+{
+ const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
+ const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
+ static const char * const test_hashes[2] =
+ {"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */
+ "VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */
+ const char *test_hash = test_hashes[0];
+ char *retval;
+ const char *p;
+ int save_errno, ok;
+ struct {
+ char s[7 + 22 + 1];
+ char o[7 + 22 + 31 + 1 + 1 + 1];
+ } buf;
+
+/* Hash the supplied password */
+ _crypt_output_magic(setting, output, size);
+ retval = BF_crypt(key, setting, output, size, 16);
+ save_errno = errno;
+
+/*
+ * Do a quick self-test. It is important that we make both calls to BF_crypt()
+ * from the same scope such that they likely use the same stack locations,
+ * which makes the second call overwrite the first call's sensitive data on the
+ * stack and makes it more likely that any alignment related issues would be
+ * detected by the self-test.
+ */
+ memcpy(buf.s, test_setting, sizeof(buf.s));
+ if (retval) {
+ unsigned int flags = flags_by_subtype[
+ (unsigned int)(unsigned char)setting[2] - 'a'];
+ test_hash = test_hashes[flags & 1];
+ buf.s[2] = setting[2];
+ }
+ memset(buf.o, 0x55, sizeof(buf.o));
+ buf.o[sizeof(buf.o) - 1] = 0;
+ p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
+
+ ok = (p == buf.o &&
+ !memcmp(p, buf.s, 7 + 22) &&
+ !memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1));
+
+ {
+ const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
+ BF_key ae, ai, ye, yi;
+ BF_set_key(k, ae, ai, 2); /* $2a$ */
+ BF_set_key(k, ye, yi, 4); /* $2y$ */
+ ai[0] ^= 0x10000; /* undo the safety (for comparison) */
+ ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
+ !memcmp(ae, ye, sizeof(ae)) &&
+ !memcmp(ai, yi, sizeof(ai));
+ }
+
+ __set_errno(save_errno);
+ if (ok)
+ return retval;
+
+/* Should not happen */
+ _crypt_output_magic(setting, output, size);
+ __set_errno(EINVAL); /* pretend we don't support this hash type */
+ return NULL;
+}
+
+char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
+ const char *input, int size, char *output, int output_size)
+{
+ if (size < 16 || output_size < 7 + 22 + 1 ||
+ (count && (count < 4 || count > 31)) ||
+ prefix[0] != '$' || prefix[1] != '2' ||
+ (prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) {
+ if (output_size > 0) output[0] = '\0';
+ __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
+ return NULL;
+ }
+
+ if (!count) count = 5;
+
+ output[0] = '$';
+ output[1] = '2';
+ output[2] = prefix[2];
+ output[3] = '$';
+ output[4] = '0' + count / 10;
+ output[5] = '0' + count % 10;
+ output[6] = '$';
+
+ BF_encode(&output[7], (const BF_word *)input, 16);
+ output[7 + 22] = '\0';
+
+ return output;
+}
diff --git a/vendor/bcrypt/crypt_blowfish.h b/vendor/bcrypt/crypt_blowfish.h
new file mode 100644
index 000000000..2ee0d8c1d
--- /dev/null
+++ b/vendor/bcrypt/crypt_blowfish.h
@@ -0,0 +1,27 @@
+/*
+ * Written by Solar Designer <solar at openwall.com> in 2000-2011.
+ * No copyright is claimed, and the software is hereby placed in the public
+ * domain. In case this attempt to disclaim copyright and place the software
+ * in the public domain is deemed null and void, then the software is
+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See crypt_blowfish.c for more information.
+ */
+
+#ifndef _CRYPT_BLOWFISH_H
+#define _CRYPT_BLOWFISH_H
+
+extern int _crypt_output_magic(const char *setting, char *output, int size);
+extern char *_crypt_blowfish_rn(const char *key, const char *setting,
+ char *output, int size);
+extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
+ unsigned long count,
+ const char *input, int size, char *output, int output_size);
+
+#endif
diff --git a/vendor/md5/LICENSE b/vendor/md5/LICENSE
new file mode 100644
index 000000000..26de4493e
--- /dev/null
+++ b/vendor/md5/LICENSE
@@ -0,0 +1,8 @@
+Copyright (c) 1998-2017 Solar Designer <solar at openwall.com>
+Copyright (c) 2008 Grigoriy Strokin <grg at openwall.com>
+Copyright (c) 2011-2017 ABC <abc at openwall.com>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted.
+
+There's ABSOLUTELY NO WARRANTY, express or implied.
diff --git a/vendor/md5/md5.c b/vendor/md5/md5.c
new file mode 100644
index 000000000..b235e17a5
--- /dev/null
+++ b/vendor/md5/md5.c
@@ -0,0 +1,291 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#ifndef HAVE_OPENSSL
+
+#include <string.h>
+
+#include "md5.h"
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z) (((x) ^ (y)) ^ (z))
+#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them in a
+ * properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned memory
+ * accesses is just an optimization. Nothing will break if it fails to detect
+ * a suitable architecture.
+ *
+ * Unfortunately, this optimization may be a C strict aliasing rules violation
+ * if the caller's data buffer has effective type that cannot be aliased by
+ * MD5_u32plus. In practice, this problem may occur if these MD5 routines are
+ * inlined into a calling function, or with future and dangerously advanced
+ * link-time optimizations. For the time being, keeping these MD5 routines in
+ * their own translation unit avoids the problem.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
+#define SET(n) \
+ (ctx->block[(n)] = \
+ (MD5_u32plus)ptr[(n) * 4] | \
+ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+ (ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update the bit
+ * counters. There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ const unsigned char *ptr;
+ MD5_u32plus a, b, c, d;
+ MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+ STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+ STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+ STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+ STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+ STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+ STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+ STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+ STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+ STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+ STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+ STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+ STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+ STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+ STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+ STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+ STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+ STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+ STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+ STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+ STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+ STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+ STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+ STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+ STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+ STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+ STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+ STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+ STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+ STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+ STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+ STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+ STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+ STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+ STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+ STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+ STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+ STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+ STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+ STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+ STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+ STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+ STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+ STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+ STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+ STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+ STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+ STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+ STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+ STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+ STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+ STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+ STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+ STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
+}
+
+void MD5_Init(MD5_CTX *ctx)
+{
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
+
+void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ MD5_u32plus saved_lo;
+ unsigned long used, available;
+
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += size >> 29;
+
+ used = saved_lo & 0x3f;
+
+ if (used) {
+ available = 64 - used;
+
+ if (size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if (size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
+}
+
+#define OUT(dst, src) \
+ (dst)[0] = (unsigned char)(src); \
+ (dst)[1] = (unsigned char)((src) >> 8); \
+ (dst)[2] = (unsigned char)((src) >> 16); \
+ (dst)[3] = (unsigned char)((src) >> 24);
+
+void MD5_Final(unsigned char *result, MD5_CTX *ctx)
+{
+ unsigned long used, available;
+
+ used = ctx->lo & 0x3f;
+
+ ctx->buffer[used++] = 0x80;
+
+ available = 64 - used;
+
+ if (available < 8) {
+ memset(&ctx->buffer[used], 0, available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
+
+ memset(&ctx->buffer[used], 0, available - 8);
+
+ ctx->lo <<= 3;
+ OUT(&ctx->buffer[56], ctx->lo)
+ OUT(&ctx->buffer[60], ctx->hi)
+
+ body(ctx, ctx->buffer, 64);
+
+ OUT(&result[0], ctx->a)
+ OUT(&result[4], ctx->b)
+ OUT(&result[8], ctx->c)
+ OUT(&result[12], ctx->d)
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif
diff --git a/vendor/md5/md5.h b/vendor/md5/md5.h
new file mode 100644
index 000000000..2da44bf35
--- /dev/null
+++ b/vendor/md5/md5.h
@@ -0,0 +1,45 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md5.c for more information.
+ */
+
+#ifdef HAVE_OPENSSL
+#include <openssl/md5.h>
+#elif !defined(_MD5_H)
+#define _MD5_H
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD5_u32plus;
+
+typedef struct {
+ MD5_u32plus lo, hi;
+ MD5_u32plus a, b, c, d;
+ unsigned char buffer[64];
+ MD5_u32plus block[16];
+} MD5_CTX;
+
+extern void MD5_Init(MD5_CTX *ctx);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
+extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
+
+#endif
diff --git a/vendor/sha2/sha2.c b/vendor/sha2/sha2.c
new file mode 100644
index 000000000..0fe4c375c
--- /dev/null
+++ b/vendor/sha2/sha2.c
@@ -0,0 +1,949 @@
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#define UNROLL_LOOPS /* Enable loops unrolling */
+#endif
+
+#include <string.h>
+
+#include "sha2.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
+
+#define UNPACK32(x, str) \
+{ \
+ *((str) + 3) = (uint8) ((x) ); \
+ *((str) + 2) = (uint8) ((x) >> 8); \
+ *((str) + 1) = (uint8) ((x) >> 16); \
+ *((str) + 0) = (uint8) ((x) >> 24); \
+}
+
+#define PACK32(str, x) \
+{ \
+ *(x) = ((uint32) *((str) + 3) ) \
+ | ((uint32) *((str) + 2) << 8) \
+ | ((uint32) *((str) + 1) << 16) \
+ | ((uint32) *((str) + 0) << 24); \
+}
+
+#define UNPACK64(x, str) \
+{ \
+ *((str) + 7) = (uint8) ((x) ); \
+ *((str) + 6) = (uint8) ((x) >> 8); \
+ *((str) + 5) = (uint8) ((x) >> 16); \
+ *((str) + 4) = (uint8) ((x) >> 24); \
+ *((str) + 3) = (uint8) ((x) >> 32); \
+ *((str) + 2) = (uint8) ((x) >> 40); \
+ *((str) + 1) = (uint8) ((x) >> 48); \
+ *((str) + 0) = (uint8) ((x) >> 56); \
+}
+
+#define PACK64(str, x) \
+{ \
+ *(x) = ((uint64) *((str) + 7) ) \
+ | ((uint64) *((str) + 6) << 8) \
+ | ((uint64) *((str) + 5) << 16) \
+ | ((uint64) *((str) + 4) << 24) \
+ | ((uint64) *((str) + 3) << 32) \
+ | ((uint64) *((str) + 2) << 40) \
+ | ((uint64) *((str) + 1) << 48) \
+ | ((uint64) *((str) + 0) << 56); \
+}
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+{ \
+ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ + SHA256_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA512_SCR(i) \
+{ \
+ w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
+ + SHA512_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+{ \
+ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha256_k[j] + w[j]; \
+ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
+{ \
+ t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha512_k[j] + w[j]; \
+ t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+uint32 sha224_h0[8] =
+ {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
+
+uint32 sha256_h0[8] =
+ {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+
+uint64 sha384_h0[8] =
+ {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
+
+uint64 sha512_h0[8] =
+ {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
+
+uint32 sha256_k[64] =
+ {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+uint64 sha512_k[80] =
+ {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
+
+/* SHA-256 functions */
+
+void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint32 w[64];
+ uint32 wv[8];
+ uint32 t1, t2;
+ const unsigned char *sub_block;
+ int i;
+
+#ifndef UNROLL_LOOPS
+ int j;
+#endif
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK32(&sub_block[j << 2], &w[j]);
+ }
+
+ for (j = 16; j < 64; j++) {
+ SHA256_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 64; j++) {
+ t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ + sha256_k[j] + w[j];
+ t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
+ PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
+ PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
+ PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
+ PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
+ PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
+ PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
+ PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
+
+ SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
+ SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
+ SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
+ SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
+ SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
+ SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
+ SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
+ SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
+ SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
+ SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
+ SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
+ SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
+ SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
+ SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
+ SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
+ SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
+ SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
+ SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
+ SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
+ SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
+ SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
+ SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
+ SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
+ SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
+ SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
+ SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
+ SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
+ SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
+ SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
+ SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
+ SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
+ SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
+ SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
+ SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
+ SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
+ SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
+ SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
+ SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
+ SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
+ SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
+ SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
+ SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
+ SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ sha256_ctx ctx;
+
+ sha256_init(&ctx);
+ sha256_update(&ctx, message, len);
+ sha256_final(&ctx, digest);
+}
+
+void sha256_init(sha256_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha256_h0[i];
+ }
+#else
+ ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
+ ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
+ ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
+ ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA256_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx, ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA256_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha256_final(sha256_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
+ < (ctx->len % SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 8; i++) {
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+ UNPACK32(ctx->h[7], &digest[28]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-512 functions */
+
+void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint64 w[80];
+ uint64 wv[8];
+ uint64 t1, t2;
+ const unsigned char *sub_block;
+ int i, j;
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 7);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK64(&sub_block[j << 3], &w[j]);
+ }
+
+ for (j = 16; j < 80; j++) {
+ SHA512_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 80; j++) {
+ t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ + sha512_k[j] + w[j];
+ t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
+ PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
+ PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
+ PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
+ PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
+ PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
+ PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
+ PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
+
+ SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
+ SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
+ SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
+ SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
+ SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
+ SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
+ SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
+ SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
+ SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
+ SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
+ SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
+ SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
+ SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
+ SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
+ SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
+ SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ j = 0;
+
+ do {
+ SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
+ SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
+ SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
+ SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
+ SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
+ SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
+ SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
+ SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
+ } while (j < 80);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void sha512(const unsigned char *message, unsigned int len,
+ unsigned char *digest)
+{
+ sha512_ctx ctx;
+
+ sha512_init(&ctx);
+ sha512_update(&ctx, message, len);
+ sha512_final(&ctx, digest);
+}
+
+void sha512_init(sha512_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha512_h0[i];
+ }
+#else
+ ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
+ ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
+ ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
+ ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha512_update(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA512_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA512_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA512_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha512_transf(ctx, ctx->block, 1);
+ sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA512_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void sha512_final(sha512_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
+ < (ctx->len % SHA512_BLOCK_SIZE));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 8; i++) {
+ UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ UNPACK64(ctx->h[0], &digest[ 0]);
+ UNPACK64(ctx->h[1], &digest[ 8]);
+ UNPACK64(ctx->h[2], &digest[16]);
+ UNPACK64(ctx->h[3], &digest[24]);
+ UNPACK64(ctx->h[4], &digest[32]);
+ UNPACK64(ctx->h[5], &digest[40]);
+ UNPACK64(ctx->h[6], &digest[48]);
+ UNPACK64(ctx->h[7], &digest[56]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-384 functions */
+
+void sha384(const unsigned char *message, unsigned int len,
+ unsigned char *digest)
+{
+ sha384_ctx ctx;
+
+ sha384_init(&ctx);
+ sha384_update(&ctx, message, len);
+ sha384_final(&ctx, digest);
+}
+
+void sha384_init(sha384_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha384_h0[i];
+ }
+#else
+ ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
+ ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
+ ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
+ ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha384_update(sha384_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA384_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA384_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA384_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha512_transf(ctx, ctx->block, 1);
+ sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA384_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void sha384_final(sha384_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
+ < (ctx->len % SHA384_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 6; i++) {
+ UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ UNPACK64(ctx->h[0], &digest[ 0]);
+ UNPACK64(ctx->h[1], &digest[ 8]);
+ UNPACK64(ctx->h[2], &digest[16]);
+ UNPACK64(ctx->h[3], &digest[24]);
+ UNPACK64(ctx->h[4], &digest[32]);
+ UNPACK64(ctx->h[5], &digest[40]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-224 functions */
+
+void sha224(const unsigned char *message, unsigned int len,
+ unsigned char *digest)
+{
+ sha224_ctx ctx;
+
+ sha224_init(&ctx);
+ sha224_update(&ctx, message, len);
+ sha224_final(&ctx, digest);
+}
+
+void sha224_init(sha224_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha224_h0[i];
+ }
+#else
+ ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
+ ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
+ ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
+ ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha224_update(sha224_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA224_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA224_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA224_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx, ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA224_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha224_final(sha224_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
+ < (ctx->len % SHA224_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 7; i++) {
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+#endif /* !UNROLL_LOOPS */
+}
+
+#ifdef TEST_VECTORS
+
+/* FIPS 180-2 Validation tests */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void test(const char *vector, unsigned char *digest,
+ unsigned int digest_size)
+{
+ char output[2 * SHA512_DIGEST_SIZE + 1];
+ int i;
+
+ output[2 * digest_size] = '\0';
+
+ for (i = 0; i < (int) digest_size ; i++) {
+ sprintf(output + 2 * i, "%02x", digest[i]);
+ }
+
+ printf("H: %s\n", output);
+ if (strcmp(vector, output)) {
+ fprintf(stderr, "Test failed.\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(void)
+{
+ static const char *vectors[4][3] =
+ { /* SHA-224 */
+ {
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
+ },
+ /* SHA-256 */
+ {
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
+ },
+ /* SHA-384 */
+ {
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
+ "8086072ba1e7cc2358baeca134c825a7",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
+ "fcc7c71a557e2db966c3e9fa91746039",
+ "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
+ "07b8b3dc38ecc4ebae97ddd87f3d8985",
+ },
+ /* SHA-512 */
+ {
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
+ }
+ };
+
+ static const char message1[] = "abc";
+ static const char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
+ "jkijkljklmklmnlmnomnopnopq";
+ static const char message2b[] = "abcdefghbcdefghicdefghijdefghijkefghij"
+ "klfghijklmghijklmnhijklmnoijklmnopjklm"
+ "nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+ unsigned char *message3;
+ unsigned int message3_len = 1000000;
+ unsigned char digest[SHA512_DIGEST_SIZE];
+
+ message3 = malloc(message3_len);
+ if (message3 == NULL) {
+ fprintf(stderr, "Can't allocate memory\n");
+ return -1;
+ }
+ memset(message3, 'a', message3_len);
+
+ printf("SHA-2 FIPS 180-2 Validation tests\n\n");
+ printf("SHA-224 Test vectors\n");
+
+ sha224((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
+ sha224((const unsigned char *) message2a, strlen(message2a), digest);
+ test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
+ sha224(message3, message3_len, digest);
+ test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-256 Test vectors\n");
+
+ sha256((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
+ sha256((const unsigned char *) message2a, strlen(message2a), digest);
+ test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
+ sha256(message3, message3_len, digest);
+ test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-384 Test vectors\n");
+
+ sha384((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
+ sha384((const unsigned char *)message2b, strlen(message2b), digest);
+ test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
+ sha384(message3, message3_len, digest);
+ test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-512 Test vectors\n");
+
+ sha512((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
+ sha512((const unsigned char *) message2b, strlen(message2b), digest);
+ test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
+ sha512(message3, message3_len, digest);
+ test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
+ printf("\n");
+
+ printf("All tests passed.\n");
+
+ return 0;
+}
+
+#endif /* TEST_VECTORS */
+
diff --git a/vendor/sha2/sha2.h b/vendor/sha2/sha2.h
new file mode 100644
index 000000000..60f52e34d
--- /dev/null
+++ b/vendor/sha2/sha2.h
@@ -0,0 +1,108 @@
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SHA2_H
+#define SHA2_H
+
+#define SHA224_DIGEST_SIZE ( 224 / 8)
+#define SHA256_DIGEST_SIZE ( 256 / 8)
+#define SHA384_DIGEST_SIZE ( 384 / 8)
+#define SHA512_DIGEST_SIZE ( 512 / 8)
+
+#define SHA256_BLOCK_SIZE ( 512 / 8)
+#define SHA512_BLOCK_SIZE (1024 / 8)
+#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE
+#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE
+
+#ifndef SHA2_TYPES
+#define SHA2_TYPES
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA256_BLOCK_SIZE];
+ uint32 h[8];
+} sha256_ctx;
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA512_BLOCK_SIZE];
+ uint64 h[8];
+} sha512_ctx;
+
+typedef sha512_ctx sha384_ctx;
+typedef sha256_ctx sha224_ctx;
+
+void sha224_init(sha224_ctx *ctx);
+void sha224_update(sha224_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha224_final(sha224_ctx *ctx, unsigned char *digest);
+void sha224(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+void sha256_init(sha256_ctx * ctx);
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha256_final(sha256_ctx *ctx, unsigned char *digest);
+void sha256(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+void sha384_init(sha384_ctx *ctx);
+void sha384_update(sha384_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha384_final(sha384_ctx *ctx, unsigned char *digest);
+void sha384(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+void sha512_init(sha512_ctx *ctx);
+void sha512_update(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha512_final(sha512_ctx *ctx, unsigned char *digest);
+void sha512(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !SHA2_H */
+
diff --git a/vendor/update b/vendor/update
new file mode 100755
index 000000000..91c88e2ae
--- /dev/null
+++ b/vendor/update
@@ -0,0 +1,111 @@
+#!/usr/bin/env perl
+#
+# (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.
+
+use v5.26.0;
+use strict;
+use warnings FATAL => qw(all);
+
+use File::Basename qw(basename dirname);
+use File::Copy qw(move);
+use File::Spec::Functions qw(abs2rel catdir catfile);
+use File::Temp qw(tempdir);
+use FindBin qw($RealDir);
+use File::Path qw(mkpath);
+use POSIX qw(strftime);
+use TOML qw(from_toml);
+
+use constant {
+ CC_BOLD => -t STDOUT ? "\e[1m" : '',
+ CC_RESET => -t STDOUT ? "\e[0m" : '',
+ CC_GREEN => -t STDOUT ? "\e[1;32m" : '',
+ CC_RED => -t STDOUT ? "\e[1;31m" : '',
+};
+
+sub execute(@) {
+ say "${\CC_BOLD}\$${\CC_RESET} @_";
+ return system @_;
+}
+
+sub print_error {
+ print STDERR "${\CC_BOLD}Error:${\CC_RESET} ";
+ for my $line (@_) {
+ say STDERR $line;
+ }
+ exit 1;
+}
+
+my $config = catfile $RealDir, 'update.toml';
+open(my $fh, $config) or print_error "unable to read $config: $!";
+my $contents = do { local $/; <$fh> };
+close $fh;
+
+my ($data, $error) = from_toml $contents;
+print_error "unable to parse $config: $!" if $error;
+
+while (my ($name, $info) = each %{$data}) {
+ say "Updating ${\CC_GREEN}$name${\CC_RESET} ...";
+
+ my $unpackdir = File::Temp->newdir;
+ my $vendordir = catdir $RealDir, $name;
+ my $success = 0;
+ if (defined $info->{git}) {
+ my @extra_args;
+ push @extra_args, '--branch', $info->{branch} if defined $info->{branch};
+ $success ||= execute 'git', 'clone', @extra_args, $info->{git}, $unpackdir;
+ chomp(my $tag = `git -C $unpackdir describe --abbrev=0 --tags HEAD 2>/dev/null`) unless $success;
+ $success ||= execute 'git', '-C', $unpackdir, 'checkout', $tag if $tag;
+ chomp($info->{version} = `git -C $unpackdir describe --always --tags HEAD 2>/dev/null`);
+ if (defined $info->{patches}) {
+ my $patches = catfile($unpackdir, $info->{patches});
+ for my $patch (glob $patches) {
+ $success |= execute 'git', '-C', $unpackdir, 'apply', $patch;
+ }
+ }
+ } elsif (defined $info->{tarball}) {
+ my $tarball = catfile $unpackdir, basename $info->{tarball};
+ $success ||= execute 'wget', '--output-document', $tarball, $info->{tarball};
+ $success ||= execute 'tar', 'fx', $tarball, '-C', $unpackdir, '--strip-components', 1;
+ } else {
+ print_error "unable to update $name; no git or tarball specified!";
+ }
+ print_error "unable to update $name: download failed!" if $success;
+
+ unlink $vendordir;
+ my $glob = $info->{files} or print_error "unable to update $name: no file glob specified!";
+ for my $file (glob catfile $unpackdir, $glob) {
+ my $pathname = abs2rel $file, $unpackdir;
+ for (my $i = 0; $i < ($info->{depth} // 0); ++$i) {
+ $pathname =~ s/[^\/]+\///;
+ }
+ my $filename = catfile $vendordir, $pathname;
+ my $dirname = dirname $filename;
+ mkdir $dirname, 0750 or print_error "unable to create $dirname: $!." unless -e $dirname;
+ move $file, $filename;
+ }
+}
+
+my $readme = catfile $RealDir, 'README.md';
+open($fh, $readme) or print_error "unable to read $readme: $!";
+$contents = do { local $/; <$fh> };
+close $fh;
+
+open($fh, '>', $readme) or print_error "unable to write $readme: $!";
+print $fh $contents =~ s/\n\#\#.*//rs;
+for my $name (sort keys %{$data}) {
+ my $info = $data->{$name};
+ printf $fh "\n## %s\n\n", $name;
+ printf $fh "**Author** &mdash; [%s](mailto:%s)\n\n", $info->{author}, $info->{email} if $info->{email};
+ printf $fh "**Author** &mdash; %s\n\n", $info->{author} unless $info->{email};
+ printf $fh "**License** &mdash; %s\n\n", $info->{license};
+ printf $fh "**Version** &mdash; %s\n\n", $info->{version};
+ my $website = $info->{website} // $info->{git};
+ printf $fh "**Website** &mdash; [%s](%s)\n", $website, $website;
+}
+close $fh;
diff --git a/vendor/update.toml b/vendor/update.toml
new file mode 100644
index 000000000..cee9fbd9e
--- /dev/null
+++ b/vendor/update.toml
@@ -0,0 +1,34 @@
+[bcrypt]
+author = "Solar Designer"
+email = "solar@openwall.com"
+files = "crypt_blowfish.[ch]"
+license = "Public Domain"
+tarball = "https://www.openwall.com/crypt/crypt_blowfish-1.3.tar.gz"
+version = "v1.3"
+website = "https://www.openwall.com/crypt/"
+
+[md5]
+author = "Solar Designer"
+depth = 1
+email = "solar@openwall.com"
+files = "{LICENSE,md5/md5.[ch]}"
+license = "Cut-down BSD License"
+tarball = "https://www.openwall.com/blists/blists-2.0.tar.gz"
+version = "v2.0"
+website = "https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5"
+
+[sha2]
+author = "Olivier Gay"
+email = "olivier.gay@a3.epfl.ch"
+files = "sha2.[ch]"
+license = "3-clause BSD License"
+tarball = "http://www.ouah.org/ogay/sha2/sha2.tar.gz"
+version = "2007-02-02"
+website = "http://www.ouah.org/ogay/sha2/"
+
+[yyjson]
+author = "Yaoyuan Guo"
+depth = 1
+git = "https://github.com/ibireme/yyjson"
+files = "{LICENSE,src/yyjson.[ch]}"
+license = "MIT License"
diff --git a/vendor/yyjson/LICENSE b/vendor/yyjson/LICENSE
new file mode 100644
index 000000000..a09bff355
--- /dev/null
+++ b/vendor/yyjson/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 YaoYuan <ibireme@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/yyjson/yyjson.c b/vendor/yyjson/yyjson.c
new file mode 100644
index 000000000..16ecbacf5
--- /dev/null
+++ b/vendor/yyjson/yyjson.c
@@ -0,0 +1,9568 @@
+/*==============================================================================
+ Copyright (c) 2020 YaoYuan <ibireme@gmail.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ *============================================================================*/
+
+#include "yyjson.h"
+#include <math.h>
+
+
+
+/*==============================================================================
+ * Warning Suppress
+ *============================================================================*/
+
+#if defined(__clang__)
+# pragma clang diagnostic ignored "-Wunused-function"
+# pragma clang diagnostic ignored "-Wunused-parameter"
+# pragma clang diagnostic ignored "-Wunused-label"
+# pragma clang diagnostic ignored "-Wunused-macros"
+# pragma clang diagnostic ignored "-Wunused-variable"
+#elif defined(__GNUC__)
+# pragma GCC diagnostic ignored "-Wunused-function"
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+# pragma GCC diagnostic ignored "-Wunused-label"
+# pragma GCC diagnostic ignored "-Wunused-macros"
+# pragma GCC diagnostic ignored "-Wunused-variable"
+#elif defined(_MSC_VER)
+# pragma warning(disable:4100) /* unreferenced formal parameter */
+# pragma warning(disable:4101) /* unreferenced variable */
+# pragma warning(disable:4102) /* unreferenced label */
+# pragma warning(disable:4127) /* conditional expression is constant */
+# pragma warning(disable:4706) /* assignment within conditional expression */
+#endif
+
+
+
+/*==============================================================================
+ * Version
+ *============================================================================*/
+
+uint32_t yyjson_version(void) {
+ return YYJSON_VERSION_HEX;
+}
+
+
+
+/*==============================================================================
+ * Flags
+ *============================================================================*/
+
+/* msvc intrinsic */
+#if YYJSON_MSC_VER >= 1400
+# include <intrin.h>
+# if defined(_M_AMD64) || defined(_M_ARM64)
+# define MSC_HAS_BIT_SCAN_64 1
+# pragma intrinsic(_BitScanForward64)
+# pragma intrinsic(_BitScanReverse64)
+# else
+# define MSC_HAS_BIT_SCAN_64 0
+# endif
+# if defined(_M_AMD64) || defined(_M_ARM64) || \
+ defined(_M_IX86) || defined(_M_ARM)
+# define MSC_HAS_BIT_SCAN 1
+# pragma intrinsic(_BitScanForward)
+# pragma intrinsic(_BitScanReverse)
+# else
+# define MSC_HAS_BIT_SCAN 0
+# endif
+# if defined(_M_AMD64)
+# define MSC_HAS_UMUL128 1
+# pragma intrinsic(_umul128)
+# else
+# define MSC_HAS_UMUL128 0
+# endif
+#else
+# define MSC_HAS_BIT_SCAN_64 0
+# define MSC_HAS_BIT_SCAN 0
+# define MSC_HAS_UMUL128 0
+#endif
+
+/* gcc builtin */
+#if yyjson_has_builtin(__builtin_clzll) || yyjson_gcc_available(3, 4, 0)
+# define GCC_HAS_CLZLL 1
+#else
+# define GCC_HAS_CLZLL 0
+#endif
+
+#if yyjson_has_builtin(__builtin_ctzll) || yyjson_gcc_available(3, 4, 0)
+# define GCC_HAS_CTZLL 1
+#else
+# define GCC_HAS_CTZLL 0
+#endif
+
+/* int128 type */
+#if defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16) && \
+ (defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER))
+# define YYJSON_HAS_INT128 1
+#else
+# define YYJSON_HAS_INT128 0
+#endif
+
+/* IEEE 754 floating-point binary representation */
+#if defined(__STDC_IEC_559__) || defined(__STDC_IEC_60559_BFP__)
+# define YYJSON_HAS_IEEE_754 1
+#elif (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_DIG == 15) && \
+ (DBL_MIN_EXP == -1021) && (DBL_MAX_EXP == 1024) && \
+ (DBL_MIN_10_EXP == -307) && (DBL_MAX_10_EXP == 308)
+# define YYJSON_HAS_IEEE_754 1
+#else
+# define YYJSON_HAS_IEEE_754 0
+#endif
+
+/*
+ Correct rounding in double number computations.
+
+ On the x86 architecture, some compilers may use x87 FPU instructions for
+ floating-point arithmetic. The x87 FPU loads all floating point number as
+ 80-bit double-extended precision internally, then rounds the result to original
+ precision, which may produce inaccurate results. For a more detailed
+ explanation, see the paper: https://arxiv.org/abs/cs/0701192
+
+ Here are some examples of double precision calculation error:
+
+ 2877.0 / 1e6 == 0.002877, but x87 returns 0.0028770000000000002
+ 43683.0 * 1e21 == 4.3683e25, but x87 returns 4.3683000000000004e25
+
+ Here are some examples of compiler flags to generate x87 instructions on x86:
+
+ clang -m32 -mno-sse
+ gcc/icc -m32 -mfpmath=387
+ msvc /arch:SSE or /arch:IA32
+
+ If we are sure that there's no similar error described above, we can define the
+ YYJSON_DOUBLE_MATH_CORRECT as 1 to enable the fast path calculation. This is
+ not an accurate detection, it's just try to avoid the error at compile-time.
+ An accurate detection can be done at run-time:
+
+ bool is_double_math_correct(void) {
+ volatile double r = 43683.0;
+ r *= 1e21;
+ return r == 4.3683e25;
+ }
+
+ See also: utils.h in https://github.com/google/double-conversion/
+ */
+#if !defined(FLT_EVAL_METHOD) && defined(__FLT_EVAL_METHOD__)
+# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#endif
+
+#if defined(FLT_EVAL_METHOD) && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1
+# define YYJSON_DOUBLE_MATH_CORRECT 0
+#elif defined(i386) || defined(__i386) || defined(__i386__) || \
+ defined(_X86_) || defined(__X86__) || defined(_M_IX86) || \
+ defined(__I86__) || defined(__IA32__) || defined(__THW_INTEL)
+# if (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 2) || \
+ (defined(__SSE2_MATH__) && __SSE2_MATH__)
+# define YYJSON_DOUBLE_MATH_CORRECT 1
+# else
+# define YYJSON_DOUBLE_MATH_CORRECT 0
+# endif
+#elif defined(__mc68000__) || defined(__pnacl__) || defined(__native_client__)
+# define YYJSON_DOUBLE_MATH_CORRECT 0
+#else
+# define YYJSON_DOUBLE_MATH_CORRECT 1
+#endif
+
+/* endian */
+#if yyjson_has_include(<sys/types.h>)
+# include <sys/types.h> /* POSIX */
+#endif
+#if yyjson_has_include(<endian.h>)
+# include <endian.h> /* Linux */
+#elif yyjson_has_include(<sys/endian.h>)
+# include <sys/endian.h> /* BSD, Android */
+#elif yyjson_has_include(<machine/endian.h>)
+# include <machine/endian.h> /* BSD, Darwin */
+#endif
+
+#define YYJSON_BIG_ENDIAN 4321
+#define YYJSON_LITTLE_ENDIAN 1234
+
+#if defined(BYTE_ORDER) && BYTE_ORDER
+# if defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+# elif defined(LITTLE_ENDIAN) && (BYTE_ORDER == LITTLE_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+# endif
+
+#elif defined(__BYTE_ORDER) && __BYTE_ORDER
+# if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+# elif defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+# endif
+
+#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__
+# if defined(__ORDER_BIG_ENDIAN__) && \
+ (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+# elif defined(__ORDER_LITTLE_ENDIAN__) && \
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+# endif
+
+#elif (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \
+ defined(__i386) || defined(__i386__) || \
+ defined(_X86_) || defined(__X86__) || \
+ defined(_M_IX86) || defined(__THW_INTEL__) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(__amd64) || defined(__amd64__) || \
+ defined(_M_AMD64) || defined(_M_X64) || \
+ defined(_M_ARM) || defined(_M_ARM64) || \
+ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
+ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
+ defined(__EMSCRIPTEN__) || defined(__wasm__) || \
+ defined(__loongarch__)
+# define YYJSON_ENDIAN YYJSON_LITTLE_ENDIAN
+
+#elif (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \
+ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \
+ defined(__or1k__) || defined(__OR1K__)
+# define YYJSON_ENDIAN YYJSON_BIG_ENDIAN
+
+#else
+# define YYJSON_ENDIAN 0 /* unknown endian, detect at run-time */
+#endif
+
+/*
+ This macro controls how yyjson handles unaligned memory accesses.
+
+ By default, yyjson uses `memcpy()` for memory copying. This takes advantage of
+ the compiler's automatic optimizations to generate unaligned memory access
+ instructions when the target architecture supports it.
+
+ However, for some older compilers or architectures where `memcpy()` isn't
+ optimized well and may generate unnecessary function calls, consider defining
+ this macro as 1. In such cases, yyjson switches to manual byte-by-byte access,
+ potentially improving performance. An example of the generated assembly code on
+ the ARM platform can be found here: https://godbolt.org/z/334jjhxPT
+
+ As this flag has already been enabled for some common architectures in the
+ following code, users typically don't need to manually specify it. If users are
+ unsure about it, please review the generated assembly code or perform actual
+ benchmark to make an informed decision.
+ */
+#ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
+# if defined(__ia64) || defined(_IA64) || defined(__IA64__) || \
+ defined(__ia64__) || defined(_M_IA64) || defined(__itanium__)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* Itanium */
+# elif (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) && \
+ (defined(__GNUC__) || defined(__clang__)) && \
+ (!defined(__ARM_FEATURE_UNALIGNED) || !__ARM_FEATURE_UNALIGNED)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* ARM */
+# elif defined(__sparc) || defined(__sparc__)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* SPARC */
+# elif defined(__mips) || defined(__mips__) || defined(__MIPS__)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* MIPS */
+# elif defined(__m68k__) || defined(M68000)
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 1 /* M68K */
+# else
+# define YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS 0
+# endif
+#endif
+
+/*
+ Estimated initial ratio of the JSON data (data_size / value_count).
+ For example:
+
+ data: {"id":12345678,"name":"Harry"}
+ data_size: 30
+ value_count: 5
+ ratio: 6
+
+ yyjson uses dynamic memory with a growth factor of 1.5 when reading and writing
+ JSON, the ratios below are used to determine the initial memory size.
+
+ A too large ratio will waste memory, and a too small ratio will cause multiple
+ memory growths and degrade performance. Currently, these ratios are generated
+ with some commonly used JSON datasets.
+ */
+#define YYJSON_READER_ESTIMATED_PRETTY_RATIO 16
+#define YYJSON_READER_ESTIMATED_MINIFY_RATIO 6
+#define YYJSON_WRITER_ESTIMATED_PRETTY_RATIO 32
+#define YYJSON_WRITER_ESTIMATED_MINIFY_RATIO 18
+
+/* The initial and maximum size of the memory pool's chunk in yyjson_mut_doc. */
+#define YYJSON_MUT_DOC_STR_POOL_INIT_SIZE 0x100
+#define YYJSON_MUT_DOC_STR_POOL_MAX_SIZE 0x10000000
+#define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val))
+#define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val))
+
+/* The minimum size of the dynamic allocator's chunk. */
+#define YYJSON_ALC_DYN_MIN_SIZE 0x1000
+
+/* Default value for compile-time options. */
+#ifndef YYJSON_DISABLE_READER
+#define YYJSON_DISABLE_READER 0
+#endif
+#ifndef YYJSON_DISABLE_WRITER
+#define YYJSON_DISABLE_WRITER 0
+#endif
+#ifndef YYJSON_DISABLE_UTILS
+#define YYJSON_DISABLE_UTILS 0
+#endif
+#ifndef YYJSON_DISABLE_FAST_FP_CONV
+#define YYJSON_DISABLE_FAST_FP_CONV 0
+#endif
+#ifndef YYJSON_DISABLE_NON_STANDARD
+#define YYJSON_DISABLE_NON_STANDARD 0
+#endif
+#ifndef YYJSON_DISABLE_UTF8_VALIDATION
+#define YYJSON_DISABLE_UTF8_VALIDATION 0
+#endif
+
+
+
+/*==============================================================================
+ * Macros
+ *============================================================================*/
+
+/* Macros used for loop unrolling and other purpose. */
+#define repeat2(x) { x x }
+#define repeat3(x) { x x x }
+#define repeat4(x) { x x x x }
+#define repeat8(x) { x x x x x x x x }
+#define repeat16(x) { x x x x x x x x x x x x x x x x }
+
+#define repeat2_incr(x) { x(0) x(1) }
+#define repeat4_incr(x) { x(0) x(1) x(2) x(3) }
+#define repeat8_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) }
+#define repeat16_incr(x) { x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \
+ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) }
+
+#define repeat_in_1_18(x) { x(1) x(2) x(3) x(4) x(5) x(6) x(7) x(8) \
+ x(9) x(10) x(11) x(12) x(13) x(14) x(15) x(16) \
+ x(17) x(18) }
+
+/* Macros used to provide branch prediction information for compiler. */
+#undef likely
+#define likely(x) yyjson_likely(x)
+#undef unlikely
+#define unlikely(x) yyjson_unlikely(x)
+
+/* Macros used to provide inline information for compiler. */
+#undef static_inline
+#define static_inline static yyjson_inline
+#undef static_noinline
+#define static_noinline static yyjson_noinline
+
+/* Macros for min and max. */
+#undef yyjson_min
+#define yyjson_min(x, y) ((x) < (y) ? (x) : (y))
+#undef yyjson_max
+#define yyjson_max(x, y) ((x) > (y) ? (x) : (y))
+
+/* Used to write u64 literal for C89 which doesn't support "ULL" suffix. */
+#undef U64
+#define U64(hi, lo) ((((u64)hi##UL) << 32U) + lo##UL)
+
+/* Used to cast away (remove) const qualifier. */
+#define constcast(type) (type)(void *)(size_t)(const void *)
+
+/* flag test */
+#define has_read_flag(_flag) unlikely(read_flag_eq(flg, YYJSON_READ_##_flag))
+#define has_write_flag(_flag) unlikely(write_flag_eq(flg, YYJSON_WRITE_##_flag))
+
+static_inline bool read_flag_eq(yyjson_read_flag flg, yyjson_read_flag chk) {
+#if YYJSON_DISABLE_NON_STANDARD
+ if (chk == YYJSON_READ_ALLOW_INF_AND_NAN ||
+ chk == YYJSON_READ_ALLOW_COMMENTS ||
+ chk == YYJSON_READ_ALLOW_TRAILING_COMMAS ||
+ chk == YYJSON_READ_ALLOW_INVALID_UNICODE)
+ return false; /* this should be evaluated at compile-time */
+#endif
+ return (flg & chk) != 0;
+}
+
+static_inline bool write_flag_eq(yyjson_write_flag flg, yyjson_write_flag chk) {
+#if YYJSON_DISABLE_NON_STANDARD
+ if (chk == YYJSON_WRITE_ALLOW_INF_AND_NAN ||
+ chk == YYJSON_WRITE_ALLOW_INVALID_UNICODE)
+ return false; /* this should be evaluated at compile-time */
+#endif
+ return (flg & chk) != 0;
+}
+
+
+
+/*==============================================================================
+ * Integer Constants
+ *============================================================================*/
+
+/* U64 constant values */
+#undef U64_MAX
+#define U64_MAX U64(0xFFFFFFFF, 0xFFFFFFFF)
+#undef I64_MAX
+#define I64_MAX U64(0x7FFFFFFF, 0xFFFFFFFF)
+#undef USIZE_MAX
+#define USIZE_MAX ((usize)(~(usize)0))
+
+/* Maximum number of digits for reading u32/u64/usize safety (not overflow). */
+#undef U32_SAFE_DIG
+#define U32_SAFE_DIG 9 /* u32 max is 4294967295, 10 digits */
+#undef U64_SAFE_DIG
+#define U64_SAFE_DIG 19 /* u64 max is 18446744073709551615, 20 digits */
+#undef USIZE_SAFE_DIG
+#define USIZE_SAFE_DIG (sizeof(usize) == 8 ? U64_SAFE_DIG : U32_SAFE_DIG)
+
+
+
+/*==============================================================================
+ * IEEE-754 Double Number Constants
+ *============================================================================*/
+
+/* Inf raw value (positive) */
+#define F64_RAW_INF U64(0x7FF00000, 0x00000000)
+
+/* NaN raw value (quiet NaN, no payload, no sign) */
+#if defined(__hppa__) || (defined(__mips__) && !defined(__mips_nan2008))
+#define F64_RAW_NAN U64(0x7FF7FFFF, 0xFFFFFFFF)
+#else
+#define F64_RAW_NAN U64(0x7FF80000, 0x00000000)
+#endif
+
+/* double number bits */
+#define F64_BITS 64
+
+/* double number exponent part bits */
+#define F64_EXP_BITS 11
+
+/* double number significand part bits */
+#define F64_SIG_BITS 52
+
+/* double number significand part bits (with 1 hidden bit) */
+#define F64_SIG_FULL_BITS 53
+
+/* double number significand bit mask */
+#define F64_SIG_MASK U64(0x000FFFFF, 0xFFFFFFFF)
+
+/* double number exponent bit mask */
+#define F64_EXP_MASK U64(0x7FF00000, 0x00000000)
+
+/* double number exponent bias */
+#define F64_EXP_BIAS 1023
+
+/* double number significant digits count in decimal */
+#define F64_DEC_DIG 17
+
+/* max significant digits count in decimal when reading double number */
+#define F64_MAX_DEC_DIG 768
+
+/* maximum decimal power of double number (1.7976931348623157e308) */
+#define F64_MAX_DEC_EXP 308
+
+/* minimum decimal power of double number (4.9406564584124654e-324) */
+#define F64_MIN_DEC_EXP (-324)
+
+/* maximum binary power of double number */
+#define F64_MAX_BIN_EXP 1024
+
+/* minimum binary power of double number */
+#define F64_MIN_BIN_EXP (-1021)
+
+
+
+/*==============================================================================
+ * Types
+ *============================================================================*/
+
+/** Type define for primitive types. */
+typedef float f32;
+typedef double f64;
+typedef int8_t i8;
+typedef uint8_t u8;
+typedef int16_t i16;
+typedef uint16_t u16;
+typedef int32_t i32;
+typedef uint32_t u32;
+typedef int64_t i64;
+typedef uint64_t u64;
+typedef size_t usize;
+
+/** 128-bit integer, used by floating-point number reader and writer. */
+#if YYJSON_HAS_INT128
+__extension__ typedef __int128 i128;
+__extension__ typedef unsigned __int128 u128;
+#endif
+
+/** 16/32/64-bit vector */
+typedef struct v16 { char c[2]; } v16;
+typedef struct v32 { char c[4]; } v32;
+typedef struct v64 { char c[8]; } v64;
+
+/** 16/32/64-bit vector union */
+typedef union v16_uni { v16 v; u16 u; } v16_uni;
+typedef union v32_uni { v32 v; u32 u; } v32_uni;
+typedef union v64_uni { v64 v; u64 u; } v64_uni;
+
+
+
+/*==============================================================================
+ * Load/Store Utils
+ *============================================================================*/
+
+#if YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
+
+#define byte_move_idx(x) ((char *)dst)[x] = ((const char *)src)[x];
+
+static_inline void byte_copy_2(void *dst, const void *src) {
+ repeat2_incr(byte_move_idx)
+}
+
+static_inline void byte_copy_4(void *dst, const void *src) {
+ repeat4_incr(byte_move_idx)
+}
+
+static_inline void byte_copy_8(void *dst, const void *src) {
+ repeat8_incr(byte_move_idx)
+}
+
+static_inline void byte_copy_16(void *dst, const void *src) {
+ repeat16_incr(byte_move_idx)
+}
+
+static_inline void byte_move_2(void *dst, const void *src) {
+ repeat2_incr(byte_move_idx)
+}
+
+static_inline void byte_move_4(void *dst, const void *src) {
+ repeat4_incr(byte_move_idx)
+}
+
+static_inline void byte_move_8(void *dst, const void *src) {
+ repeat8_incr(byte_move_idx)
+}
+
+static_inline void byte_move_16(void *dst, const void *src) {
+ repeat16_incr(byte_move_idx)
+}
+
+static_inline bool byte_match_2(void *buf, const char *pat) {
+ return
+ ((char *)buf)[0] == ((const char *)pat)[0] &&
+ ((char *)buf)[1] == ((const char *)pat)[1];
+}
+
+static_inline bool byte_match_4(void *buf, const char *pat) {
+ return
+ ((char *)buf)[0] == ((const char *)pat)[0] &&
+ ((char *)buf)[1] == ((const char *)pat)[1] &&
+ ((char *)buf)[2] == ((const char *)pat)[2] &&
+ ((char *)buf)[3] == ((const char *)pat)[3];
+}
+
+static_inline u16 byte_load_2(const void *src) {
+ v16_uni uni;
+ uni.v.c[0] = ((const char *)src)[0];
+ uni.v.c[1] = ((const char *)src)[1];
+ return uni.u;
+}
+
+static_inline u32 byte_load_3(const void *src) {
+ v32_uni uni;
+ uni.v.c[0] = ((const char *)src)[0];
+ uni.v.c[1] = ((const char *)src)[1];
+ uni.v.c[2] = ((const char *)src)[2];
+ uni.v.c[3] = 0;
+ return uni.u;
+}
+
+static_inline u32 byte_load_4(const void *src) {
+ v32_uni uni;
+ uni.v.c[0] = ((const char *)src)[0];
+ uni.v.c[1] = ((const char *)src)[1];
+ uni.v.c[2] = ((const char *)src)[2];
+ uni.v.c[3] = ((const char *)src)[3];
+ return uni.u;
+}
+
+#undef byte_move_expr
+
+#else
+
+static_inline void byte_copy_2(void *dst, const void *src) {
+ memcpy(dst, src, 2);
+}
+
+static_inline void byte_copy_4(void *dst, const void *src) {
+ memcpy(dst, src, 4);
+}
+
+static_inline void byte_copy_8(void *dst, const void *src) {
+ memcpy(dst, src, 8);
+}
+
+static_inline void byte_copy_16(void *dst, const void *src) {
+ memcpy(dst, src, 16);
+}
+
+static_inline void byte_move_2(void *dst, const void *src) {
+ u16 tmp;
+ memcpy(&tmp, src, 2);
+ memcpy(dst, &tmp, 2);
+}
+
+static_inline void byte_move_4(void *dst, const void *src) {
+ u32 tmp;
+ memcpy(&tmp, src, 4);
+ memcpy(dst, &tmp, 4);
+}
+
+static_inline void byte_move_8(void *dst, const void *src) {
+ u64 tmp;
+ memcpy(&tmp, src, 8);
+ memcpy(dst, &tmp, 8);
+}
+
+static_inline void byte_move_16(void *dst, const void *src) {
+ char *pdst = (char *)dst;
+ const char *psrc = (const char *)src;
+ u64 tmp1, tmp2;
+ memcpy(&tmp1, psrc, 8);
+ memcpy(&tmp2, psrc + 8, 8);
+ memcpy(pdst, &tmp1, 8);
+ memcpy(pdst + 8, &tmp2, 8);
+}
+
+static_inline bool byte_match_2(void *buf, const char *pat) {
+ v16_uni u1, u2;
+ memcpy(&u1, buf, 2);
+ memcpy(&u2, pat, 2);
+ return u1.u == u2.u;
+}
+
+static_inline bool byte_match_4(void *buf, const char *pat) {
+ v32_uni u1, u2;
+ memcpy(&u1, buf, 4);
+ memcpy(&u2, pat, 4);
+ return u1.u == u2.u;
+}
+
+static_inline u16 byte_load_2(const void *src) {
+ v16_uni uni;
+ memcpy(&uni, src, 2);
+ return uni.u;
+}
+
+static_inline u32 byte_load_3(const void *src) {
+ v32_uni uni;
+ memcpy(&uni, src, 2);
+ uni.v.c[2] = ((const char *)src)[2];
+ uni.v.c[3] = 0;
+ return uni.u;
+}
+
+static_inline u32 byte_load_4(const void *src) {
+ v32_uni uni;
+ memcpy(&uni, src, 4);
+ return uni.u;
+}
+
+#endif
+
+
+
+/*==============================================================================
+ * Number Utils
+ * These functions are used to detect and convert NaN and Inf numbers.
+ *============================================================================*/
+
+/** Convert raw binary to double. */
+static_inline f64 f64_from_raw(u64 u) {
+ /* use memcpy to avoid violating the strict aliasing rule */
+ f64 f;
+ memcpy(&f, &u, 8);
+ return f;
+}
+
+/** Convert double to raw binary. */
+static_inline u64 f64_to_raw(f64 f) {
+ /* use memcpy to avoid violating the strict aliasing rule */
+ u64 u;
+ memcpy(&u, &f, 8);
+ return u;
+}
+
+/** Get raw 'infinity' with sign. */
+static_inline u64 f64_raw_get_inf(bool sign) {
+#if YYJSON_HAS_IEEE_754
+ return F64_RAW_INF | ((u64)sign << 63);
+#elif defined(INFINITY)
+ return f64_to_raw(sign ? -INFINITY : INFINITY);
+#else
+ return f64_to_raw(sign ? -HUGE_VAL : HUGE_VAL);
+#endif
+}
+
+/** Get raw 'nan' with sign. */
+static_inline u64 f64_raw_get_nan(bool sign) {
+#if YYJSON_HAS_IEEE_754
+ return F64_RAW_NAN | ((u64)sign << 63);
+#elif defined(NAN)
+ return f64_to_raw(sign ? (f64)-NAN : (f64)NAN);
+#else
+ return f64_to_raw((sign ? -0.0 : 0.0) / 0.0);
+#endif
+}
+
+/**
+ Convert normalized u64 (highest bit is 1) to f64.
+
+ Some compiler (such as Microsoft Visual C++ 6.0) do not support converting
+ number from u64 to f64. This function will first convert u64 to i64 and then
+ to f64, with `to nearest` rounding mode.
+ */
+static_inline f64 normalized_u64_to_f64(u64 val) {
+#if YYJSON_U64_TO_F64_NO_IMPL
+ i64 sig = (i64)((val >> 1) | (val & 1));
+ return ((f64)sig) * (f64)2.0;
+#else
+ return (f64)val;
+#endif
+}
+
+
+
+/*==============================================================================
+ * Size Utils
+ * These functions are used for memory allocation.
+ *============================================================================*/
+
+/** Returns whether the size is overflow after increment. */
+static_inline bool size_add_is_overflow(usize size, usize add) {
+ return size > (size + add);
+}
+
+/** Returns whether the size is power of 2 (size should not be 0). */
+static_inline bool size_is_pow2(usize size) {
+ return (size & (size - 1)) == 0;
+}
+
+/** Align size upwards (may overflow). */
+static_inline usize size_align_up(usize size, usize align) {
+ if (size_is_pow2(align)) {
+ return (size + (align - 1)) & ~(align - 1);
+ } else {
+ return size + align - (size + align - 1) % align - 1;
+ }
+}
+
+/** Align size downwards. */
+static_inline usize size_align_down(usize size, usize align) {
+ if (size_is_pow2(align)) {
+ return size & ~(align - 1);
+ } else {
+ return size - (size % align);
+ }
+}
+
+/** Align address upwards (may overflow). */
+static_inline void *mem_align_up(void *mem, usize align) {
+ usize size;
+ memcpy(&size, &mem, sizeof(usize));
+ size = size_align_up(size, align);
+ memcpy(&mem, &size, sizeof(usize));
+ return mem;
+}
+
+
+
+/*==============================================================================
+ * Bits Utils
+ * These functions are used by the floating-point number reader and writer.
+ *============================================================================*/
+
+/** Returns the number of leading 0-bits in value (input should not be 0). */
+static_inline u32 u64_lz_bits(u64 v) {
+#if GCC_HAS_CLZLL
+ return (u32)__builtin_clzll(v);
+#elif MSC_HAS_BIT_SCAN_64
+ unsigned long r;
+ _BitScanReverse64(&r, v);
+ return (u32)63 - (u32)r;
+#elif MSC_HAS_BIT_SCAN
+ unsigned long hi, lo;
+ bool hi_set = _BitScanReverse(&hi, (u32)(v >> 32)) != 0;
+ _BitScanReverse(&lo, (u32)v);
+ hi |= 32;
+ return (u32)63 - (u32)(hi_set ? hi : lo);
+#else
+ /*
+ branchless, use de Bruijn sequences
+ see: https://www.chessprogramming.org/BitScan
+ */
+ const u8 table[64] = {
+ 63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2,
+ 9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1,
+ 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18,
+ 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0
+ };
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v |= v >> 32;
+ return table[(v * U64(0x03F79D71, 0xB4CB0A89)) >> 58];
+#endif
+}
+
+/** Returns the number of trailing 0-bits in value (input should not be 0). */
+static_inline u32 u64_tz_bits(u64 v) {
+#if GCC_HAS_CTZLL
+ return (u32)__builtin_ctzll(v);
+#elif MSC_HAS_BIT_SCAN_64
+ unsigned long r;
+ _BitScanForward64(&r, v);
+ return (u32)r;
+#elif MSC_HAS_BIT_SCAN
+ unsigned long lo, hi;
+ bool lo_set = _BitScanForward(&lo, (u32)(v)) != 0;
+ _BitScanForward(&hi, (u32)(v >> 32));
+ hi += 32;
+ return lo_set ? lo : hi;
+#else
+ /*
+ branchless, use de Bruijn sequences
+ see: https://www.chessprogramming.org/BitScan
+ */
+ const u8 table[64] = {
+ 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
+ 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
+ 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
+ 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
+ };
+ return table[((v & (~v + 1)) * U64(0x022FDD63, 0xCC95386D)) >> 58];
+#endif
+}
+
+
+
+/*==============================================================================
+ * 128-bit Integer Utils
+ * These functions are used by the floating-point number reader and writer.
+ *============================================================================*/
+
+/** Multiplies two 64-bit unsigned integers (a * b),
+ returns the 128-bit result as 'hi' and 'lo'. */
+static_inline void u128_mul(u64 a, u64 b, u64 *hi, u64 *lo) {
+#if YYJSON_HAS_INT128
+ u128 m = (u128)a * b;
+ *hi = (u64)(m >> 64);
+ *lo = (u64)(m);
+#elif MSC_HAS_UMUL128
+ *lo = _umul128(a, b, hi);
+#else
+ u32 a0 = (u32)(a), a1 = (u32)(a >> 32);
+ u32 b0 = (u32)(b), b1 = (u32)(b >> 32);
+ u64 p00 = (u64)a0 * b0, p01 = (u64)a0 * b1;
+ u64 p10 = (u64)a1 * b0, p11 = (u64)a1 * b1;
+ u64 m0 = p01 + (p00 >> 32);
+ u32 m00 = (u32)(m0), m01 = (u32)(m0 >> 32);
+ u64 m1 = p10 + m00;
+ u32 m10 = (u32)(m1), m11 = (u32)(m1 >> 32);
+ *hi = p11 + m01 + m11;
+ *lo = ((u64)m10 << 32) | (u32)p00;
+#endif
+}
+
+/** Multiplies two 64-bit unsigned integers and add a value (a * b + c),
+ returns the 128-bit result as 'hi' and 'lo'. */
+static_inline void u128_mul_add(u64 a, u64 b, u64 c, u64 *hi, u64 *lo) {
+#if YYJSON_HAS_INT128
+ u128 m = (u128)a * b + c;
+ *hi = (u64)(m >> 64);
+ *lo = (u64)(m);
+#else
+ u64 h, l, t;
+ u128_mul(a, b, &h, &l);
+ t = l + c;
+ h += (u64)(((t < l) | (t < c)));
+ *hi = h;
+ *lo = t;
+#endif
+}
+
+
+
+/*==============================================================================
+ * File Utils
+ * These functions are used to read and write JSON files.
+ *============================================================================*/
+
+#define YYJSON_FOPEN_EXT
+#if !defined(_MSC_VER) && defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+# if __GLIBC_PREREQ(2, 7)
+# undef YYJSON_FOPEN_EXT
+# define YYJSON_FOPEN_EXT "e" /* glibc extension to enable O_CLOEXEC */
+# endif
+#endif
+
+static_inline FILE *fopen_safe(const char *path, const char *mode) {
+#if YYJSON_MSC_VER >= 1400
+ FILE *file = NULL;
+ if (fopen_s(&file, path, mode) != 0) return NULL;
+ return file;
+#else
+ return fopen(path, mode);
+#endif
+}
+
+static_inline FILE *fopen_readonly(const char *path) {
+ return fopen_safe(path, "rb" YYJSON_FOPEN_EXT);
+}
+
+static_inline FILE *fopen_writeonly(const char *path) {
+ return fopen_safe(path, "wb" YYJSON_FOPEN_EXT);
+}
+
+static_inline usize fread_safe(void *buf, usize size, FILE *file) {
+#if YYJSON_MSC_VER >= 1400
+ return fread_s(buf, size, 1, size, file);
+#else
+ return fread(buf, 1, size, file);
+#endif
+}
+
+
+
+/*==============================================================================
+ * Default Memory Allocator
+ * This is a simple libc memory allocator wrapper.
+ *============================================================================*/
+
+static void *default_malloc(void *ctx, usize size) {
+ return malloc(size);
+}
+
+static void *default_realloc(void *ctx, void *ptr, usize old_size, usize size) {
+ return realloc(ptr, size);
+}
+
+static void default_free(void *ctx, void *ptr) {
+ free(ptr);
+}
+
+static const yyjson_alc YYJSON_DEFAULT_ALC = {
+ default_malloc,
+ default_realloc,
+ default_free,
+ NULL
+};
+
+
+
+/*==============================================================================
+ * Null Memory Allocator
+ *
+ * This allocator is just a placeholder to ensure that the internal
+ * malloc/realloc/free function pointers are not null.
+ *============================================================================*/
+
+static void *null_malloc(void *ctx, usize size) {
+ return NULL;
+}
+
+static void *null_realloc(void *ctx, void *ptr, usize old_size, usize size) {
+ return NULL;
+}
+
+static void null_free(void *ctx, void *ptr) {
+ return;
+}
+
+static const yyjson_alc YYJSON_NULL_ALC = {
+ null_malloc,
+ null_realloc,
+ null_free,
+ NULL
+};
+
+
+
+/*==============================================================================
+ * Pool Memory Allocator
+ *
+ * This allocator is initialized with a fixed-size buffer.
+ * The buffer is split into multiple memory chunks for memory allocation.
+ *============================================================================*/
+
+/** memory chunk header */
+typedef struct pool_chunk {
+ usize size; /* chunk memory size, include chunk header */
+ struct pool_chunk *next; /* linked list, nullable */
+ /* char mem[]; flexible array member */
+} pool_chunk;
+
+/** allocator ctx header */
+typedef struct pool_ctx {
+ usize size; /* total memory size, include ctx header */
+ pool_chunk *free_list; /* linked list, nullable */
+ /* pool_chunk chunks[]; flexible array member */
+} pool_ctx;
+
+/** align up the input size to chunk size */
+static_inline void pool_size_align(usize *size) {
+ *size = size_align_up(*size, sizeof(pool_chunk)) + sizeof(pool_chunk);
+}
+
+static void *pool_malloc(void *ctx_ptr, usize size) {
+ /* assert(size != 0) */
+ pool_ctx *ctx = (pool_ctx *)ctx_ptr;
+ pool_chunk *next, *prev = NULL, *cur = ctx->free_list;
+
+ if (unlikely(size >= ctx->size)) return NULL;
+ pool_size_align(&size);
+
+ while (cur) {
+ if (cur->size < size) {
+ /* not enough space, try next chunk */
+ prev = cur;
+ cur = cur->next;
+ continue;
+ }
+ if (cur->size >= size + sizeof(pool_chunk) * 2) {
+ /* too much space, split this chunk */
+ next = (pool_chunk *)(void *)((u8 *)cur + size);
+ next->size = cur->size - size;
+ next->next = cur->next;
+ cur->size = size;
+ } else {
+ /* just enough space, use whole chunk */
+ next = cur->next;
+ }
+ if (prev) prev->next = next;
+ else ctx->free_list = next;
+ return (void *)(cur + 1);
+ }
+ return NULL;
+}
+
+static void pool_free(void *ctx_ptr, void *ptr) {
+ /* assert(ptr != NULL) */
+ pool_ctx *ctx = (pool_ctx *)ctx_ptr;
+ pool_chunk *cur = ((pool_chunk *)ptr) - 1;
+ pool_chunk *prev = NULL, *next = ctx->free_list;
+
+ while (next && next < cur) {
+ prev = next;
+ next = next->next;
+ }
+ if (prev) prev->next = cur;
+ else ctx->free_list = cur;
+ cur->next = next;
+
+ if (next && ((u8 *)cur + cur->size) == (u8 *)next) {
+ /* merge cur to higher chunk */
+ cur->size += next->size;
+ cur->next = next->next;
+ }
+ if (prev && ((u8 *)prev + prev->size) == (u8 *)cur) {
+ /* merge cur to lower chunk */
+ prev->size += cur->size;
+ prev->next = cur->next;
+ }
+}
+
+static void *pool_realloc(void *ctx_ptr, void *ptr,
+ usize old_size, usize size) {
+ /* assert(ptr != NULL && size != 0 && old_size < size) */
+ pool_ctx *ctx = (pool_ctx *)ctx_ptr;
+ pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp;
+
+ /* check size */
+ if (unlikely(size >= ctx->size)) return NULL;
+ pool_size_align(&old_size);
+ pool_size_align(&size);
+ if (unlikely(old_size == size)) return ptr;
+
+ /* find next and prev chunk */
+ prev = NULL;
+ next = ctx->free_list;
+ while (next && next < cur) {
+ prev = next;
+ next = next->next;
+ }
+
+ if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) {
+ /* merge to higher chunk if they are contiguous */
+ usize free_size = cur->size + next->size - size;
+ if (free_size > sizeof(pool_chunk) * 2) {
+ tmp = (pool_chunk *)(void *)((u8 *)cur + size);
+ if (prev) prev->next = tmp;
+ else ctx->free_list = tmp;
+ tmp->next = next->next;
+ tmp->size = free_size;
+ cur->size = size;
+ } else {
+ if (prev) prev->next = next->next;
+ else ctx->free_list = next->next;
+ cur->size += next->size;
+ }
+ return ptr;
+ } else {
+ /* fallback to malloc and memcpy */
+ void *new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk));
+ if (new_ptr) {
+ memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk));
+ pool_free(ctx_ptr, ptr);
+ }
+ return new_ptr;
+ }
+}
+
+bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) {
+ pool_chunk *chunk;
+ pool_ctx *ctx;
+
+ if (unlikely(!alc)) return false;
+ *alc = YYJSON_NULL_ALC;
+ if (size < sizeof(pool_ctx) * 4) return false;
+ ctx = (pool_ctx *)mem_align_up(buf, sizeof(pool_ctx));
+ if (unlikely(!ctx)) return false;
+ size -= (usize)((u8 *)ctx - (u8 *)buf);
+ size = size_align_down(size, sizeof(pool_ctx));
+
+ chunk = (pool_chunk *)(ctx + 1);
+ chunk->size = size - sizeof(pool_ctx);
+ chunk->next = NULL;
+ ctx->size = size;
+ ctx->free_list = chunk;
+
+ alc->malloc = pool_malloc;
+ alc->realloc = pool_realloc;
+ alc->free = pool_free;
+ alc->ctx = (void *)ctx;
+ return true;
+}
+
+
+
+/*==============================================================================
+ * Dynamic Memory Allocator
+ *
+ * This allocator allocates memory on demand and does not immediately release
+ * unused memory. Instead, it places the unused memory into a freelist for
+ * potential reuse in the future. It is only when the entire allocator is
+ * destroyed that all previously allocated memory is released at once.
+ *============================================================================*/
+
+/** memory chunk header */
+typedef struct dyn_chunk {
+ usize size; /* chunk size, include header */
+ struct dyn_chunk *next;
+ /* char mem[]; flexible array member */
+} dyn_chunk;
+
+/** allocator ctx header */
+typedef struct {
+ dyn_chunk free_list; /* dummy header, sorted from small to large */
+ dyn_chunk used_list; /* dummy header */
+} dyn_ctx;
+
+/** align up the input size to chunk size */
+static_inline bool dyn_size_align(usize *size) {
+ usize alc_size = *size + sizeof(dyn_chunk);
+ alc_size = size_align_up(alc_size, YYJSON_ALC_DYN_MIN_SIZE);
+ if (unlikely(alc_size < *size)) return false; /* overflow */
+ *size = alc_size;
+ return true;
+}
+
+/** remove a chunk from list (the chunk must already be in the list) */
+static_inline void dyn_chunk_list_remove(dyn_chunk *list, dyn_chunk *chunk) {
+ dyn_chunk *prev = list, *cur;
+ for (cur = prev->next; cur; cur = cur->next) {
+ if (cur == chunk) {
+ prev->next = cur->next;
+ cur->next = NULL;
+ return;
+ }
+ prev = cur;
+ }
+}
+
+/** add a chunk to list header (the chunk must not be in the list) */
+static_inline void dyn_chunk_list_add(dyn_chunk *list, dyn_chunk *chunk) {
+ chunk->next = list->next;
+ list->next = chunk;
+}
+
+static void *dyn_malloc(void *ctx_ptr, usize size) {
+ /* assert(size != 0) */
+ const yyjson_alc def = YYJSON_DEFAULT_ALC;
+ dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
+ dyn_chunk *chunk, *prev, *next;
+ if (unlikely(!dyn_size_align(&size))) return NULL;
+
+ /* freelist is empty, create new chunk */
+ if (!ctx->free_list.next) {
+ chunk = (dyn_chunk *)def.malloc(def.ctx, size);
+ if (unlikely(!chunk)) return NULL;
+ chunk->size = size;
+ chunk->next = NULL;
+ dyn_chunk_list_add(&ctx->used_list, chunk);
+ return (void *)(chunk + 1);
+ }
+
+ /* find a large enough chunk, or resize the largest chunk */
+ prev = &ctx->free_list;
+ while (true) {
+ chunk = prev->next;
+ if (chunk->size >= size) { /* enough size, reuse this chunk */
+ prev->next = chunk->next;
+ dyn_chunk_list_add(&ctx->used_list, chunk);
+ return (void *)(chunk + 1);
+ }
+ if (!chunk->next) { /* resize the largest chunk */
+ chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size);
+ if (unlikely(!chunk)) return NULL;
+ prev->next = NULL;
+ chunk->size = size;
+ dyn_chunk_list_add(&ctx->used_list, chunk);
+ return (void *)(chunk + 1);
+ }
+ prev = chunk;
+ }
+}
+
+static void *dyn_realloc(void *ctx_ptr, void *ptr,
+ usize old_size, usize size) {
+ /* assert(ptr != NULL && size != 0 && old_size < size) */
+ const yyjson_alc def = YYJSON_DEFAULT_ALC;
+ dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
+ dyn_chunk *prev, *next, *new_chunk;
+ dyn_chunk *chunk = (dyn_chunk *)ptr - 1;
+ if (unlikely(!dyn_size_align(&size))) return NULL;
+ if (chunk->size >= size) return ptr;
+
+ dyn_chunk_list_remove(&ctx->used_list, chunk);
+ new_chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size);
+ if (likely(new_chunk)) {
+ new_chunk->size = size;
+ chunk = new_chunk;
+ }
+ dyn_chunk_list_add(&ctx->used_list, chunk);
+ return new_chunk ? (void *)(new_chunk + 1) : NULL;
+}
+
+static void dyn_free(void *ctx_ptr, void *ptr) {
+ /* assert(ptr != NULL) */
+ dyn_ctx *ctx = (dyn_ctx *)ctx_ptr;
+ dyn_chunk *chunk = (dyn_chunk *)ptr - 1, *prev;
+
+ dyn_chunk_list_remove(&ctx->used_list, chunk);
+ for (prev = &ctx->free_list; prev; prev = prev->next) {
+ if (!prev->next || prev->next->size >= chunk->size) {
+ chunk->next = prev->next;
+ prev->next = chunk;
+ break;
+ }
+ }
+}
+
+yyjson_alc *yyjson_alc_dyn_new(void) {
+ const yyjson_alc def = YYJSON_DEFAULT_ALC;
+ usize hdr_len = sizeof(yyjson_alc) + sizeof(dyn_ctx);
+ yyjson_alc *alc = (yyjson_alc *)def.malloc(def.ctx, hdr_len);
+ dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1);
+ if (unlikely(!alc)) return NULL;
+ alc->malloc = dyn_malloc;
+ alc->realloc = dyn_realloc;
+ alc->free = dyn_free;
+ alc->ctx = alc + 1;
+ memset(ctx, 0, sizeof(*ctx));
+ return alc;
+}
+
+void yyjson_alc_dyn_free(yyjson_alc *alc) {
+ const yyjson_alc def = YYJSON_DEFAULT_ALC;
+ dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1);
+ dyn_chunk *chunk, *next;
+ if (unlikely(!alc)) return;
+ for (chunk = ctx->free_list.next; chunk; chunk = next) {
+ next = chunk->next;
+ def.free(def.ctx, chunk);
+ }
+ for (chunk = ctx->used_list.next; chunk; chunk = next) {
+ next = chunk->next;
+ def.free(def.ctx, chunk);
+ }
+ def.free(def.ctx, alc);
+}
+
+
+
+/*==============================================================================
+ * JSON document and value
+ *============================================================================*/
+
+static_inline void unsafe_yyjson_str_pool_release(yyjson_str_pool *pool,
+ yyjson_alc *alc) {
+ yyjson_str_chunk *chunk = pool->chunks, *next;
+ while (chunk) {
+ next = chunk->next;
+ alc->free(alc->ctx, chunk);
+ chunk = next;
+ }
+}
+
+static_inline void unsafe_yyjson_val_pool_release(yyjson_val_pool *pool,
+ yyjson_alc *alc) {
+ yyjson_val_chunk *chunk = pool->chunks, *next;
+ while (chunk) {
+ next = chunk->next;
+ alc->free(alc->ctx, chunk);
+ chunk = next;
+ }
+}
+
+bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool,
+ const yyjson_alc *alc, usize len) {
+ yyjson_str_chunk *chunk;
+ usize size, max_len;
+
+ /* create a new chunk */
+ max_len = USIZE_MAX - sizeof(yyjson_str_chunk);
+ if (unlikely(len > max_len)) return false;
+ size = len + sizeof(yyjson_str_chunk);
+ size = yyjson_max(pool->chunk_size, size);
+ chunk = (yyjson_str_chunk *)alc->malloc(alc->ctx, size);
+ if (unlikely(!chunk)) return false;
+
+ /* insert the new chunk as the head of the linked list */
+ chunk->next = pool->chunks;
+ chunk->chunk_size = size;
+ pool->chunks = chunk;
+ pool->cur = (char *)chunk + sizeof(yyjson_str_chunk);
+ pool->end = (char *)chunk + size;
+
+ /* the next chunk is twice the size of the current one */
+ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max);
+ if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */
+ pool->chunk_size = size;
+ return true;
+}
+
+bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool,
+ const yyjson_alc *alc, usize count) {
+ yyjson_val_chunk *chunk;
+ usize size, max_count;
+
+ /* create a new chunk */
+ max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1;
+ if (unlikely(count > max_count)) return false;
+ size = (count + 1) * sizeof(yyjson_mut_val);
+ size = yyjson_max(pool->chunk_size, size);
+ chunk = (yyjson_val_chunk *)alc->malloc(alc->ctx, size);
+ if (unlikely(!chunk)) return false;
+
+ /* insert the new chunk as the head of the linked list */
+ chunk->next = pool->chunks;
+ chunk->chunk_size = size;
+ pool->chunks = chunk;
+ pool->cur = (yyjson_mut_val *)(void *)((u8 *)chunk) + 1;
+ pool->end = (yyjson_mut_val *)(void *)((u8 *)chunk + size);
+
+ /* the next chunk is twice the size of the current one */
+ size = yyjson_min(pool->chunk_size * 2, pool->chunk_size_max);
+ if (size < pool->chunk_size) size = pool->chunk_size_max; /* overflow */
+ pool->chunk_size = size;
+ return true;
+}
+
+bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc, size_t len) {
+ usize max_size = USIZE_MAX - sizeof(yyjson_str_chunk);
+ if (!doc || !len || len > max_size) return false;
+ doc->str_pool.chunk_size = len + sizeof(yyjson_str_chunk);
+ return true;
+}
+
+bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc, size_t count) {
+ usize max_count = USIZE_MAX / sizeof(yyjson_mut_val) - 1;
+ if (!doc || !count || count > max_count) return false;
+ doc->val_pool.chunk_size = (count + 1) * sizeof(yyjson_mut_val);
+ return true;
+}
+
+void yyjson_mut_doc_free(yyjson_mut_doc *doc) {
+ if (doc) {
+ yyjson_alc alc = doc->alc;
+ memset(&doc->alc, 0, sizeof(alc));
+ unsafe_yyjson_str_pool_release(&doc->str_pool, &alc);
+ unsafe_yyjson_val_pool_release(&doc->val_pool, &alc);
+ alc.free(alc.ctx, doc);
+ }
+}
+
+yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc) {
+ yyjson_mut_doc *doc;
+ if (!alc) alc = &YYJSON_DEFAULT_ALC;
+ doc = (yyjson_mut_doc *)alc->malloc(alc->ctx, sizeof(yyjson_mut_doc));
+ if (!doc) return NULL;
+ memset(doc, 0, sizeof(yyjson_mut_doc));
+
+ doc->alc = *alc;
+ doc->str_pool.chunk_size = YYJSON_MUT_DOC_STR_POOL_INIT_SIZE;
+ doc->str_pool.chunk_size_max = YYJSON_MUT_DOC_STR_POOL_MAX_SIZE;
+ doc->val_pool.chunk_size = YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE;
+ doc->val_pool.chunk_size_max = YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE;
+ return doc;
+}
+
+yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc, const yyjson_alc *alc) {
+ yyjson_mut_doc *m_doc;
+ yyjson_mut_val *m_val;
+
+ if (!doc || !doc->root) return NULL;
+ m_doc = yyjson_mut_doc_new(alc);
+ if (!m_doc) return NULL;
+ m_val = yyjson_val_mut_copy(m_doc, doc->root);
+ if (!m_val) {
+ yyjson_mut_doc_free(m_doc);
+ return NULL;
+ }
+ yyjson_mut_doc_set_root(m_doc, m_val);
+ return m_doc;
+}
+
+yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc,
+ const yyjson_alc *alc) {
+ yyjson_mut_doc *m_doc;
+ yyjson_mut_val *m_val;
+
+ if (!doc) return NULL;
+ if (!doc->root) return yyjson_mut_doc_new(alc);
+
+ m_doc = yyjson_mut_doc_new(alc);
+ if (!m_doc) return NULL;
+ m_val = yyjson_mut_val_mut_copy(m_doc, doc->root);
+ if (!m_val) {
+ yyjson_mut_doc_free(m_doc);
+ return NULL;
+ }
+ yyjson_mut_doc_set_root(m_doc, m_val);
+ return m_doc;
+}
+
+yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc,
+ yyjson_val *i_vals) {
+ /*
+ The immutable object or array stores all sub-values in a contiguous memory,
+ We copy them to another contiguous memory as mutable values,
+ then reconnect the mutable values with the original relationship.
+ */
+ usize i_vals_len;
+ yyjson_mut_val *m_vals, *m_val;
+ yyjson_val *i_val, *i_end;
+
+ if (!m_doc || !i_vals) return NULL;
+ i_end = unsafe_yyjson_get_next(i_vals);
+ i_vals_len = (usize)(unsafe_yyjson_get_next(i_vals) - i_vals);
+ m_vals = unsafe_yyjson_mut_val(m_doc, i_vals_len);
+ if (!m_vals) return NULL;
+ i_val = i_vals;
+ m_val = m_vals;
+
+ for (; i_val < i_end; i_val++, m_val++) {
+ yyjson_type type = unsafe_yyjson_get_type(i_val);
+ m_val->tag = i_val->tag;
+ m_val->uni.u64 = i_val->uni.u64;
+ if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) {
+ const char *str = i_val->uni.str;
+ usize str_len = unsafe_yyjson_get_len(i_val);
+ m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len);
+ if (!m_val->uni.str) return NULL;
+ } else if (type == YYJSON_TYPE_ARR) {
+ usize len = unsafe_yyjson_get_len(i_val);
+ if (len > 0) {
+ yyjson_val *ii_val = i_val + 1, *ii_next;
+ yyjson_mut_val *mm_val = m_val + 1, *mm_ctn = m_val, *mm_next;
+ while (len-- > 1) {
+ ii_next = unsafe_yyjson_get_next(ii_val);
+ mm_next = mm_val + (ii_next - ii_val);
+ mm_val->next = mm_next;
+ ii_val = ii_next;
+ mm_val = mm_next;
+ }
+ mm_val->next = mm_ctn + 1;
+ mm_ctn->uni.ptr = mm_val;
+ }
+ } else if (type == YYJSON_TYPE_OBJ) {
+ usize len = unsafe_yyjson_get_len(i_val);
+ if (len > 0) {
+ yyjson_val *ii_key = i_val + 1, *ii_nextkey;
+ yyjson_mut_val *mm_key = m_val + 1, *mm_ctn = m_val;
+ yyjson_mut_val *mm_nextkey;
+ while (len-- > 1) {
+ ii_nextkey = unsafe_yyjson_get_next(ii_key + 1);
+ mm_nextkey = mm_key + (ii_nextkey - ii_key);
+ mm_key->next = mm_key + 1;
+ mm_key->next->next = mm_nextkey;
+ ii_key = ii_nextkey;
+ mm_key = mm_nextkey;
+ }
+ mm_key->next = mm_key + 1;
+ mm_key->next->next = mm_ctn + 1;
+ mm_ctn->uni.ptr = mm_key;
+ }
+ }
+ }
+
+ return m_vals;
+}
+
+static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc,
+ yyjson_mut_val *m_vals) {
+ /*
+ The mutable object or array stores all sub-values in a circular linked
+ list, so we can traverse them in the same loop. The traversal starts from
+ the last item, continues with the first item in a list, and ends with the
+ second to last item, which needs to be linked to the last item to close the
+ circle.
+ */
+ yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1);
+ if (unlikely(!m_val)) return NULL;
+ m_val->tag = m_vals->tag;
+
+ switch (unsafe_yyjson_get_type(m_vals)) {
+ case YYJSON_TYPE_OBJ:
+ case YYJSON_TYPE_ARR:
+ if (unsafe_yyjson_get_len(m_vals) > 0) {
+ yyjson_mut_val *last = (yyjson_mut_val *)m_vals->uni.ptr;
+ yyjson_mut_val *next = last->next, *prev;
+ prev = unsafe_yyjson_mut_val_mut_copy(m_doc, last);
+ if (!prev) return NULL;
+ m_val->uni.ptr = (void *)prev;
+ while (next != last) {
+ prev->next = unsafe_yyjson_mut_val_mut_copy(m_doc, next);
+ if (!prev->next) return NULL;
+ prev = prev->next;
+ next = next->next;
+ }
+ prev->next = (yyjson_mut_val *)m_val->uni.ptr;
+ }
+ break;
+
+ case YYJSON_TYPE_RAW:
+ case YYJSON_TYPE_STR: {
+ const char *str = m_vals->uni.str;
+ usize str_len = unsafe_yyjson_get_len(m_vals);
+ m_val->uni.str = unsafe_yyjson_mut_strncpy(m_doc, str, str_len);
+ if (!m_val->uni.str) return NULL;
+ break;
+ }
+
+ default:
+ m_val->uni = m_vals->uni;
+ break;
+ }
+
+ return m_val;
+}
+
+yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc,
+ yyjson_mut_val *val) {
+ if (doc && val) return unsafe_yyjson_mut_val_mut_copy(doc, val);
+ return NULL;
+}
+
+/* Count the number of values and the total length of the strings. */
+static void yyjson_mut_stat(yyjson_mut_val *val,
+ usize *val_sum, usize *str_sum) {
+ yyjson_type type = unsafe_yyjson_get_type(val);
+ *val_sum += 1;
+ if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) {
+ yyjson_mut_val *child = (yyjson_mut_val *)val->uni.ptr;
+ usize len = unsafe_yyjson_get_len(val), i;
+ len <<= (u8)(type == YYJSON_TYPE_OBJ);
+ *val_sum += len;
+ for (i = 0; i < len; i++) {
+ yyjson_type stype = unsafe_yyjson_get_type(child);
+ if (stype == YYJSON_TYPE_STR || stype == YYJSON_TYPE_RAW) {
+ *str_sum += unsafe_yyjson_get_len(child) + 1;
+ } else if (stype == YYJSON_TYPE_ARR || stype == YYJSON_TYPE_OBJ) {
+ yyjson_mut_stat(child, val_sum, str_sum);
+ *val_sum -= 1;
+ }
+ child = child->next;
+ }
+ } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) {
+ *str_sum += unsafe_yyjson_get_len(val) + 1;
+ }
+}
+
+/* Copy mutable values to immutable value pool. */
+static usize yyjson_imut_copy(yyjson_val **val_ptr, char **buf_ptr,
+ yyjson_mut_val *mval) {
+ yyjson_val *val = *val_ptr;
+ yyjson_type type = unsafe_yyjson_get_type(mval);
+ if (type == YYJSON_TYPE_ARR || type == YYJSON_TYPE_OBJ) {
+ yyjson_mut_val *child = (yyjson_mut_val *)mval->uni.ptr;
+ usize len = unsafe_yyjson_get_len(mval), i;
+ usize val_sum = 1;
+ if (type == YYJSON_TYPE_OBJ) {
+ if (len) child = child->next->next;
+ len <<= 1;
+ } else {
+ if (len) child = child->next;
+ }
+ *val_ptr = val + 1;
+ for (i = 0; i < len; i++) {
+ val_sum += yyjson_imut_copy(val_ptr, buf_ptr, child);
+ child = child->next;
+ }
+ val->tag = mval->tag;
+ val->uni.ofs = val_sum * sizeof(yyjson_val);
+ return val_sum;
+ } else if (type == YYJSON_TYPE_STR || type == YYJSON_TYPE_RAW) {
+ char *buf = *buf_ptr;
+ usize len = unsafe_yyjson_get_len(mval);
+ memcpy((void *)buf, (const void *)mval->uni.str, len);
+ buf[len] = '\0';
+ val->tag = mval->tag;
+ val->uni.str = buf;
+ *val_ptr = val + 1;
+ *buf_ptr = buf + len + 1;
+ return 1;
+ } else {
+ val->tag = mval->tag;
+ val->uni = mval->uni;
+ *val_ptr = val + 1;
+ return 1;
+ }
+}
+
+yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *mdoc,
+ const yyjson_alc *alc) {
+ if (!mdoc) return NULL;
+ return yyjson_mut_val_imut_copy(mdoc->root, alc);
+}
+
+yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *mval,
+ const yyjson_alc *alc) {
+ usize val_num = 0, str_sum = 0, hdr_size, buf_size;
+ yyjson_doc *doc = NULL;
+ yyjson_val *val_hdr = NULL;
+
+ /* This value should be NULL here. Setting a non-null value suppresses
+ warning from the clang analyzer. */
+ char *str_hdr = (char *)(void *)&str_sum;
+ if (!mval) return NULL;
+ if (!alc) alc = &YYJSON_DEFAULT_ALC;
+
+ /* traverse the input value to get pool size */
+ yyjson_mut_stat(mval, &val_num, &str_sum);
+
+ /* create doc and val pool */
+ hdr_size = size_align_up(sizeof(yyjson_doc), sizeof(yyjson_val));
+ buf_size = hdr_size + val_num * sizeof(yyjson_val);
+ doc = (yyjson_doc *)alc->malloc(alc->ctx, buf_size);
+ if (!doc) return NULL;
+ memset(doc, 0, sizeof(yyjson_doc));
+ val_hdr = (yyjson_val *)(void *)((char *)(void *)doc + hdr_size);
+ doc->root = val_hdr;
+ doc->alc = *alc;
+
+ /* create str pool */
+ if (str_sum > 0) {
+ str_hdr = (char *)alc->malloc(alc->ctx, str_sum);
+ doc->str_pool = str_hdr;
+ if (!str_hdr) {
+ alc->free(alc->ctx, (void *)doc);
+ return NULL;
+ }
+ }
+
+ /* copy vals and strs */
+ doc->val_read = yyjson_imut_copy(&val_hdr, &str_hdr, mval);
+ doc->dat_read = str_sum + 1;
+ return doc;
+}
+
+static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) {
+ yyjson_val_uni *luni = &((yyjson_val *)lhs)->uni;
+ yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni;
+ yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs);
+ yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs);
+ if (lt == rt) return luni->u64 == runi->u64;
+ if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) {
+ return luni->i64 >= 0 && luni->u64 == runi->u64;
+ }
+ if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) {
+ return runi->i64 >= 0 && luni->u64 == runi->u64;
+ }
+ return false;
+}
+
+static_inline bool unsafe_yyjson_str_equals(void *lhs, void *rhs) {
+ usize len = unsafe_yyjson_get_len(lhs);
+ if (len != unsafe_yyjson_get_len(rhs)) return false;
+ return !memcmp(unsafe_yyjson_get_str(lhs),
+ unsafe_yyjson_get_str(rhs), len);
+}
+
+bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) {
+ yyjson_type type = unsafe_yyjson_get_type(lhs);
+ if (type != unsafe_yyjson_get_type(rhs)) return false;
+
+ switch (type) {
+ case YYJSON_TYPE_OBJ: {
+ usize len = unsafe_yyjson_get_len(lhs);
+ if (len != unsafe_yyjson_get_len(rhs)) return false;
+ if (len > 0) {
+ yyjson_obj_iter iter;
+ yyjson_obj_iter_init(rhs, &iter);
+ lhs = unsafe_yyjson_get_first(lhs);
+ while (len-- > 0) {
+ rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str,
+ unsafe_yyjson_get_len(lhs));
+ if (!rhs) return false;
+ if (!unsafe_yyjson_equals(lhs + 1, rhs)) return false;
+ lhs = unsafe_yyjson_get_next(lhs + 1);
+ }
+ }
+ /* yyjson allows duplicate keys, so the check may be inaccurate */
+ return true;
+ }
+
+ case YYJSON_TYPE_ARR: {
+ usize len = unsafe_yyjson_get_len(lhs);
+ if (len != unsafe_yyjson_get_len(rhs)) return false;
+ if (len > 0) {
+ lhs = unsafe_yyjson_get_first(lhs);
+ rhs = unsafe_yyjson_get_first(rhs);
+ while (len-- > 0) {
+ if (!unsafe_yyjson_equals(lhs, rhs)) return false;
+ lhs = unsafe_yyjson_get_next(lhs);
+ rhs = unsafe_yyjson_get_next(rhs);
+ }
+ }
+ return true;
+ }
+
+ case YYJSON_TYPE_NUM:
+ return unsafe_yyjson_num_equals(lhs, rhs);
+
+ case YYJSON_TYPE_RAW:
+ case YYJSON_TYPE_STR:
+ return unsafe_yyjson_str_equals(lhs, rhs);
+
+ case YYJSON_TYPE_NULL:
+ case YYJSON_TYPE_BOOL:
+ return lhs->tag == rhs->tag;
+
+ default:
+ return false;
+ }
+}
+
+bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) {
+ yyjson_type type = unsafe_yyjson_get_type(lhs);
+ if (type != unsafe_yyjson_get_type(rhs)) return false;
+
+ switch (type) {
+ case YYJSON_TYPE_OBJ: {
+ usize len = unsafe_yyjson_get_len(lhs);
+ if (len != unsafe_yyjson_get_len(rhs)) return false;
+ if (len > 0) {
+ yyjson_mut_obj_iter iter;
+ yyjson_mut_obj_iter_init(rhs, &iter);
+ lhs = (yyjson_mut_val *)lhs->uni.ptr;
+ while (len-- > 0) {
+ rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str,
+ unsafe_yyjson_get_len(lhs));
+ if (!rhs) return false;
+ if (!unsafe_yyjson_mut_equals(lhs->next, rhs)) return false;
+ lhs = lhs->next->next;
+ }
+ }
+ /* yyjson allows duplicate keys, so the check may be inaccurate */
+ return true;
+ }
+
+ case YYJSON_TYPE_ARR: {
+ usize len = unsafe_yyjson_get_len(lhs);
+ if (len != unsafe_yyjson_get_len(rhs)) return false;
+ if (len > 0) {
+ lhs = (yyjson_mut_val *)lhs->uni.ptr;
+ rhs = (yyjson_mut_val *)rhs->uni.ptr;
+ while (len-- > 0) {
+ if (!unsafe_yyjson_mut_equals(lhs, rhs)) return false;
+ lhs = lhs->next;
+ rhs = rhs->next;
+ }
+ }
+ return true;
+ }
+
+ case YYJSON_TYPE_NUM:
+ return unsafe_yyjson_num_equals(lhs, rhs);
+
+ case YYJSON_TYPE_RAW:
+ case YYJSON_TYPE_STR:
+ return unsafe_yyjson_str_equals(lhs, rhs);
+
+ case YYJSON_TYPE_NULL:
+ case YYJSON_TYPE_BOOL:
+ return lhs->tag == rhs->tag;
+
+ default:
+ return false;
+ }
+}
+
+bool yyjson_locate_pos(const char *str, size_t len, size_t pos,
+ size_t *line, size_t *col, size_t *chr) {
+ usize line_sum = 0, line_pos = 0, chr_sum = 0;
+ const u8 *cur = (const u8 *)str;
+ const u8 *end = cur + pos;
+
+ if (!str || pos > len) {
+ if (line) *line = 0;
+ if (col) *col = 0;
+ if (chr) *chr = 0;
+ return false;
+ }
+
+ while (cur < end) {
+ u8 c = *cur;
+ chr_sum += 1;
+ if (likely(c < 0x80)) { /* 0xxxxxxx (0x00-0x7F) ASCII */
+ if (c == '\n') {
+ line_sum += 1;
+ line_pos = chr_sum;
+ }
+ cur += 1;
+ }
+ else if (c < 0xC0) cur += 1; /* 10xxxxxx (0x80-0xBF) Invalid */
+ else if (c < 0xE0) cur += 2; /* 110xxxxx (0xC0-0xDF) 2-byte UTF-8 */
+ else if (c < 0xF0) cur += 3; /* 1110xxxx (0xE0-0xEF) 3-byte UTF-8 */
+ else if (c < 0xF8) cur += 4; /* 11110xxx (0xF0-0xF7) 4-byte UTF-8 */
+ else cur += 1; /* 11111xxx (0xF8-0xFF) Invalid */
+ }
+
+ if (line) *line = line_sum + 1;
+ if (col) *col = chr_sum - line_pos + 1;
+ if (chr) *chr = chr_sum;
+ return true;
+}
+
+
+
+#if !YYJSON_DISABLE_UTILS
+
+/*==============================================================================
+ * JSON Pointer API (RFC 6901)
+ *============================================================================*/
+
+/**
+ Get a token from JSON pointer string.
+ @param ptr [in,out]
+ in: string that points to current token prefix `/`
+ out: string that points to next token prefix `/`, or string end
+ @param end [in] end of the entire JSON Pointer string
+ @param len [out] unescaped token length
+ @param esc [out] number of escaped characters in this token
+ @return head of the token, or NULL if syntax error
+ */
+static_inline const char *ptr_next_token(const char **ptr, const char *end,
+ usize *len, usize *esc) {
+ const char *hdr = *ptr + 1;
+ const char *cur = hdr;
+ /* skip unescaped characters */
+ while (cur < end && *cur != '/' && *cur != '~') cur++;
+ if (likely(cur == end || *cur != '~')) {
+ /* no escaped characters, return */
+ *ptr = cur;
+ *len = (usize)(cur - hdr);
+ *esc = 0;
+ return hdr;
+ } else {
+ /* handle escaped characters */
+ usize esc_num = 0;
+ while (cur < end && *cur != '/') {
+ if (*cur++ == '~') {
+ if (cur == end || (*cur != '0' && *cur != '1')) {
+ *ptr = cur - 1;
+ return NULL;
+ }
+ esc_num++;
+ }
+ }
+ *ptr = cur;
+ *len = (usize)(cur - hdr) - esc_num;
+ *esc = esc_num;
+ return hdr;
+ }
+}
+
+/**
+ Convert token string to index.
+ @param cur [in] token head
+ @param len [in] token length
+ @param idx [out] the index number, or USIZE_MAX if token is '-'
+ @return true if token is a valid array index
+ */
+static_inline bool ptr_token_to_idx(const char *cur, usize len, usize *idx) {
+ const char *end = cur + len;
+ usize num = 0, add;
+ if (unlikely(len == 0 || len > USIZE_SAFE_DIG)) return false;
+ if (*cur == '0') {
+ if (unlikely(len > 1)) return false;
+ *idx = 0;
+ return true;
+ }
+ if (*cur == '-') {
+ if (unlikely(len > 1)) return false;
+ *idx = USIZE_MAX;
+ return true;
+ }
+ for (; cur < end && (add = (usize)((u8)*cur - (u8)'0')) <= 9; cur++) {
+ num = num * 10 + add;
+ }
+ if (unlikely(num == 0 || cur < end)) return false;
+ *idx = num;
+ return true;
+}
+
+/**
+ Compare JSON key with token.
+ @param key a string key (yyjson_val or yyjson_mut_val)
+ @param token a JSON pointer token
+ @param len unescaped token length
+ @param esc number of escaped characters in this token
+ @return true if `str` is equals to `token`
+ */
+static_inline bool ptr_token_eq(void *key,
+ const char *token, usize len, usize esc) {
+ yyjson_val *val = (yyjson_val *)key;
+ if (unsafe_yyjson_get_len(val) != len) return false;
+ if (likely(!esc)) {
+ return memcmp(val->uni.str, token, len) == 0;
+ } else {
+ const char *str = val->uni.str;
+ for (; len-- > 0; token++, str++) {
+ if (*token == '~') {
+ if (*str != (*++token == '0' ? '~' : '/')) return false;
+ } else {
+ if (*str != *token) return false;
+ }
+ }
+ return true;
+ }
+}
+
+/**
+ Get a value from array by token.
+ @param arr an array, should not be NULL or non-array type
+ @param token a JSON pointer token
+ @param len unescaped token length
+ @param esc number of escaped characters in this token
+ @return value at index, or NULL if token is not index or index is out of range
+ */
+static_inline yyjson_val *ptr_arr_get(yyjson_val *arr, const char *token,
+ usize len, usize esc) {
+ yyjson_val *val = unsafe_yyjson_get_first(arr);
+ usize num = unsafe_yyjson_get_len(arr), idx = 0;
+ if (unlikely(num == 0)) return NULL;
+ if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL;
+ if (unlikely(idx >= num)) return NULL;
+ if (unsafe_yyjson_arr_is_flat(arr)) {
+ return val + idx;
+ } else {
+ while (idx-- > 0) val = unsafe_yyjson_get_next(val);
+ return val;
+ }
+}
+
+/**
+ Get a value from object by token.
+ @param obj [in] an object, should not be NULL or non-object type
+ @param token [in] a JSON pointer token
+ @param len [in] unescaped token length
+ @param esc [in] number of escaped characters in this token
+ @return value associated with the token, or NULL if no value
+ */
+static_inline yyjson_val *ptr_obj_get(yyjson_val *obj, const char *token,
+ usize len, usize esc) {
+ yyjson_val *key = unsafe_yyjson_get_first(obj);
+ usize num = unsafe_yyjson_get_len(obj);
+ if (unlikely(num == 0)) return NULL;
+ for (; num > 0; num--, key = unsafe_yyjson_get_next(key + 1)) {
+ if (ptr_token_eq(key, token, len, esc)) return key + 1;
+ }
+ return NULL;
+}
+
+/**
+ Get a value from array by token.
+ @param arr [in] an array, should not be NULL or non-array type
+ @param token [in] a JSON pointer token
+ @param len [in] unescaped token length
+ @param esc [in] number of escaped characters in this token
+ @param pre [out] previous (sibling) value of the returned value
+ @param last [out] whether index is last
+ @return value at index, or NULL if token is not index or index is out of range
+ */
+static_inline yyjson_mut_val *ptr_mut_arr_get(yyjson_mut_val *arr,
+ const char *token,
+ usize len, usize esc,
+ yyjson_mut_val **pre,
+ bool *last) {
+ yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr; /* last (tail) */
+ usize num = unsafe_yyjson_get_len(arr), idx;
+ if (last) *last = false;
+ if (pre) *pre = NULL;
+ if (unlikely(num == 0)) {
+ if (last && len == 1 && (*token == '0' || *token == '-')) *last = true;
+ return NULL;
+ }
+ if (unlikely(!ptr_token_to_idx(token, len, &idx))) return NULL;
+ if (last) *last = (idx == num || idx == USIZE_MAX);
+ if (unlikely(idx >= num)) return NULL;
+ while (idx-- > 0) val = val->next;
+ *pre = val;
+ return val->next;
+}
+
+/**
+ Get a value from object by token.
+ @param obj [in] an object, should not be NULL or non-object type
+ @param token [in] a JSON pointer token
+ @param len [in] unescaped token length
+ @param esc [in] number of escaped characters in this token
+ @param pre [out] previous (sibling) key of the returned value's key
+ @return value associated with the token, or NULL if no value
+ */
+static_inline yyjson_mut_val *ptr_mut_obj_get(yyjson_mut_val *obj,
+ const char *token,
+ usize len, usize esc,
+ yyjson_mut_val **pre) {
+ yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr, *key;
+ usize num = unsafe_yyjson_get_len(obj);
+ if (pre) *pre = NULL;
+ if (unlikely(num == 0)) return NULL;
+ for (; num > 0; num--, pre_key = key) {
+ key = pre_key->next->next;
+ if (ptr_token_eq(key, token, len, esc)) {
+ *pre = pre_key;
+ return key->next;
+ }
+ }
+ return NULL;
+}
+
+/**
+ Create a string value with JSON pointer token.
+ @param token [in] a JSON pointer token
+ @param len [in] unescaped token length
+ @param esc [in] number of escaped characters in this token
+ @param doc [in] used for memory allocation when creating value
+ @return new string value, or NULL if memory allocation failed
+ */
+static_inline yyjson_mut_val *ptr_new_key(const char *token,
+ usize len, usize esc,
+ yyjson_mut_doc *doc) {
+ const char *src = token;
+ if (likely(!esc)) {
+ return yyjson_mut_strncpy(doc, src, len);
+ } else {
+ const char *end = src + len + esc;
+ char *dst = unsafe_yyjson_mut_str_alc(doc, len + esc);
+ char *str = dst;
+ if (unlikely(!dst)) return NULL;
+ for (; src < end; src++, dst++) {
+ if (*src != '~') *dst = *src;
+ else *dst = (*++src == '0' ? '~' : '/');
+ }
+ *dst = '\0';
+ return yyjson_mut_strn(doc, str, len);
+ }
+}
+
+/* macros for yyjson_ptr */
+#define return_err(_ret, _code, _pos, _msg) do { \
+ if (err) { \
+ err->code = YYJSON_PTR_ERR_##_code; \
+ err->msg = _msg; \
+ err->pos = (usize)(_pos); \
+ } \
+ return _ret; \
+} while (false)
+
+#define return_err_resolve(_ret, _pos) \
+ return_err(_ret, RESOLVE, _pos, "JSON pointer cannot be resolved")
+#define return_err_syntax(_ret, _pos) \
+ return_err(_ret, SYNTAX, _pos, "invalid escaped character")
+#define return_err_alloc(_ret) \
+ return_err(_ret, MEMORY_ALLOCATION, 0, "failed to create value")
+
+yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val,
+ const char *ptr, size_t ptr_len,
+ yyjson_ptr_err *err) {
+
+ const char *hdr = ptr, *end = ptr + ptr_len, *token;
+ usize len, esc;
+ yyjson_type type;
+
+ while (true) {
+ token = ptr_next_token(&ptr, end, &len, &esc);
+ if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr);
+ type = unsafe_yyjson_get_type(val);
+ if (type == YYJSON_TYPE_OBJ) {
+ val = ptr_obj_get(val, token, len, esc);
+ } else if (type == YYJSON_TYPE_ARR) {
+ val = ptr_arr_get(val, token, len, esc);
+ } else {
+ val = NULL;
+ }
+ if (!val) return_err_resolve(NULL, token - hdr);
+ if (ptr == end) return val;
+ }
+}
+
+yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val,
+ const char *ptr,
+ size_t ptr_len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+
+ const char *hdr = ptr, *end = ptr + ptr_len, *token;
+ usize len, esc;
+ yyjson_mut_val *ctn, *pre = NULL;
+ yyjson_type type;
+ bool idx_is_last = false;
+
+ while (true) {
+ token = ptr_next_token(&ptr, end, &len, &esc);
+ if (unlikely(!token)) return_err_syntax(NULL, ptr - hdr);
+ ctn = val;
+ type = unsafe_yyjson_get_type(val);
+ if (type == YYJSON_TYPE_OBJ) {
+ val = ptr_mut_obj_get(val, token, len, esc, &pre);
+ } else if (type == YYJSON_TYPE_ARR) {
+ val = ptr_mut_arr_get(val, token, len, esc, &pre, &idx_is_last);
+ } else {
+ val = NULL;
+ }
+ if (ctx && (ptr == end)) {
+ if (type == YYJSON_TYPE_OBJ ||
+ (type == YYJSON_TYPE_ARR && (val || idx_is_last))) {
+ ctx->ctn = ctn;
+ ctx->pre = pre;
+ }
+ }
+ if (!val) return_err_resolve(NULL, token - hdr);
+ if (ptr == end) return val;
+ }
+}
+
+bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val,
+ const char *ptr, size_t ptr_len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc,
+ bool create_parent, bool insert_new,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+
+ const char *hdr = ptr, *end = ptr + ptr_len, *token;
+ usize token_len, esc, ctn_len;
+ yyjson_mut_val *ctn, *key, *pre = NULL;
+ yyjson_mut_val *sep_ctn = NULL, *sep_key = NULL, *sep_val = NULL;
+ yyjson_type ctn_type;
+ bool idx_is_last = false;
+
+ /* skip exist parent nodes */
+ while (true) {
+ token = ptr_next_token(&ptr, end, &token_len, &esc);
+ if (unlikely(!token)) return_err_syntax(false, ptr - hdr);
+ ctn = val;
+ ctn_type = unsafe_yyjson_get_type(ctn);
+ if (ctn_type == YYJSON_TYPE_OBJ) {
+ val = ptr_mut_obj_get(ctn, token, token_len, esc, &pre);
+ } else if (ctn_type == YYJSON_TYPE_ARR) {
+ val = ptr_mut_arr_get(ctn, token, token_len, esc, &pre,
+ &idx_is_last);
+ } else return_err_resolve(false, token - hdr);
+ if (!val) break;
+ if (ptr == end) break; /* is last token */
+ }
+
+ /* create parent nodes if not exist */
+ if (unlikely(ptr != end)) { /* not last token */
+ if (!create_parent) return_err_resolve(false, token - hdr);
+
+ /* add value at last index if container is array */
+ if (ctn_type == YYJSON_TYPE_ARR) {
+ if (!idx_is_last || !insert_new) {
+ return_err_resolve(false, token - hdr);
+ }
+ val = yyjson_mut_obj(doc);
+ if (!val) return_err_alloc(false);
+
+ /* delay attaching until all operations are completed */
+ sep_ctn = ctn;
+ sep_key = NULL;
+ sep_val = val;
+
+ /* move to next token */
+ ctn = val;
+ val = NULL;
+ ctn_type = YYJSON_TYPE_OBJ;
+ token = ptr_next_token(&ptr, end, &token_len, &esc);
+ if (unlikely(!token)) return_err_resolve(false, token - hdr);
+ }
+
+ /* container is object, create parent nodes */
+ while (ptr != end) { /* not last token */
+ key = ptr_new_key(token, token_len, esc, doc);
+ if (!key) return_err_alloc(false);
+ val = yyjson_mut_obj(doc);
+ if (!val) return_err_alloc(false);
+
+ /* delay attaching until all operations are completed */
+ if (!sep_ctn) {
+ sep_ctn = ctn;
+ sep_key = key;
+ sep_val = val;
+ } else {
+ yyjson_mut_obj_add(ctn, key, val);
+ }
+
+ /* move to next token */
+ ctn = val;
+ val = NULL;
+ token = ptr_next_token(&ptr, end, &token_len, &esc);
+ if (unlikely(!token)) return_err_syntax(false, ptr - hdr);
+ }
+ }
+
+ /* JSON pointer is resolved, insert or replace target value */
+ ctn_len = unsafe_yyjson_get_len(ctn);
+ if (ctn_type == YYJSON_TYPE_OBJ) {
+ if (ctx) ctx->ctn = ctn;
+ if (!val || insert_new) {
+ /* insert new key-value pair */
+ key = ptr_new_key(token, token_len, esc, doc);
+ if (unlikely(!key)) return_err_alloc(false);
+ if (ctx) ctx->pre = ctn_len ? (yyjson_mut_val *)ctn->uni.ptr : key;
+ unsafe_yyjson_mut_obj_add(ctn, key, new_val, ctn_len);
+ } else {
+ /* replace exist value */
+ key = pre->next->next;
+ if (ctx) ctx->pre = pre;
+ if (ctx) ctx->old = val;
+ yyjson_mut_obj_put(ctn, key, new_val);
+ }
+ } else {
+ /* array */
+ if (ctx && (val || idx_is_last)) ctx->ctn = ctn;
+ if (insert_new) {
+ /* append new value */
+ if (val) {
+ pre->next = new_val;
+ new_val->next = val;
+ if (ctx) ctx->pre = pre;
+ unsafe_yyjson_set_len(ctn, ctn_len + 1);
+ } else if (idx_is_last) {
+ if (ctx) ctx->pre = ctn_len ?
+ (yyjson_mut_val *)ctn->uni.ptr : new_val;
+ yyjson_mut_arr_append(ctn, new_val);
+ } else {
+ return_err_resolve(false, token - hdr);
+ }
+ } else {
+ /* replace exist value */
+ if (!val) return_err_resolve(false, token - hdr);
+ if (ctn_len > 1) {
+ new_val->next = val->next;
+ pre->next = new_val;
+ if (ctn->uni.ptr == val) ctn->uni.ptr = new_val;
+ } else {
+ new_val->next = new_val;
+ ctn->uni.ptr = new_val;
+ pre = new_val;
+ }
+ if (ctx) ctx->pre = pre;
+ if (ctx) ctx->old = val;
+ }
+ }
+
+ /* all operations are completed, attach the new components to the target */
+ if (unlikely(sep_ctn)) {
+ if (sep_key) yyjson_mut_obj_add(sep_ctn, sep_key, sep_val);
+ else yyjson_mut_arr_append(sep_ctn, sep_val);
+ }
+ return true;
+}
+
+yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex(
+ yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
+
+ yyjson_mut_val *cur_val;
+ yyjson_ptr_ctx cur_ctx;
+ memset(&cur_ctx, 0, sizeof(cur_ctx));
+ if (!ctx) ctx = &cur_ctx;
+ cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err);
+ if (!cur_val) return NULL;
+
+ if (yyjson_mut_is_obj(ctx->ctn)) {
+ yyjson_mut_val *key = ctx->pre->next->next;
+ yyjson_mut_obj_put(ctx->ctn, key, new_val);
+ } else {
+ yyjson_ptr_ctx_replace(ctx, new_val);
+ }
+ ctx->old = cur_val;
+ return cur_val;
+}
+
+yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_mut_val *cur_val;
+ yyjson_ptr_ctx cur_ctx;
+ memset(&cur_ctx, 0, sizeof(cur_ctx));
+ if (!ctx) ctx = &cur_ctx;
+ cur_val = unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err);
+ if (cur_val) {
+ if (yyjson_mut_is_obj(ctx->ctn)) {
+ yyjson_mut_val *key = ctx->pre->next->next;
+ yyjson_mut_obj_put(ctx->ctn, key, NULL);
+ } else {
+ yyjson_ptr_ctx_remove(ctx);
+ }
+ ctx->pre = NULL;
+ ctx->old = cur_val;
+ }
+ return cur_val;
+}
+
+/* macros for yyjson_ptr */
+#undef return_err
+#undef return_err_resolve
+#undef return_err_syntax
+#undef return_err_alloc
+
+
+
+/*==============================================================================
+ * JSON Patch API (RFC 6902)
+ *============================================================================*/
+
+/* JSON Patch operation */
+typedef enum patch_op {
+ PATCH_OP_ADD, /* path, value */
+ PATCH_OP_REMOVE, /* path */
+ PATCH_OP_REPLACE, /* path, value */
+ PATCH_OP_MOVE, /* from, path */
+ PATCH_OP_COPY, /* from, path */
+ PATCH_OP_TEST, /* path, value */
+ PATCH_OP_NONE /* invalid */
+} patch_op;
+
+static patch_op patch_op_get(yyjson_val *op) {
+ const char *str = op->uni.str;
+ switch (unsafe_yyjson_get_len(op)) {
+ case 3:
+ if (!memcmp(str, "add", 3)) return PATCH_OP_ADD;
+ return PATCH_OP_NONE;
+ case 4:
+ if (!memcmp(str, "move", 4)) return PATCH_OP_MOVE;
+ if (!memcmp(str, "copy", 4)) return PATCH_OP_COPY;
+ if (!memcmp(str, "test", 4)) return PATCH_OP_TEST;
+ return PATCH_OP_NONE;
+ case 6:
+ if (!memcmp(str, "remove", 6)) return PATCH_OP_REMOVE;
+ return PATCH_OP_NONE;
+ case 7:
+ if (!memcmp(str, "replace", 7)) return PATCH_OP_REPLACE;
+ return PATCH_OP_NONE;
+ default:
+ return PATCH_OP_NONE;
+ }
+}
+
+/* macros for yyjson_patch */
+#define return_err(_code, _msg) do { \
+ if (err->ptr.code == YYJSON_PTR_ERR_MEMORY_ALLOCATION) { \
+ err->code = YYJSON_PATCH_ERROR_MEMORY_ALLOCATION; \
+ err->msg = _msg; \
+ memset(&err->ptr, 0, sizeof(yyjson_ptr_err)); \
+ } else { \
+ err->code = YYJSON_PATCH_ERROR_##_code; \
+ err->msg = _msg; \
+ err->idx = iter.idx ? iter.idx - 1 : 0; \
+ } \
+ return NULL; \
+} while (false)
+
+#define return_err_copy() \
+ return_err(MEMORY_ALLOCATION, "failed to copy value")
+#define return_err_key(_key) \
+ return_err(MISSING_KEY, "missing key " _key)
+#define return_err_val(_key) \
+ return_err(INVALID_MEMBER, "invalid member " _key)
+
+#define ptr_get(_ptr) yyjson_mut_ptr_getx( \
+ root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr)
+#define ptr_add(_ptr, _val) yyjson_mut_ptr_addx( \
+ root, _ptr->uni.str, _ptr##_len, _val, doc, false, NULL, &err->ptr)
+#define ptr_remove(_ptr) yyjson_mut_ptr_removex( \
+ root, _ptr->uni.str, _ptr##_len, NULL, &err->ptr)
+#define ptr_replace(_ptr, _val)yyjson_mut_ptr_replacex( \
+ root, _ptr->uni.str, _ptr##_len, _val, NULL, &err->ptr)
+
+yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc,
+ yyjson_val *orig,
+ yyjson_val *patch,
+ yyjson_patch_err *err) {
+
+ yyjson_mut_val *root;
+ yyjson_val *obj;
+ yyjson_arr_iter iter;
+ yyjson_patch_err err_tmp;
+ if (!err) err = &err_tmp;
+ memset(err, 0, sizeof(*err));
+ memset(&iter, 0, sizeof(iter));
+
+ if (unlikely(!doc || !orig || !patch)) {
+ return_err(INVALID_PARAMETER, "input parameter is NULL");
+ }
+ if (unlikely(!yyjson_is_arr(patch))) {
+ return_err(INVALID_PARAMETER, "input patch is not array");
+ }
+ root = yyjson_val_mut_copy(doc, orig);
+ if (unlikely(!root)) return_err_copy();
+
+ /* iterate through the patch array */
+ yyjson_arr_iter_init(patch, &iter);
+ while ((obj = yyjson_arr_iter_next(&iter))) {
+ patch_op op_enum;
+ yyjson_val *op, *path, *from = NULL, *value;
+ yyjson_mut_val *val = NULL, *test;
+ usize path_len, from_len = 0;
+ if (unlikely(!unsafe_yyjson_is_obj(obj))) {
+ return_err(INVALID_OPERATION, "JSON patch operation is not object");
+ }
+
+ /* get required member: op */
+ op = yyjson_obj_get(obj, "op");
+ if (unlikely(!op)) return_err_key("`op`");
+ if (unlikely(!yyjson_is_str(op))) return_err_val("`op`");
+ op_enum = patch_op_get(op);
+
+ /* get required member: path */
+ path = yyjson_obj_get(obj, "path");
+ if (unlikely(!path)) return_err_key("`path`");
+ if (unlikely(!yyjson_is_str(path))) return_err_val("`path`");
+ path_len = unsafe_yyjson_get_len(path);
+
+ /* get required member: value, from */
+ switch ((int)op_enum) {
+ case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST:
+ value = yyjson_obj_get(obj, "value");
+ if (unlikely(!value)) return_err_key("`value`");
+ val = yyjson_val_mut_copy(doc, value);
+ if (unlikely(!val)) return_err_copy();
+ break;
+ case PATCH_OP_MOVE: case PATCH_OP_COPY:
+ from = yyjson_obj_get(obj, "from");
+ if (unlikely(!from)) return_err_key("`from`");
+ if (unlikely(!yyjson_is_str(from))) return_err_val("`from`");
+ from_len = unsafe_yyjson_get_len(from);
+ break;
+ default:
+ break;
+ }
+
+ /* perform an operation */
+ switch ((int)op_enum) {
+ case PATCH_OP_ADD: /* add(path, val) */
+ if (unlikely(path_len == 0)) { root = val; break; }
+ if (unlikely(!ptr_add(path, val))) {
+ return_err(POINTER, "failed to add `path`");
+ }
+ break;
+ case PATCH_OP_REMOVE: /* remove(path) */
+ if (unlikely(!ptr_remove(path))) {
+ return_err(POINTER, "failed to remove `path`");
+ }
+ break;
+ case PATCH_OP_REPLACE: /* replace(path, val) */
+ if (unlikely(path_len == 0)) { root = val; break; }
+ if (unlikely(!ptr_replace(path, val))) {
+ return_err(POINTER, "failed to replace `path`");
+ }
+ break;
+ case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */
+ if (unlikely(from_len == 0 && path_len == 0)) break;
+ val = ptr_remove(from);
+ if (unlikely(!val)) {
+ return_err(POINTER, "failed to remove `from`");
+ }
+ if (unlikely(path_len == 0)) { root = val; break; }
+ if (unlikely(!ptr_add(path, val))) {
+ return_err(POINTER, "failed to add `path`");
+ }
+ break;
+ case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */
+ val = ptr_get(from);
+ if (unlikely(!val)) {
+ return_err(POINTER, "failed to get `from`");
+ }
+ if (unlikely(path_len == 0)) { root = val; break; }
+ val = yyjson_mut_val_mut_copy(doc, val);
+ if (unlikely(!val)) return_err_copy();
+ if (unlikely(!ptr_add(path, val))) {
+ return_err(POINTER, "failed to add `path`");
+ }
+ break;
+ case PATCH_OP_TEST: /* test = get(path), test.eq(val) */
+ test = ptr_get(path);
+ if (unlikely(!test)) {
+ return_err(POINTER, "failed to get `path`");
+ }
+ if (unlikely(!yyjson_mut_equals(val, test))) {
+ return_err(EQUAL, "failed to test equal");
+ }
+ break;
+ default:
+ return_err(INVALID_MEMBER, "unsupported `op`");
+ }
+ }
+ return root;
+}
+
+yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc,
+ yyjson_mut_val *orig,
+ yyjson_mut_val *patch,
+ yyjson_patch_err *err) {
+ yyjson_mut_val *root, *obj;
+ yyjson_mut_arr_iter iter;
+ yyjson_patch_err err_tmp;
+ if (!err) err = &err_tmp;
+ memset(err, 0, sizeof(*err));
+ memset(&iter, 0, sizeof(iter));
+
+ if (unlikely(!doc || !orig || !patch)) {
+ return_err(INVALID_PARAMETER, "input parameter is NULL");
+ }
+ if (unlikely(!yyjson_mut_is_arr(patch))) {
+ return_err(INVALID_PARAMETER, "input patch is not array");
+ }
+ root = yyjson_mut_val_mut_copy(doc, orig);
+ if (unlikely(!root)) return_err_copy();
+
+ /* iterate through the patch array */
+ yyjson_mut_arr_iter_init(patch, &iter);
+ while ((obj = yyjson_mut_arr_iter_next(&iter))) {
+ patch_op op_enum;
+ yyjson_mut_val *op, *path, *from = NULL, *value;
+ yyjson_mut_val *val = NULL, *test;
+ usize path_len, from_len = 0;
+ if (!unsafe_yyjson_is_obj(obj)) {
+ return_err(INVALID_OPERATION, "JSON patch operation is not object");
+ }
+
+ /* get required member: op */
+ op = yyjson_mut_obj_get(obj, "op");
+ if (unlikely(!op)) return_err_key("`op`");
+ if (unlikely(!yyjson_mut_is_str(op))) return_err_val("`op`");
+ op_enum = patch_op_get((yyjson_val *)(void *)op);
+
+ /* get required member: path */
+ path = yyjson_mut_obj_get(obj, "path");
+ if (unlikely(!path)) return_err_key("`path`");
+ if (unlikely(!yyjson_mut_is_str(path))) return_err_val("`path`");
+ path_len = unsafe_yyjson_get_len(path);
+
+ /* get required member: value, from */
+ switch ((int)op_enum) {
+ case PATCH_OP_ADD: case PATCH_OP_REPLACE: case PATCH_OP_TEST:
+ value = yyjson_mut_obj_get(obj, "value");
+ if (unlikely(!value)) return_err_key("`value`");
+ val = yyjson_mut_val_mut_copy(doc, value);
+ if (unlikely(!val)) return_err_copy();
+ break;
+ case PATCH_OP_MOVE: case PATCH_OP_COPY:
+ from = yyjson_mut_obj_get(obj, "from");
+ if (unlikely(!from)) return_err_key("`from`");
+ if (unlikely(!yyjson_mut_is_str(from))) {
+ return_err_val("`from`");
+ }
+ from_len = unsafe_yyjson_get_len(from);
+ break;
+ default:
+ break;
+ }
+
+ /* perform an operation */
+ switch ((int)op_enum) {
+ case PATCH_OP_ADD: /* add(path, val) */
+ if (unlikely(path_len == 0)) { root = val; break; }
+ if (unlikely(!ptr_add(path, val))) {
+ return_err(POINTER, "failed to add `path`");
+ }
+ break;
+ case PATCH_OP_REMOVE: /* remove(path) */
+ if (unlikely(!ptr_remove(path))) {
+ return_err(POINTER, "failed to remove `path`");
+ }
+ break;
+ case PATCH_OP_REPLACE: /* replace(path, val) */
+ if (unlikely(path_len == 0)) { root = val; break; }
+ if (unlikely(!ptr_replace(path, val))) {
+ return_err(POINTER, "failed to replace `path`");
+ }
+ break;
+ case PATCH_OP_MOVE: /* val = remove(from), add(path, val) */
+ if (unlikely(from_len == 0 && path_len == 0)) break;
+ val = ptr_remove(from);
+ if (unlikely(!val)) {
+ return_err(POINTER, "failed to remove `from`");
+ }
+ if (unlikely(path_len == 0)) { root = val; break; }
+ if (unlikely(!ptr_add(path, val))) {
+ return_err(POINTER, "failed to add `path`");
+ }
+ break;
+ case PATCH_OP_COPY: /* val = get(from).copy, add(path, val) */
+ val = ptr_get(from);
+ if (unlikely(!val)) {
+ return_err(POINTER, "failed to get `from`");
+ }
+ if (unlikely(path_len == 0)) { root = val; break; }
+ val = yyjson_mut_val_mut_copy(doc, val);
+ if (unlikely(!val)) return_err_copy();
+ if (unlikely(!ptr_add(path, val))) {
+ return_err(POINTER, "failed to add `path`");
+ }
+ break;
+ case PATCH_OP_TEST: /* test = get(path), test.eq(val) */
+ test = ptr_get(path);
+ if (unlikely(!test)) {
+ return_err(POINTER, "failed to get `path`");
+ }
+ if (unlikely(!yyjson_mut_equals(val, test))) {
+ return_err(EQUAL, "failed to test equal");
+ }
+ break;
+ default:
+ return_err(INVALID_MEMBER, "unsupported `op`");
+ }
+ }
+ return root;
+}
+
+/* macros for yyjson_patch */
+#undef return_err
+#undef return_err_copy
+#undef return_err_key
+#undef return_err_val
+#undef ptr_get
+#undef ptr_add
+#undef ptr_remove
+#undef ptr_replace
+
+
+
+/*==============================================================================
+ * JSON Merge-Patch API (RFC 7386)
+ *============================================================================*/
+
+yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc,
+ yyjson_val *orig,
+ yyjson_val *patch) {
+ usize idx, max;
+ yyjson_val *key, *orig_val, *patch_val, local_orig;
+ yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val;
+
+ if (unlikely(!yyjson_is_obj(patch))) {
+ return yyjson_val_mut_copy(doc, patch);
+ }
+
+ builder = yyjson_mut_obj(doc);
+ if (unlikely(!builder)) return NULL;
+
+ memset(&local_orig, 0, sizeof(local_orig));
+ if (!yyjson_is_obj(orig)) {
+ orig = &local_orig;
+ orig->tag = builder->tag;
+ orig->uni = builder->uni;
+ }
+
+ /* If orig is contributing, copy any items not modified by the patch */
+ if (orig != &local_orig) {
+ yyjson_obj_foreach(orig, idx, max, key, orig_val) {
+ patch_val = yyjson_obj_getn(patch,
+ unsafe_yyjson_get_str(key),
+ unsafe_yyjson_get_len(key));
+ if (!patch_val) {
+ mut_key = yyjson_val_mut_copy(doc, key);
+ mut_val = yyjson_val_mut_copy(doc, orig_val);
+ if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL;
+ }
+ }
+ }
+
+ /* Merge items modified by the patch. */
+ yyjson_obj_foreach(patch, idx, max, key, patch_val) {
+ /* null indicates the field is removed. */
+ if (unsafe_yyjson_is_null(patch_val)) {
+ continue;
+ }
+ mut_key = yyjson_val_mut_copy(doc, key);
+ orig_val = yyjson_obj_getn(orig,
+ unsafe_yyjson_get_str(key),
+ unsafe_yyjson_get_len(key));
+ merged_val = yyjson_merge_patch(doc, orig_val, patch_val);
+ if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL;
+ }
+
+ return builder;
+}
+
+yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc,
+ yyjson_mut_val *orig,
+ yyjson_mut_val *patch) {
+ usize idx, max;
+ yyjson_mut_val *key, *orig_val, *patch_val, local_orig;
+ yyjson_mut_val *builder, *mut_key, *mut_val, *merged_val;
+
+ if (unlikely(!yyjson_mut_is_obj(patch))) {
+ return yyjson_mut_val_mut_copy(doc, patch);
+ }
+
+ builder = yyjson_mut_obj(doc);
+ if (unlikely(!builder)) return NULL;
+
+ memset(&local_orig, 0, sizeof(local_orig));
+ if (!yyjson_mut_is_obj(orig)) {
+ orig = &local_orig;
+ orig->tag = builder->tag;
+ orig->uni = builder->uni;
+ }
+
+ /* If orig is contributing, copy any items not modified by the patch */
+ if (orig != &local_orig) {
+ yyjson_mut_obj_foreach(orig, idx, max, key, orig_val) {
+ patch_val = yyjson_mut_obj_getn(patch,
+ unsafe_yyjson_get_str(key),
+ unsafe_yyjson_get_len(key));
+ if (!patch_val) {
+ mut_key = yyjson_mut_val_mut_copy(doc, key);
+ mut_val = yyjson_mut_val_mut_copy(doc, orig_val);
+ if (!yyjson_mut_obj_add(builder, mut_key, mut_val)) return NULL;
+ }
+ }
+ }
+
+ /* Merge items modified by the patch. */
+ yyjson_mut_obj_foreach(patch, idx, max, key, patch_val) {
+ /* null indicates the field is removed. */
+ if (unsafe_yyjson_is_null(patch_val)) {
+ continue;
+ }
+ mut_key = yyjson_mut_val_mut_copy(doc, key);
+ orig_val = yyjson_mut_obj_getn(orig,
+ unsafe_yyjson_get_str(key),
+ unsafe_yyjson_get_len(key));
+ merged_val = yyjson_mut_merge_patch(doc, orig_val, patch_val);
+ if (!yyjson_mut_obj_add(builder, mut_key, merged_val)) return NULL;
+ }
+
+ return builder;
+}
+
+#endif /* YYJSON_DISABLE_UTILS */
+
+
+
+/*==============================================================================
+ * Power10 Lookup Table
+ * These data are used by the floating-point number reader and writer.
+ *============================================================================*/
+
+#if (!YYJSON_DISABLE_READER || !YYJSON_DISABLE_WRITER) && \
+ (!YYJSON_DISABLE_FAST_FP_CONV)
+
+/** Minimum decimal exponent in pow10_sig_table. */
+#define POW10_SIG_TABLE_MIN_EXP -343
+
+/** Maximum decimal exponent in pow10_sig_table. */
+#define POW10_SIG_TABLE_MAX_EXP 324
+
+/** Minimum exact decimal exponent in pow10_sig_table */
+#define POW10_SIG_TABLE_MIN_EXACT_EXP 0
+
+/** Maximum exact decimal exponent in pow10_sig_table */
+#define POW10_SIG_TABLE_MAX_EXACT_EXP 55
+
+/** Normalized significant 128 bits of pow10, no rounded up (size: 10.4KB).
+ This lookup table is used by both the double number reader and writer.
+ (generate with misc/make_tables.c) */
+static const u64 pow10_sig_table[] = {
+ U64(0xBF29DCAB, 0xA82FDEAE), U64(0x7432EE87, 0x3880FC33), /* ~= 10^-343 */
+ U64(0xEEF453D6, 0x923BD65A), U64(0x113FAA29, 0x06A13B3F), /* ~= 10^-342 */
+ U64(0x9558B466, 0x1B6565F8), U64(0x4AC7CA59, 0xA424C507), /* ~= 10^-341 */
+ U64(0xBAAEE17F, 0xA23EBF76), U64(0x5D79BCF0, 0x0D2DF649), /* ~= 10^-340 */
+ U64(0xE95A99DF, 0x8ACE6F53), U64(0xF4D82C2C, 0x107973DC), /* ~= 10^-339 */
+ U64(0x91D8A02B, 0xB6C10594), U64(0x79071B9B, 0x8A4BE869), /* ~= 10^-338 */
+ U64(0xB64EC836, 0xA47146F9), U64(0x9748E282, 0x6CDEE284), /* ~= 10^-337 */
+ U64(0xE3E27A44, 0x4D8D98B7), U64(0xFD1B1B23, 0x08169B25), /* ~= 10^-336 */
+ U64(0x8E6D8C6A, 0xB0787F72), U64(0xFE30F0F5, 0xE50E20F7), /* ~= 10^-335 */
+ U64(0xB208EF85, 0x5C969F4F), U64(0xBDBD2D33, 0x5E51A935), /* ~= 10^-334 */
+ U64(0xDE8B2B66, 0xB3BC4723), U64(0xAD2C7880, 0x35E61382), /* ~= 10^-333 */
+ U64(0x8B16FB20, 0x3055AC76), U64(0x4C3BCB50, 0x21AFCC31), /* ~= 10^-332 */
+ U64(0xADDCB9E8, 0x3C6B1793), U64(0xDF4ABE24, 0x2A1BBF3D), /* ~= 10^-331 */
+ U64(0xD953E862, 0x4B85DD78), U64(0xD71D6DAD, 0x34A2AF0D), /* ~= 10^-330 */
+ U64(0x87D4713D, 0x6F33AA6B), U64(0x8672648C, 0x40E5AD68), /* ~= 10^-329 */
+ U64(0xA9C98D8C, 0xCB009506), U64(0x680EFDAF, 0x511F18C2), /* ~= 10^-328 */
+ U64(0xD43BF0EF, 0xFDC0BA48), U64(0x0212BD1B, 0x2566DEF2), /* ~= 10^-327 */
+ U64(0x84A57695, 0xFE98746D), U64(0x014BB630, 0xF7604B57), /* ~= 10^-326 */
+ U64(0xA5CED43B, 0x7E3E9188), U64(0x419EA3BD, 0x35385E2D), /* ~= 10^-325 */
+ U64(0xCF42894A, 0x5DCE35EA), U64(0x52064CAC, 0x828675B9), /* ~= 10^-324 */
+ U64(0x818995CE, 0x7AA0E1B2), U64(0x7343EFEB, 0xD1940993), /* ~= 10^-323 */
+ U64(0xA1EBFB42, 0x19491A1F), U64(0x1014EBE6, 0xC5F90BF8), /* ~= 10^-322 */
+ U64(0xCA66FA12, 0x9F9B60A6), U64(0xD41A26E0, 0x77774EF6), /* ~= 10^-321 */
+ U64(0xFD00B897, 0x478238D0), U64(0x8920B098, 0x955522B4), /* ~= 10^-320 */
+ U64(0x9E20735E, 0x8CB16382), U64(0x55B46E5F, 0x5D5535B0), /* ~= 10^-319 */
+ U64(0xC5A89036, 0x2FDDBC62), U64(0xEB2189F7, 0x34AA831D), /* ~= 10^-318 */
+ U64(0xF712B443, 0xBBD52B7B), U64(0xA5E9EC75, 0x01D523E4), /* ~= 10^-317 */
+ U64(0x9A6BB0AA, 0x55653B2D), U64(0x47B233C9, 0x2125366E), /* ~= 10^-316 */
+ U64(0xC1069CD4, 0xEABE89F8), U64(0x999EC0BB, 0x696E840A), /* ~= 10^-315 */
+ U64(0xF148440A, 0x256E2C76), U64(0xC00670EA, 0x43CA250D), /* ~= 10^-314 */
+ U64(0x96CD2A86, 0x5764DBCA), U64(0x38040692, 0x6A5E5728), /* ~= 10^-313 */
+ U64(0xBC807527, 0xED3E12BC), U64(0xC6050837, 0x04F5ECF2), /* ~= 10^-312 */
+ U64(0xEBA09271, 0xE88D976B), U64(0xF7864A44, 0xC633682E), /* ~= 10^-311 */
+ U64(0x93445B87, 0x31587EA3), U64(0x7AB3EE6A, 0xFBE0211D), /* ~= 10^-310 */
+ U64(0xB8157268, 0xFDAE9E4C), U64(0x5960EA05, 0xBAD82964), /* ~= 10^-309 */
+ U64(0xE61ACF03, 0x3D1A45DF), U64(0x6FB92487, 0x298E33BD), /* ~= 10^-308 */
+ U64(0x8FD0C162, 0x06306BAB), U64(0xA5D3B6D4, 0x79F8E056), /* ~= 10^-307 */
+ U64(0xB3C4F1BA, 0x87BC8696), U64(0x8F48A489, 0x9877186C), /* ~= 10^-306 */
+ U64(0xE0B62E29, 0x29ABA83C), U64(0x331ACDAB, 0xFE94DE87), /* ~= 10^-305 */
+ U64(0x8C71DCD9, 0xBA0B4925), U64(0x9FF0C08B, 0x7F1D0B14), /* ~= 10^-304 */
+ U64(0xAF8E5410, 0x288E1B6F), U64(0x07ECF0AE, 0x5EE44DD9), /* ~= 10^-303 */
+ U64(0xDB71E914, 0x32B1A24A), U64(0xC9E82CD9, 0xF69D6150), /* ~= 10^-302 */
+ U64(0x892731AC, 0x9FAF056E), U64(0xBE311C08, 0x3A225CD2), /* ~= 10^-301 */
+ U64(0xAB70FE17, 0xC79AC6CA), U64(0x6DBD630A, 0x48AAF406), /* ~= 10^-300 */
+ U64(0xD64D3D9D, 0xB981787D), U64(0x092CBBCC, 0xDAD5B108), /* ~= 10^-299 */
+ U64(0x85F04682, 0x93F0EB4E), U64(0x25BBF560, 0x08C58EA5), /* ~= 10^-298 */
+ U64(0xA76C5823, 0x38ED2621), U64(0xAF2AF2B8, 0x0AF6F24E), /* ~= 10^-297 */
+ U64(0xD1476E2C, 0x07286FAA), U64(0x1AF5AF66, 0x0DB4AEE1), /* ~= 10^-296 */
+ U64(0x82CCA4DB, 0x847945CA), U64(0x50D98D9F, 0xC890ED4D), /* ~= 10^-295 */
+ U64(0xA37FCE12, 0x6597973C), U64(0xE50FF107, 0xBAB528A0), /* ~= 10^-294 */
+ U64(0xCC5FC196, 0xFEFD7D0C), U64(0x1E53ED49, 0xA96272C8), /* ~= 10^-293 */
+ U64(0xFF77B1FC, 0xBEBCDC4F), U64(0x25E8E89C, 0x13BB0F7A), /* ~= 10^-292 */
+ U64(0x9FAACF3D, 0xF73609B1), U64(0x77B19161, 0x8C54E9AC), /* ~= 10^-291 */
+ U64(0xC795830D, 0x75038C1D), U64(0xD59DF5B9, 0xEF6A2417), /* ~= 10^-290 */
+ U64(0xF97AE3D0, 0xD2446F25), U64(0x4B057328, 0x6B44AD1D), /* ~= 10^-289 */
+ U64(0x9BECCE62, 0x836AC577), U64(0x4EE367F9, 0x430AEC32), /* ~= 10^-288 */
+ U64(0xC2E801FB, 0x244576D5), U64(0x229C41F7, 0x93CDA73F), /* ~= 10^-287 */
+ U64(0xF3A20279, 0xED56D48A), U64(0x6B435275, 0x78C1110F), /* ~= 10^-286 */
+ U64(0x9845418C, 0x345644D6), U64(0x830A1389, 0x6B78AAA9), /* ~= 10^-285 */
+ U64(0xBE5691EF, 0x416BD60C), U64(0x23CC986B, 0xC656D553), /* ~= 10^-284 */
+ U64(0xEDEC366B, 0x11C6CB8F), U64(0x2CBFBE86, 0xB7EC8AA8), /* ~= 10^-283 */
+ U64(0x94B3A202, 0xEB1C3F39), U64(0x7BF7D714, 0x32F3D6A9), /* ~= 10^-282 */
+ U64(0xB9E08A83, 0xA5E34F07), U64(0xDAF5CCD9, 0x3FB0CC53), /* ~= 10^-281 */
+ U64(0xE858AD24, 0x8F5C22C9), U64(0xD1B3400F, 0x8F9CFF68), /* ~= 10^-280 */
+ U64(0x91376C36, 0xD99995BE), U64(0x23100809, 0xB9C21FA1), /* ~= 10^-279 */
+ U64(0xB5854744, 0x8FFFFB2D), U64(0xABD40A0C, 0x2832A78A), /* ~= 10^-278 */
+ U64(0xE2E69915, 0xB3FFF9F9), U64(0x16C90C8F, 0x323F516C), /* ~= 10^-277 */
+ U64(0x8DD01FAD, 0x907FFC3B), U64(0xAE3DA7D9, 0x7F6792E3), /* ~= 10^-276 */
+ U64(0xB1442798, 0xF49FFB4A), U64(0x99CD11CF, 0xDF41779C), /* ~= 10^-275 */
+ U64(0xDD95317F, 0x31C7FA1D), U64(0x40405643, 0xD711D583), /* ~= 10^-274 */
+ U64(0x8A7D3EEF, 0x7F1CFC52), U64(0x482835EA, 0x666B2572), /* ~= 10^-273 */
+ U64(0xAD1C8EAB, 0x5EE43B66), U64(0xDA324365, 0x0005EECF), /* ~= 10^-272 */
+ U64(0xD863B256, 0x369D4A40), U64(0x90BED43E, 0x40076A82), /* ~= 10^-271 */
+ U64(0x873E4F75, 0xE2224E68), U64(0x5A7744A6, 0xE804A291), /* ~= 10^-270 */
+ U64(0xA90DE353, 0x5AAAE202), U64(0x711515D0, 0xA205CB36), /* ~= 10^-269 */
+ U64(0xD3515C28, 0x31559A83), U64(0x0D5A5B44, 0xCA873E03), /* ~= 10^-268 */
+ U64(0x8412D999, 0x1ED58091), U64(0xE858790A, 0xFE9486C2), /* ~= 10^-267 */
+ U64(0xA5178FFF, 0x668AE0B6), U64(0x626E974D, 0xBE39A872), /* ~= 10^-266 */
+ U64(0xCE5D73FF, 0x402D98E3), U64(0xFB0A3D21, 0x2DC8128F), /* ~= 10^-265 */
+ U64(0x80FA687F, 0x881C7F8E), U64(0x7CE66634, 0xBC9D0B99), /* ~= 10^-264 */
+ U64(0xA139029F, 0x6A239F72), U64(0x1C1FFFC1, 0xEBC44E80), /* ~= 10^-263 */
+ U64(0xC9874347, 0x44AC874E), U64(0xA327FFB2, 0x66B56220), /* ~= 10^-262 */
+ U64(0xFBE91419, 0x15D7A922), U64(0x4BF1FF9F, 0x0062BAA8), /* ~= 10^-261 */
+ U64(0x9D71AC8F, 0xADA6C9B5), U64(0x6F773FC3, 0x603DB4A9), /* ~= 10^-260 */
+ U64(0xC4CE17B3, 0x99107C22), U64(0xCB550FB4, 0x384D21D3), /* ~= 10^-259 */
+ U64(0xF6019DA0, 0x7F549B2B), U64(0x7E2A53A1, 0x46606A48), /* ~= 10^-258 */
+ U64(0x99C10284, 0x4F94E0FB), U64(0x2EDA7444, 0xCBFC426D), /* ~= 10^-257 */
+ U64(0xC0314325, 0x637A1939), U64(0xFA911155, 0xFEFB5308), /* ~= 10^-256 */
+ U64(0xF03D93EE, 0xBC589F88), U64(0x793555AB, 0x7EBA27CA), /* ~= 10^-255 */
+ U64(0x96267C75, 0x35B763B5), U64(0x4BC1558B, 0x2F3458DE), /* ~= 10^-254 */
+ U64(0xBBB01B92, 0x83253CA2), U64(0x9EB1AAED, 0xFB016F16), /* ~= 10^-253 */
+ U64(0xEA9C2277, 0x23EE8BCB), U64(0x465E15A9, 0x79C1CADC), /* ~= 10^-252 */
+ U64(0x92A1958A, 0x7675175F), U64(0x0BFACD89, 0xEC191EC9), /* ~= 10^-251 */
+ U64(0xB749FAED, 0x14125D36), U64(0xCEF980EC, 0x671F667B), /* ~= 10^-250 */
+ U64(0xE51C79A8, 0x5916F484), U64(0x82B7E127, 0x80E7401A), /* ~= 10^-249 */
+ U64(0x8F31CC09, 0x37AE58D2), U64(0xD1B2ECB8, 0xB0908810), /* ~= 10^-248 */
+ U64(0xB2FE3F0B, 0x8599EF07), U64(0x861FA7E6, 0xDCB4AA15), /* ~= 10^-247 */
+ U64(0xDFBDCECE, 0x67006AC9), U64(0x67A791E0, 0x93E1D49A), /* ~= 10^-246 */
+ U64(0x8BD6A141, 0x006042BD), U64(0xE0C8BB2C, 0x5C6D24E0), /* ~= 10^-245 */
+ U64(0xAECC4991, 0x4078536D), U64(0x58FAE9F7, 0x73886E18), /* ~= 10^-244 */
+ U64(0xDA7F5BF5, 0x90966848), U64(0xAF39A475, 0x506A899E), /* ~= 10^-243 */
+ U64(0x888F9979, 0x7A5E012D), U64(0x6D8406C9, 0x52429603), /* ~= 10^-242 */
+ U64(0xAAB37FD7, 0xD8F58178), U64(0xC8E5087B, 0xA6D33B83), /* ~= 10^-241 */
+ U64(0xD5605FCD, 0xCF32E1D6), U64(0xFB1E4A9A, 0x90880A64), /* ~= 10^-240 */
+ U64(0x855C3BE0, 0xA17FCD26), U64(0x5CF2EEA0, 0x9A55067F), /* ~= 10^-239 */
+ U64(0xA6B34AD8, 0xC9DFC06F), U64(0xF42FAA48, 0xC0EA481E), /* ~= 10^-238 */
+ U64(0xD0601D8E, 0xFC57B08B), U64(0xF13B94DA, 0xF124DA26), /* ~= 10^-237 */
+ U64(0x823C1279, 0x5DB6CE57), U64(0x76C53D08, 0xD6B70858), /* ~= 10^-236 */
+ U64(0xA2CB1717, 0xB52481ED), U64(0x54768C4B, 0x0C64CA6E), /* ~= 10^-235 */
+ U64(0xCB7DDCDD, 0xA26DA268), U64(0xA9942F5D, 0xCF7DFD09), /* ~= 10^-234 */
+ U64(0xFE5D5415, 0x0B090B02), U64(0xD3F93B35, 0x435D7C4C), /* ~= 10^-233 */
+ U64(0x9EFA548D, 0x26E5A6E1), U64(0xC47BC501, 0x4A1A6DAF), /* ~= 10^-232 */
+ U64(0xC6B8E9B0, 0x709F109A), U64(0x359AB641, 0x9CA1091B), /* ~= 10^-231 */
+ U64(0xF867241C, 0x8CC6D4C0), U64(0xC30163D2, 0x03C94B62), /* ~= 10^-230 */
+ U64(0x9B407691, 0xD7FC44F8), U64(0x79E0DE63, 0x425DCF1D), /* ~= 10^-229 */
+ U64(0xC2109436, 0x4DFB5636), U64(0x985915FC, 0x12F542E4), /* ~= 10^-228 */
+ U64(0xF294B943, 0xE17A2BC4), U64(0x3E6F5B7B, 0x17B2939D), /* ~= 10^-227 */
+ U64(0x979CF3CA, 0x6CEC5B5A), U64(0xA705992C, 0xEECF9C42), /* ~= 10^-226 */
+ U64(0xBD8430BD, 0x08277231), U64(0x50C6FF78, 0x2A838353), /* ~= 10^-225 */
+ U64(0xECE53CEC, 0x4A314EBD), U64(0xA4F8BF56, 0x35246428), /* ~= 10^-224 */
+ U64(0x940F4613, 0xAE5ED136), U64(0x871B7795, 0xE136BE99), /* ~= 10^-223 */
+ U64(0xB9131798, 0x99F68584), U64(0x28E2557B, 0x59846E3F), /* ~= 10^-222 */
+ U64(0xE757DD7E, 0xC07426E5), U64(0x331AEADA, 0x2FE589CF), /* ~= 10^-221 */
+ U64(0x9096EA6F, 0x3848984F), U64(0x3FF0D2C8, 0x5DEF7621), /* ~= 10^-220 */
+ U64(0xB4BCA50B, 0x065ABE63), U64(0x0FED077A, 0x756B53A9), /* ~= 10^-219 */
+ U64(0xE1EBCE4D, 0xC7F16DFB), U64(0xD3E84959, 0x12C62894), /* ~= 10^-218 */
+ U64(0x8D3360F0, 0x9CF6E4BD), U64(0x64712DD7, 0xABBBD95C), /* ~= 10^-217 */
+ U64(0xB080392C, 0xC4349DEC), U64(0xBD8D794D, 0x96AACFB3), /* ~= 10^-216 */
+ U64(0xDCA04777, 0xF541C567), U64(0xECF0D7A0, 0xFC5583A0), /* ~= 10^-215 */
+ U64(0x89E42CAA, 0xF9491B60), U64(0xF41686C4, 0x9DB57244), /* ~= 10^-214 */
+ U64(0xAC5D37D5, 0xB79B6239), U64(0x311C2875, 0xC522CED5), /* ~= 10^-213 */
+ U64(0xD77485CB, 0x25823AC7), U64(0x7D633293, 0x366B828B), /* ~= 10^-212 */
+ U64(0x86A8D39E, 0xF77164BC), U64(0xAE5DFF9C, 0x02033197), /* ~= 10^-211 */
+ U64(0xA8530886, 0xB54DBDEB), U64(0xD9F57F83, 0x0283FDFC), /* ~= 10^-210 */
+ U64(0xD267CAA8, 0x62A12D66), U64(0xD072DF63, 0xC324FD7B), /* ~= 10^-209 */
+ U64(0x8380DEA9, 0x3DA4BC60), U64(0x4247CB9E, 0x59F71E6D), /* ~= 10^-208 */
+ U64(0xA4611653, 0x8D0DEB78), U64(0x52D9BE85, 0xF074E608), /* ~= 10^-207 */
+ U64(0xCD795BE8, 0x70516656), U64(0x67902E27, 0x6C921F8B), /* ~= 10^-206 */
+ U64(0x806BD971, 0x4632DFF6), U64(0x00BA1CD8, 0xA3DB53B6), /* ~= 10^-205 */
+ U64(0xA086CFCD, 0x97BF97F3), U64(0x80E8A40E, 0xCCD228A4), /* ~= 10^-204 */
+ U64(0xC8A883C0, 0xFDAF7DF0), U64(0x6122CD12, 0x8006B2CD), /* ~= 10^-203 */
+ U64(0xFAD2A4B1, 0x3D1B5D6C), U64(0x796B8057, 0x20085F81), /* ~= 10^-202 */
+ U64(0x9CC3A6EE, 0xC6311A63), U64(0xCBE33036, 0x74053BB0), /* ~= 10^-201 */
+ U64(0xC3F490AA, 0x77BD60FC), U64(0xBEDBFC44, 0x11068A9C), /* ~= 10^-200 */
+ U64(0xF4F1B4D5, 0x15ACB93B), U64(0xEE92FB55, 0x15482D44), /* ~= 10^-199 */
+ U64(0x99171105, 0x2D8BF3C5), U64(0x751BDD15, 0x2D4D1C4A), /* ~= 10^-198 */
+ U64(0xBF5CD546, 0x78EEF0B6), U64(0xD262D45A, 0x78A0635D), /* ~= 10^-197 */
+ U64(0xEF340A98, 0x172AACE4), U64(0x86FB8971, 0x16C87C34), /* ~= 10^-196 */
+ U64(0x9580869F, 0x0E7AAC0E), U64(0xD45D35E6, 0xAE3D4DA0), /* ~= 10^-195 */
+ U64(0xBAE0A846, 0xD2195712), U64(0x89748360, 0x59CCA109), /* ~= 10^-194 */
+ U64(0xE998D258, 0x869FACD7), U64(0x2BD1A438, 0x703FC94B), /* ~= 10^-193 */
+ U64(0x91FF8377, 0x5423CC06), U64(0x7B6306A3, 0x4627DDCF), /* ~= 10^-192 */
+ U64(0xB67F6455, 0x292CBF08), U64(0x1A3BC84C, 0x17B1D542), /* ~= 10^-191 */
+ U64(0xE41F3D6A, 0x7377EECA), U64(0x20CABA5F, 0x1D9E4A93), /* ~= 10^-190 */
+ U64(0x8E938662, 0x882AF53E), U64(0x547EB47B, 0x7282EE9C), /* ~= 10^-189 */
+ U64(0xB23867FB, 0x2A35B28D), U64(0xE99E619A, 0x4F23AA43), /* ~= 10^-188 */
+ U64(0xDEC681F9, 0xF4C31F31), U64(0x6405FA00, 0xE2EC94D4), /* ~= 10^-187 */
+ U64(0x8B3C113C, 0x38F9F37E), U64(0xDE83BC40, 0x8DD3DD04), /* ~= 10^-186 */
+ U64(0xAE0B158B, 0x4738705E), U64(0x9624AB50, 0xB148D445), /* ~= 10^-185 */
+ U64(0xD98DDAEE, 0x19068C76), U64(0x3BADD624, 0xDD9B0957), /* ~= 10^-184 */
+ U64(0x87F8A8D4, 0xCFA417C9), U64(0xE54CA5D7, 0x0A80E5D6), /* ~= 10^-183 */
+ U64(0xA9F6D30A, 0x038D1DBC), U64(0x5E9FCF4C, 0xCD211F4C), /* ~= 10^-182 */
+ U64(0xD47487CC, 0x8470652B), U64(0x7647C320, 0x0069671F), /* ~= 10^-181 */
+ U64(0x84C8D4DF, 0xD2C63F3B), U64(0x29ECD9F4, 0x0041E073), /* ~= 10^-180 */
+ U64(0xA5FB0A17, 0xC777CF09), U64(0xF4681071, 0x00525890), /* ~= 10^-179 */
+ U64(0xCF79CC9D, 0xB955C2CC), U64(0x7182148D, 0x4066EEB4), /* ~= 10^-178 */
+ U64(0x81AC1FE2, 0x93D599BF), U64(0xC6F14CD8, 0x48405530), /* ~= 10^-177 */
+ U64(0xA21727DB, 0x38CB002F), U64(0xB8ADA00E, 0x5A506A7C), /* ~= 10^-176 */
+ U64(0xCA9CF1D2, 0x06FDC03B), U64(0xA6D90811, 0xF0E4851C), /* ~= 10^-175 */
+ U64(0xFD442E46, 0x88BD304A), U64(0x908F4A16, 0x6D1DA663), /* ~= 10^-174 */
+ U64(0x9E4A9CEC, 0x15763E2E), U64(0x9A598E4E, 0x043287FE), /* ~= 10^-173 */
+ U64(0xC5DD4427, 0x1AD3CDBA), U64(0x40EFF1E1, 0x853F29FD), /* ~= 10^-172 */
+ U64(0xF7549530, 0xE188C128), U64(0xD12BEE59, 0xE68EF47C), /* ~= 10^-171 */
+ U64(0x9A94DD3E, 0x8CF578B9), U64(0x82BB74F8, 0x301958CE), /* ~= 10^-170 */
+ U64(0xC13A148E, 0x3032D6E7), U64(0xE36A5236, 0x3C1FAF01), /* ~= 10^-169 */
+ U64(0xF18899B1, 0xBC3F8CA1), U64(0xDC44E6C3, 0xCB279AC1), /* ~= 10^-168 */
+ U64(0x96F5600F, 0x15A7B7E5), U64(0x29AB103A, 0x5EF8C0B9), /* ~= 10^-167 */
+ U64(0xBCB2B812, 0xDB11A5DE), U64(0x7415D448, 0xF6B6F0E7), /* ~= 10^-166 */
+ U64(0xEBDF6617, 0x91D60F56), U64(0x111B495B, 0x3464AD21), /* ~= 10^-165 */
+ U64(0x936B9FCE, 0xBB25C995), U64(0xCAB10DD9, 0x00BEEC34), /* ~= 10^-164 */
+ U64(0xB84687C2, 0x69EF3BFB), U64(0x3D5D514F, 0x40EEA742), /* ~= 10^-163 */
+ U64(0xE65829B3, 0x046B0AFA), U64(0x0CB4A5A3, 0x112A5112), /* ~= 10^-162 */
+ U64(0x8FF71A0F, 0xE2C2E6DC), U64(0x47F0E785, 0xEABA72AB), /* ~= 10^-161 */
+ U64(0xB3F4E093, 0xDB73A093), U64(0x59ED2167, 0x65690F56), /* ~= 10^-160 */
+ U64(0xE0F218B8, 0xD25088B8), U64(0x306869C1, 0x3EC3532C), /* ~= 10^-159 */
+ U64(0x8C974F73, 0x83725573), U64(0x1E414218, 0xC73A13FB), /* ~= 10^-158 */
+ U64(0xAFBD2350, 0x644EEACF), U64(0xE5D1929E, 0xF90898FA), /* ~= 10^-157 */
+ U64(0xDBAC6C24, 0x7D62A583), U64(0xDF45F746, 0xB74ABF39), /* ~= 10^-156 */
+ U64(0x894BC396, 0xCE5DA772), U64(0x6B8BBA8C, 0x328EB783), /* ~= 10^-155 */
+ U64(0xAB9EB47C, 0x81F5114F), U64(0x066EA92F, 0x3F326564), /* ~= 10^-154 */
+ U64(0xD686619B, 0xA27255A2), U64(0xC80A537B, 0x0EFEFEBD), /* ~= 10^-153 */
+ U64(0x8613FD01, 0x45877585), U64(0xBD06742C, 0xE95F5F36), /* ~= 10^-152 */
+ U64(0xA798FC41, 0x96E952E7), U64(0x2C481138, 0x23B73704), /* ~= 10^-151 */
+ U64(0xD17F3B51, 0xFCA3A7A0), U64(0xF75A1586, 0x2CA504C5), /* ~= 10^-150 */
+ U64(0x82EF8513, 0x3DE648C4), U64(0x9A984D73, 0xDBE722FB), /* ~= 10^-149 */
+ U64(0xA3AB6658, 0x0D5FDAF5), U64(0xC13E60D0, 0xD2E0EBBA), /* ~= 10^-148 */
+ U64(0xCC963FEE, 0x10B7D1B3), U64(0x318DF905, 0x079926A8), /* ~= 10^-147 */
+ U64(0xFFBBCFE9, 0x94E5C61F), U64(0xFDF17746, 0x497F7052), /* ~= 10^-146 */
+ U64(0x9FD561F1, 0xFD0F9BD3), U64(0xFEB6EA8B, 0xEDEFA633), /* ~= 10^-145 */
+ U64(0xC7CABA6E, 0x7C5382C8), U64(0xFE64A52E, 0xE96B8FC0), /* ~= 10^-144 */
+ U64(0xF9BD690A, 0x1B68637B), U64(0x3DFDCE7A, 0xA3C673B0), /* ~= 10^-143 */
+ U64(0x9C1661A6, 0x51213E2D), U64(0x06BEA10C, 0xA65C084E), /* ~= 10^-142 */
+ U64(0xC31BFA0F, 0xE5698DB8), U64(0x486E494F, 0xCFF30A62), /* ~= 10^-141 */
+ U64(0xF3E2F893, 0xDEC3F126), U64(0x5A89DBA3, 0xC3EFCCFA), /* ~= 10^-140 */
+ U64(0x986DDB5C, 0x6B3A76B7), U64(0xF8962946, 0x5A75E01C), /* ~= 10^-139 */
+ U64(0xBE895233, 0x86091465), U64(0xF6BBB397, 0xF1135823), /* ~= 10^-138 */
+ U64(0xEE2BA6C0, 0x678B597F), U64(0x746AA07D, 0xED582E2C), /* ~= 10^-137 */
+ U64(0x94DB4838, 0x40B717EF), U64(0xA8C2A44E, 0xB4571CDC), /* ~= 10^-136 */
+ U64(0xBA121A46, 0x50E4DDEB), U64(0x92F34D62, 0x616CE413), /* ~= 10^-135 */
+ U64(0xE896A0D7, 0xE51E1566), U64(0x77B020BA, 0xF9C81D17), /* ~= 10^-134 */
+ U64(0x915E2486, 0xEF32CD60), U64(0x0ACE1474, 0xDC1D122E), /* ~= 10^-133 */
+ U64(0xB5B5ADA8, 0xAAFF80B8), U64(0x0D819992, 0x132456BA), /* ~= 10^-132 */
+ U64(0xE3231912, 0xD5BF60E6), U64(0x10E1FFF6, 0x97ED6C69), /* ~= 10^-131 */
+ U64(0x8DF5EFAB, 0xC5979C8F), U64(0xCA8D3FFA, 0x1EF463C1), /* ~= 10^-130 */
+ U64(0xB1736B96, 0xB6FD83B3), U64(0xBD308FF8, 0xA6B17CB2), /* ~= 10^-129 */
+ U64(0xDDD0467C, 0x64BCE4A0), U64(0xAC7CB3F6, 0xD05DDBDE), /* ~= 10^-128 */
+ U64(0x8AA22C0D, 0xBEF60EE4), U64(0x6BCDF07A, 0x423AA96B), /* ~= 10^-127 */
+ U64(0xAD4AB711, 0x2EB3929D), U64(0x86C16C98, 0xD2C953C6), /* ~= 10^-126 */
+ U64(0xD89D64D5, 0x7A607744), U64(0xE871C7BF, 0x077BA8B7), /* ~= 10^-125 */
+ U64(0x87625F05, 0x6C7C4A8B), U64(0x11471CD7, 0x64AD4972), /* ~= 10^-124 */
+ U64(0xA93AF6C6, 0xC79B5D2D), U64(0xD598E40D, 0x3DD89BCF), /* ~= 10^-123 */
+ U64(0xD389B478, 0x79823479), U64(0x4AFF1D10, 0x8D4EC2C3), /* ~= 10^-122 */
+ U64(0x843610CB, 0x4BF160CB), U64(0xCEDF722A, 0x585139BA), /* ~= 10^-121 */
+ U64(0xA54394FE, 0x1EEDB8FE), U64(0xC2974EB4, 0xEE658828), /* ~= 10^-120 */
+ U64(0xCE947A3D, 0xA6A9273E), U64(0x733D2262, 0x29FEEA32), /* ~= 10^-119 */
+ U64(0x811CCC66, 0x8829B887), U64(0x0806357D, 0x5A3F525F), /* ~= 10^-118 */
+ U64(0xA163FF80, 0x2A3426A8), U64(0xCA07C2DC, 0xB0CF26F7), /* ~= 10^-117 */
+ U64(0xC9BCFF60, 0x34C13052), U64(0xFC89B393, 0xDD02F0B5), /* ~= 10^-116 */
+ U64(0xFC2C3F38, 0x41F17C67), U64(0xBBAC2078, 0xD443ACE2), /* ~= 10^-115 */
+ U64(0x9D9BA783, 0x2936EDC0), U64(0xD54B944B, 0x84AA4C0D), /* ~= 10^-114 */
+ U64(0xC5029163, 0xF384A931), U64(0x0A9E795E, 0x65D4DF11), /* ~= 10^-113 */
+ U64(0xF64335BC, 0xF065D37D), U64(0x4D4617B5, 0xFF4A16D5), /* ~= 10^-112 */
+ U64(0x99EA0196, 0x163FA42E), U64(0x504BCED1, 0xBF8E4E45), /* ~= 10^-111 */
+ U64(0xC06481FB, 0x9BCF8D39), U64(0xE45EC286, 0x2F71E1D6), /* ~= 10^-110 */
+ U64(0xF07DA27A, 0x82C37088), U64(0x5D767327, 0xBB4E5A4C), /* ~= 10^-109 */
+ U64(0x964E858C, 0x91BA2655), U64(0x3A6A07F8, 0xD510F86F), /* ~= 10^-108 */
+ U64(0xBBE226EF, 0xB628AFEA), U64(0x890489F7, 0x0A55368B), /* ~= 10^-107 */
+ U64(0xEADAB0AB, 0xA3B2DBE5), U64(0x2B45AC74, 0xCCEA842E), /* ~= 10^-106 */
+ U64(0x92C8AE6B, 0x464FC96F), U64(0x3B0B8BC9, 0x0012929D), /* ~= 10^-105 */
+ U64(0xB77ADA06, 0x17E3BBCB), U64(0x09CE6EBB, 0x40173744), /* ~= 10^-104 */
+ U64(0xE5599087, 0x9DDCAABD), U64(0xCC420A6A, 0x101D0515), /* ~= 10^-103 */
+ U64(0x8F57FA54, 0xC2A9EAB6), U64(0x9FA94682, 0x4A12232D), /* ~= 10^-102 */
+ U64(0xB32DF8E9, 0xF3546564), U64(0x47939822, 0xDC96ABF9), /* ~= 10^-101 */
+ U64(0xDFF97724, 0x70297EBD), U64(0x59787E2B, 0x93BC56F7), /* ~= 10^-100 */
+ U64(0x8BFBEA76, 0xC619EF36), U64(0x57EB4EDB, 0x3C55B65A), /* ~= 10^-99 */
+ U64(0xAEFAE514, 0x77A06B03), U64(0xEDE62292, 0x0B6B23F1), /* ~= 10^-98 */
+ U64(0xDAB99E59, 0x958885C4), U64(0xE95FAB36, 0x8E45ECED), /* ~= 10^-97 */
+ U64(0x88B402F7, 0xFD75539B), U64(0x11DBCB02, 0x18EBB414), /* ~= 10^-96 */
+ U64(0xAAE103B5, 0xFCD2A881), U64(0xD652BDC2, 0x9F26A119), /* ~= 10^-95 */
+ U64(0xD59944A3, 0x7C0752A2), U64(0x4BE76D33, 0x46F0495F), /* ~= 10^-94 */
+ U64(0x857FCAE6, 0x2D8493A5), U64(0x6F70A440, 0x0C562DDB), /* ~= 10^-93 */
+ U64(0xA6DFBD9F, 0xB8E5B88E), U64(0xCB4CCD50, 0x0F6BB952), /* ~= 10^-92 */
+ U64(0xD097AD07, 0xA71F26B2), U64(0x7E2000A4, 0x1346A7A7), /* ~= 10^-91 */
+ U64(0x825ECC24, 0xC873782F), U64(0x8ED40066, 0x8C0C28C8), /* ~= 10^-90 */
+ U64(0xA2F67F2D, 0xFA90563B), U64(0x72890080, 0x2F0F32FA), /* ~= 10^-89 */
+ U64(0xCBB41EF9, 0x79346BCA), U64(0x4F2B40A0, 0x3AD2FFB9), /* ~= 10^-88 */
+ U64(0xFEA126B7, 0xD78186BC), U64(0xE2F610C8, 0x4987BFA8), /* ~= 10^-87 */
+ U64(0x9F24B832, 0xE6B0F436), U64(0x0DD9CA7D, 0x2DF4D7C9), /* ~= 10^-86 */
+ U64(0xC6EDE63F, 0xA05D3143), U64(0x91503D1C, 0x79720DBB), /* ~= 10^-85 */
+ U64(0xF8A95FCF, 0x88747D94), U64(0x75A44C63, 0x97CE912A), /* ~= 10^-84 */
+ U64(0x9B69DBE1, 0xB548CE7C), U64(0xC986AFBE, 0x3EE11ABA), /* ~= 10^-83 */
+ U64(0xC24452DA, 0x229B021B), U64(0xFBE85BAD, 0xCE996168), /* ~= 10^-82 */
+ U64(0xF2D56790, 0xAB41C2A2), U64(0xFAE27299, 0x423FB9C3), /* ~= 10^-81 */
+ U64(0x97C560BA, 0x6B0919A5), U64(0xDCCD879F, 0xC967D41A), /* ~= 10^-80 */
+ U64(0xBDB6B8E9, 0x05CB600F), U64(0x5400E987, 0xBBC1C920), /* ~= 10^-79 */
+ U64(0xED246723, 0x473E3813), U64(0x290123E9, 0xAAB23B68), /* ~= 10^-78 */
+ U64(0x9436C076, 0x0C86E30B), U64(0xF9A0B672, 0x0AAF6521), /* ~= 10^-77 */
+ U64(0xB9447093, 0x8FA89BCE), U64(0xF808E40E, 0x8D5B3E69), /* ~= 10^-76 */
+ U64(0xE7958CB8, 0x7392C2C2), U64(0xB60B1D12, 0x30B20E04), /* ~= 10^-75 */
+ U64(0x90BD77F3, 0x483BB9B9), U64(0xB1C6F22B, 0x5E6F48C2), /* ~= 10^-74 */
+ U64(0xB4ECD5F0, 0x1A4AA828), U64(0x1E38AEB6, 0x360B1AF3), /* ~= 10^-73 */
+ U64(0xE2280B6C, 0x20DD5232), U64(0x25C6DA63, 0xC38DE1B0), /* ~= 10^-72 */
+ U64(0x8D590723, 0x948A535F), U64(0x579C487E, 0x5A38AD0E), /* ~= 10^-71 */
+ U64(0xB0AF48EC, 0x79ACE837), U64(0x2D835A9D, 0xF0C6D851), /* ~= 10^-70 */
+ U64(0xDCDB1B27, 0x98182244), U64(0xF8E43145, 0x6CF88E65), /* ~= 10^-69 */
+ U64(0x8A08F0F8, 0xBF0F156B), U64(0x1B8E9ECB, 0x641B58FF), /* ~= 10^-68 */
+ U64(0xAC8B2D36, 0xEED2DAC5), U64(0xE272467E, 0x3D222F3F), /* ~= 10^-67 */
+ U64(0xD7ADF884, 0xAA879177), U64(0x5B0ED81D, 0xCC6ABB0F), /* ~= 10^-66 */
+ U64(0x86CCBB52, 0xEA94BAEA), U64(0x98E94712, 0x9FC2B4E9), /* ~= 10^-65 */
+ U64(0xA87FEA27, 0xA539E9A5), U64(0x3F2398D7, 0x47B36224), /* ~= 10^-64 */
+ U64(0xD29FE4B1, 0x8E88640E), U64(0x8EEC7F0D, 0x19A03AAD), /* ~= 10^-63 */
+ U64(0x83A3EEEE, 0xF9153E89), U64(0x1953CF68, 0x300424AC), /* ~= 10^-62 */
+ U64(0xA48CEAAA, 0xB75A8E2B), U64(0x5FA8C342, 0x3C052DD7), /* ~= 10^-61 */
+ U64(0xCDB02555, 0x653131B6), U64(0x3792F412, 0xCB06794D), /* ~= 10^-60 */
+ U64(0x808E1755, 0x5F3EBF11), U64(0xE2BBD88B, 0xBEE40BD0), /* ~= 10^-59 */
+ U64(0xA0B19D2A, 0xB70E6ED6), U64(0x5B6ACEAE, 0xAE9D0EC4), /* ~= 10^-58 */
+ U64(0xC8DE0475, 0x64D20A8B), U64(0xF245825A, 0x5A445275), /* ~= 10^-57 */
+ U64(0xFB158592, 0xBE068D2E), U64(0xEED6E2F0, 0xF0D56712), /* ~= 10^-56 */
+ U64(0x9CED737B, 0xB6C4183D), U64(0x55464DD6, 0x9685606B), /* ~= 10^-55 */
+ U64(0xC428D05A, 0xA4751E4C), U64(0xAA97E14C, 0x3C26B886), /* ~= 10^-54 */
+ U64(0xF5330471, 0x4D9265DF), U64(0xD53DD99F, 0x4B3066A8), /* ~= 10^-53 */
+ U64(0x993FE2C6, 0xD07B7FAB), U64(0xE546A803, 0x8EFE4029), /* ~= 10^-52 */
+ U64(0xBF8FDB78, 0x849A5F96), U64(0xDE985204, 0x72BDD033), /* ~= 10^-51 */
+ U64(0xEF73D256, 0xA5C0F77C), U64(0x963E6685, 0x8F6D4440), /* ~= 10^-50 */
+ U64(0x95A86376, 0x27989AAD), U64(0xDDE70013, 0x79A44AA8), /* ~= 10^-49 */
+ U64(0xBB127C53, 0xB17EC159), U64(0x5560C018, 0x580D5D52), /* ~= 10^-48 */
+ U64(0xE9D71B68, 0x9DDE71AF), U64(0xAAB8F01E, 0x6E10B4A6), /* ~= 10^-47 */
+ U64(0x92267121, 0x62AB070D), U64(0xCAB39613, 0x04CA70E8), /* ~= 10^-46 */
+ U64(0xB6B00D69, 0xBB55C8D1), U64(0x3D607B97, 0xC5FD0D22), /* ~= 10^-45 */
+ U64(0xE45C10C4, 0x2A2B3B05), U64(0x8CB89A7D, 0xB77C506A), /* ~= 10^-44 */
+ U64(0x8EB98A7A, 0x9A5B04E3), U64(0x77F3608E, 0x92ADB242), /* ~= 10^-43 */
+ U64(0xB267ED19, 0x40F1C61C), U64(0x55F038B2, 0x37591ED3), /* ~= 10^-42 */
+ U64(0xDF01E85F, 0x912E37A3), U64(0x6B6C46DE, 0xC52F6688), /* ~= 10^-41 */
+ U64(0x8B61313B, 0xBABCE2C6), U64(0x2323AC4B, 0x3B3DA015), /* ~= 10^-40 */
+ U64(0xAE397D8A, 0xA96C1B77), U64(0xABEC975E, 0x0A0D081A), /* ~= 10^-39 */
+ U64(0xD9C7DCED, 0x53C72255), U64(0x96E7BD35, 0x8C904A21), /* ~= 10^-38 */
+ U64(0x881CEA14, 0x545C7575), U64(0x7E50D641, 0x77DA2E54), /* ~= 10^-37 */
+ U64(0xAA242499, 0x697392D2), U64(0xDDE50BD1, 0xD5D0B9E9), /* ~= 10^-36 */
+ U64(0xD4AD2DBF, 0xC3D07787), U64(0x955E4EC6, 0x4B44E864), /* ~= 10^-35 */
+ U64(0x84EC3C97, 0xDA624AB4), U64(0xBD5AF13B, 0xEF0B113E), /* ~= 10^-34 */
+ U64(0xA6274BBD, 0xD0FADD61), U64(0xECB1AD8A, 0xEACDD58E), /* ~= 10^-33 */
+ U64(0xCFB11EAD, 0x453994BA), U64(0x67DE18ED, 0xA5814AF2), /* ~= 10^-32 */
+ U64(0x81CEB32C, 0x4B43FCF4), U64(0x80EACF94, 0x8770CED7), /* ~= 10^-31 */
+ U64(0xA2425FF7, 0x5E14FC31), U64(0xA1258379, 0xA94D028D), /* ~= 10^-30 */
+ U64(0xCAD2F7F5, 0x359A3B3E), U64(0x096EE458, 0x13A04330), /* ~= 10^-29 */
+ U64(0xFD87B5F2, 0x8300CA0D), U64(0x8BCA9D6E, 0x188853FC), /* ~= 10^-28 */
+ U64(0x9E74D1B7, 0x91E07E48), U64(0x775EA264, 0xCF55347D), /* ~= 10^-27 */
+ U64(0xC6120625, 0x76589DDA), U64(0x95364AFE, 0x032A819D), /* ~= 10^-26 */
+ U64(0xF79687AE, 0xD3EEC551), U64(0x3A83DDBD, 0x83F52204), /* ~= 10^-25 */
+ U64(0x9ABE14CD, 0x44753B52), U64(0xC4926A96, 0x72793542), /* ~= 10^-24 */
+ U64(0xC16D9A00, 0x95928A27), U64(0x75B7053C, 0x0F178293), /* ~= 10^-23 */
+ U64(0xF1C90080, 0xBAF72CB1), U64(0x5324C68B, 0x12DD6338), /* ~= 10^-22 */
+ U64(0x971DA050, 0x74DA7BEE), U64(0xD3F6FC16, 0xEBCA5E03), /* ~= 10^-21 */
+ U64(0xBCE50864, 0x92111AEA), U64(0x88F4BB1C, 0xA6BCF584), /* ~= 10^-20 */
+ U64(0xEC1E4A7D, 0xB69561A5), U64(0x2B31E9E3, 0xD06C32E5), /* ~= 10^-19 */
+ U64(0x9392EE8E, 0x921D5D07), U64(0x3AFF322E, 0x62439FCF), /* ~= 10^-18 */
+ U64(0xB877AA32, 0x36A4B449), U64(0x09BEFEB9, 0xFAD487C2), /* ~= 10^-17 */
+ U64(0xE69594BE, 0xC44DE15B), U64(0x4C2EBE68, 0x7989A9B3), /* ~= 10^-16 */
+ U64(0x901D7CF7, 0x3AB0ACD9), U64(0x0F9D3701, 0x4BF60A10), /* ~= 10^-15 */
+ U64(0xB424DC35, 0x095CD80F), U64(0x538484C1, 0x9EF38C94), /* ~= 10^-14 */
+ U64(0xE12E1342, 0x4BB40E13), U64(0x2865A5F2, 0x06B06FB9), /* ~= 10^-13 */
+ U64(0x8CBCCC09, 0x6F5088CB), U64(0xF93F87B7, 0x442E45D3), /* ~= 10^-12 */
+ U64(0xAFEBFF0B, 0xCB24AAFE), U64(0xF78F69A5, 0x1539D748), /* ~= 10^-11 */
+ U64(0xDBE6FECE, 0xBDEDD5BE), U64(0xB573440E, 0x5A884D1B), /* ~= 10^-10 */
+ U64(0x89705F41, 0x36B4A597), U64(0x31680A88, 0xF8953030), /* ~= 10^-9 */
+ U64(0xABCC7711, 0x8461CEFC), U64(0xFDC20D2B, 0x36BA7C3D), /* ~= 10^-8 */
+ U64(0xD6BF94D5, 0xE57A42BC), U64(0x3D329076, 0x04691B4C), /* ~= 10^-7 */
+ U64(0x8637BD05, 0xAF6C69B5), U64(0xA63F9A49, 0xC2C1B10F), /* ~= 10^-6 */
+ U64(0xA7C5AC47, 0x1B478423), U64(0x0FCF80DC, 0x33721D53), /* ~= 10^-5 */
+ U64(0xD1B71758, 0xE219652B), U64(0xD3C36113, 0x404EA4A8), /* ~= 10^-4 */
+ U64(0x83126E97, 0x8D4FDF3B), U64(0x645A1CAC, 0x083126E9), /* ~= 10^-3 */
+ U64(0xA3D70A3D, 0x70A3D70A), U64(0x3D70A3D7, 0x0A3D70A3), /* ~= 10^-2 */
+ U64(0xCCCCCCCC, 0xCCCCCCCC), U64(0xCCCCCCCC, 0xCCCCCCCC), /* ~= 10^-1 */
+ U64(0x80000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^0 */
+ U64(0xA0000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^1 */
+ U64(0xC8000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^2 */
+ U64(0xFA000000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^3 */
+ U64(0x9C400000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^4 */
+ U64(0xC3500000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^5 */
+ U64(0xF4240000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^6 */
+ U64(0x98968000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^7 */
+ U64(0xBEBC2000, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^8 */
+ U64(0xEE6B2800, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^9 */
+ U64(0x9502F900, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^10 */
+ U64(0xBA43B740, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^11 */
+ U64(0xE8D4A510, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^12 */
+ U64(0x9184E72A, 0x00000000), U64(0x00000000, 0x00000000), /* == 10^13 */
+ U64(0xB5E620F4, 0x80000000), U64(0x00000000, 0x00000000), /* == 10^14 */
+ U64(0xE35FA931, 0xA0000000), U64(0x00000000, 0x00000000), /* == 10^15 */
+ U64(0x8E1BC9BF, 0x04000000), U64(0x00000000, 0x00000000), /* == 10^16 */
+ U64(0xB1A2BC2E, 0xC5000000), U64(0x00000000, 0x00000000), /* == 10^17 */
+ U64(0xDE0B6B3A, 0x76400000), U64(0x00000000, 0x00000000), /* == 10^18 */
+ U64(0x8AC72304, 0x89E80000), U64(0x00000000, 0x00000000), /* == 10^19 */
+ U64(0xAD78EBC5, 0xAC620000), U64(0x00000000, 0x00000000), /* == 10^20 */
+ U64(0xD8D726B7, 0x177A8000), U64(0x00000000, 0x00000000), /* == 10^21 */
+ U64(0x87867832, 0x6EAC9000), U64(0x00000000, 0x00000000), /* == 10^22 */
+ U64(0xA968163F, 0x0A57B400), U64(0x00000000, 0x00000000), /* == 10^23 */
+ U64(0xD3C21BCE, 0xCCEDA100), U64(0x00000000, 0x00000000), /* == 10^24 */
+ U64(0x84595161, 0x401484A0), U64(0x00000000, 0x00000000), /* == 10^25 */
+ U64(0xA56FA5B9, 0x9019A5C8), U64(0x00000000, 0x00000000), /* == 10^26 */
+ U64(0xCECB8F27, 0xF4200F3A), U64(0x00000000, 0x00000000), /* == 10^27 */
+ U64(0x813F3978, 0xF8940984), U64(0x40000000, 0x00000000), /* == 10^28 */
+ U64(0xA18F07D7, 0x36B90BE5), U64(0x50000000, 0x00000000), /* == 10^29 */
+ U64(0xC9F2C9CD, 0x04674EDE), U64(0xA4000000, 0x00000000), /* == 10^30 */
+ U64(0xFC6F7C40, 0x45812296), U64(0x4D000000, 0x00000000), /* == 10^31 */
+ U64(0x9DC5ADA8, 0x2B70B59D), U64(0xF0200000, 0x00000000), /* == 10^32 */
+ U64(0xC5371912, 0x364CE305), U64(0x6C280000, 0x00000000), /* == 10^33 */
+ U64(0xF684DF56, 0xC3E01BC6), U64(0xC7320000, 0x00000000), /* == 10^34 */
+ U64(0x9A130B96, 0x3A6C115C), U64(0x3C7F4000, 0x00000000), /* == 10^35 */
+ U64(0xC097CE7B, 0xC90715B3), U64(0x4B9F1000, 0x00000000), /* == 10^36 */
+ U64(0xF0BDC21A, 0xBB48DB20), U64(0x1E86D400, 0x00000000), /* == 10^37 */
+ U64(0x96769950, 0xB50D88F4), U64(0x13144480, 0x00000000), /* == 10^38 */
+ U64(0xBC143FA4, 0xE250EB31), U64(0x17D955A0, 0x00000000), /* == 10^39 */
+ U64(0xEB194F8E, 0x1AE525FD), U64(0x5DCFAB08, 0x00000000), /* == 10^40 */
+ U64(0x92EFD1B8, 0xD0CF37BE), U64(0x5AA1CAE5, 0x00000000), /* == 10^41 */
+ U64(0xB7ABC627, 0x050305AD), U64(0xF14A3D9E, 0x40000000), /* == 10^42 */
+ U64(0xE596B7B0, 0xC643C719), U64(0x6D9CCD05, 0xD0000000), /* == 10^43 */
+ U64(0x8F7E32CE, 0x7BEA5C6F), U64(0xE4820023, 0xA2000000), /* == 10^44 */
+ U64(0xB35DBF82, 0x1AE4F38B), U64(0xDDA2802C, 0x8A800000), /* == 10^45 */
+ U64(0xE0352F62, 0xA19E306E), U64(0xD50B2037, 0xAD200000), /* == 10^46 */
+ U64(0x8C213D9D, 0xA502DE45), U64(0x4526F422, 0xCC340000), /* == 10^47 */
+ U64(0xAF298D05, 0x0E4395D6), U64(0x9670B12B, 0x7F410000), /* == 10^48 */
+ U64(0xDAF3F046, 0x51D47B4C), U64(0x3C0CDD76, 0x5F114000), /* == 10^49 */
+ U64(0x88D8762B, 0xF324CD0F), U64(0xA5880A69, 0xFB6AC800), /* == 10^50 */
+ U64(0xAB0E93B6, 0xEFEE0053), U64(0x8EEA0D04, 0x7A457A00), /* == 10^51 */
+ U64(0xD5D238A4, 0xABE98068), U64(0x72A49045, 0x98D6D880), /* == 10^52 */
+ U64(0x85A36366, 0xEB71F041), U64(0x47A6DA2B, 0x7F864750), /* == 10^53 */
+ U64(0xA70C3C40, 0xA64E6C51), U64(0x999090B6, 0x5F67D924), /* == 10^54 */
+ U64(0xD0CF4B50, 0xCFE20765), U64(0xFFF4B4E3, 0xF741CF6D), /* == 10^55 */
+ U64(0x82818F12, 0x81ED449F), U64(0xBFF8F10E, 0x7A8921A4), /* ~= 10^56 */
+ U64(0xA321F2D7, 0x226895C7), U64(0xAFF72D52, 0x192B6A0D), /* ~= 10^57 */
+ U64(0xCBEA6F8C, 0xEB02BB39), U64(0x9BF4F8A6, 0x9F764490), /* ~= 10^58 */
+ U64(0xFEE50B70, 0x25C36A08), U64(0x02F236D0, 0x4753D5B4), /* ~= 10^59 */
+ U64(0x9F4F2726, 0x179A2245), U64(0x01D76242, 0x2C946590), /* ~= 10^60 */
+ U64(0xC722F0EF, 0x9D80AAD6), U64(0x424D3AD2, 0xB7B97EF5), /* ~= 10^61 */
+ U64(0xF8EBAD2B, 0x84E0D58B), U64(0xD2E08987, 0x65A7DEB2), /* ~= 10^62 */
+ U64(0x9B934C3B, 0x330C8577), U64(0x63CC55F4, 0x9F88EB2F), /* ~= 10^63 */
+ U64(0xC2781F49, 0xFFCFA6D5), U64(0x3CBF6B71, 0xC76B25FB), /* ~= 10^64 */
+ U64(0xF316271C, 0x7FC3908A), U64(0x8BEF464E, 0x3945EF7A), /* ~= 10^65 */
+ U64(0x97EDD871, 0xCFDA3A56), U64(0x97758BF0, 0xE3CBB5AC), /* ~= 10^66 */
+ U64(0xBDE94E8E, 0x43D0C8EC), U64(0x3D52EEED, 0x1CBEA317), /* ~= 10^67 */
+ U64(0xED63A231, 0xD4C4FB27), U64(0x4CA7AAA8, 0x63EE4BDD), /* ~= 10^68 */
+ U64(0x945E455F, 0x24FB1CF8), U64(0x8FE8CAA9, 0x3E74EF6A), /* ~= 10^69 */
+ U64(0xB975D6B6, 0xEE39E436), U64(0xB3E2FD53, 0x8E122B44), /* ~= 10^70 */
+ U64(0xE7D34C64, 0xA9C85D44), U64(0x60DBBCA8, 0x7196B616), /* ~= 10^71 */
+ U64(0x90E40FBE, 0xEA1D3A4A), U64(0xBC8955E9, 0x46FE31CD), /* ~= 10^72 */
+ U64(0xB51D13AE, 0xA4A488DD), U64(0x6BABAB63, 0x98BDBE41), /* ~= 10^73 */
+ U64(0xE264589A, 0x4DCDAB14), U64(0xC696963C, 0x7EED2DD1), /* ~= 10^74 */
+ U64(0x8D7EB760, 0x70A08AEC), U64(0xFC1E1DE5, 0xCF543CA2), /* ~= 10^75 */
+ U64(0xB0DE6538, 0x8CC8ADA8), U64(0x3B25A55F, 0x43294BCB), /* ~= 10^76 */
+ U64(0xDD15FE86, 0xAFFAD912), U64(0x49EF0EB7, 0x13F39EBE), /* ~= 10^77 */
+ U64(0x8A2DBF14, 0x2DFCC7AB), U64(0x6E356932, 0x6C784337), /* ~= 10^78 */
+ U64(0xACB92ED9, 0x397BF996), U64(0x49C2C37F, 0x07965404), /* ~= 10^79 */
+ U64(0xD7E77A8F, 0x87DAF7FB), U64(0xDC33745E, 0xC97BE906), /* ~= 10^80 */
+ U64(0x86F0AC99, 0xB4E8DAFD), U64(0x69A028BB, 0x3DED71A3), /* ~= 10^81 */
+ U64(0xA8ACD7C0, 0x222311BC), U64(0xC40832EA, 0x0D68CE0C), /* ~= 10^82 */
+ U64(0xD2D80DB0, 0x2AABD62B), U64(0xF50A3FA4, 0x90C30190), /* ~= 10^83 */
+ U64(0x83C7088E, 0x1AAB65DB), U64(0x792667C6, 0xDA79E0FA), /* ~= 10^84 */
+ U64(0xA4B8CAB1, 0xA1563F52), U64(0x577001B8, 0x91185938), /* ~= 10^85 */
+ U64(0xCDE6FD5E, 0x09ABCF26), U64(0xED4C0226, 0xB55E6F86), /* ~= 10^86 */
+ U64(0x80B05E5A, 0xC60B6178), U64(0x544F8158, 0x315B05B4), /* ~= 10^87 */
+ U64(0xA0DC75F1, 0x778E39D6), U64(0x696361AE, 0x3DB1C721), /* ~= 10^88 */
+ U64(0xC913936D, 0xD571C84C), U64(0x03BC3A19, 0xCD1E38E9), /* ~= 10^89 */
+ U64(0xFB587849, 0x4ACE3A5F), U64(0x04AB48A0, 0x4065C723), /* ~= 10^90 */
+ U64(0x9D174B2D, 0xCEC0E47B), U64(0x62EB0D64, 0x283F9C76), /* ~= 10^91 */
+ U64(0xC45D1DF9, 0x42711D9A), U64(0x3BA5D0BD, 0x324F8394), /* ~= 10^92 */
+ U64(0xF5746577, 0x930D6500), U64(0xCA8F44EC, 0x7EE36479), /* ~= 10^93 */
+ U64(0x9968BF6A, 0xBBE85F20), U64(0x7E998B13, 0xCF4E1ECB), /* ~= 10^94 */
+ U64(0xBFC2EF45, 0x6AE276E8), U64(0x9E3FEDD8, 0xC321A67E), /* ~= 10^95 */
+ U64(0xEFB3AB16, 0xC59B14A2), U64(0xC5CFE94E, 0xF3EA101E), /* ~= 10^96 */
+ U64(0x95D04AEE, 0x3B80ECE5), U64(0xBBA1F1D1, 0x58724A12), /* ~= 10^97 */
+ U64(0xBB445DA9, 0xCA61281F), U64(0x2A8A6E45, 0xAE8EDC97), /* ~= 10^98 */
+ U64(0xEA157514, 0x3CF97226), U64(0xF52D09D7, 0x1A3293BD), /* ~= 10^99 */
+ U64(0x924D692C, 0xA61BE758), U64(0x593C2626, 0x705F9C56), /* ~= 10^100 */
+ U64(0xB6E0C377, 0xCFA2E12E), U64(0x6F8B2FB0, 0x0C77836C), /* ~= 10^101 */
+ U64(0xE498F455, 0xC38B997A), U64(0x0B6DFB9C, 0x0F956447), /* ~= 10^102 */
+ U64(0x8EDF98B5, 0x9A373FEC), U64(0x4724BD41, 0x89BD5EAC), /* ~= 10^103 */
+ U64(0xB2977EE3, 0x00C50FE7), U64(0x58EDEC91, 0xEC2CB657), /* ~= 10^104 */
+ U64(0xDF3D5E9B, 0xC0F653E1), U64(0x2F2967B6, 0x6737E3ED), /* ~= 10^105 */
+ U64(0x8B865B21, 0x5899F46C), U64(0xBD79E0D2, 0x0082EE74), /* ~= 10^106 */
+ U64(0xAE67F1E9, 0xAEC07187), U64(0xECD85906, 0x80A3AA11), /* ~= 10^107 */
+ U64(0xDA01EE64, 0x1A708DE9), U64(0xE80E6F48, 0x20CC9495), /* ~= 10^108 */
+ U64(0x884134FE, 0x908658B2), U64(0x3109058D, 0x147FDCDD), /* ~= 10^109 */
+ U64(0xAA51823E, 0x34A7EEDE), U64(0xBD4B46F0, 0x599FD415), /* ~= 10^110 */
+ U64(0xD4E5E2CD, 0xC1D1EA96), U64(0x6C9E18AC, 0x7007C91A), /* ~= 10^111 */
+ U64(0x850FADC0, 0x9923329E), U64(0x03E2CF6B, 0xC604DDB0), /* ~= 10^112 */
+ U64(0xA6539930, 0xBF6BFF45), U64(0x84DB8346, 0xB786151C), /* ~= 10^113 */
+ U64(0xCFE87F7C, 0xEF46FF16), U64(0xE6126418, 0x65679A63), /* ~= 10^114 */
+ U64(0x81F14FAE, 0x158C5F6E), U64(0x4FCB7E8F, 0x3F60C07E), /* ~= 10^115 */
+ U64(0xA26DA399, 0x9AEF7749), U64(0xE3BE5E33, 0x0F38F09D), /* ~= 10^116 */
+ U64(0xCB090C80, 0x01AB551C), U64(0x5CADF5BF, 0xD3072CC5), /* ~= 10^117 */
+ U64(0xFDCB4FA0, 0x02162A63), U64(0x73D9732F, 0xC7C8F7F6), /* ~= 10^118 */
+ U64(0x9E9F11C4, 0x014DDA7E), U64(0x2867E7FD, 0xDCDD9AFA), /* ~= 10^119 */
+ U64(0xC646D635, 0x01A1511D), U64(0xB281E1FD, 0x541501B8), /* ~= 10^120 */
+ U64(0xF7D88BC2, 0x4209A565), U64(0x1F225A7C, 0xA91A4226), /* ~= 10^121 */
+ U64(0x9AE75759, 0x6946075F), U64(0x3375788D, 0xE9B06958), /* ~= 10^122 */
+ U64(0xC1A12D2F, 0xC3978937), U64(0x0052D6B1, 0x641C83AE), /* ~= 10^123 */
+ U64(0xF209787B, 0xB47D6B84), U64(0xC0678C5D, 0xBD23A49A), /* ~= 10^124 */
+ U64(0x9745EB4D, 0x50CE6332), U64(0xF840B7BA, 0x963646E0), /* ~= 10^125 */
+ U64(0xBD176620, 0xA501FBFF), U64(0xB650E5A9, 0x3BC3D898), /* ~= 10^126 */
+ U64(0xEC5D3FA8, 0xCE427AFF), U64(0xA3E51F13, 0x8AB4CEBE), /* ~= 10^127 */
+ U64(0x93BA47C9, 0x80E98CDF), U64(0xC66F336C, 0x36B10137), /* ~= 10^128 */
+ U64(0xB8A8D9BB, 0xE123F017), U64(0xB80B0047, 0x445D4184), /* ~= 10^129 */
+ U64(0xE6D3102A, 0xD96CEC1D), U64(0xA60DC059, 0x157491E5), /* ~= 10^130 */
+ U64(0x9043EA1A, 0xC7E41392), U64(0x87C89837, 0xAD68DB2F), /* ~= 10^131 */
+ U64(0xB454E4A1, 0x79DD1877), U64(0x29BABE45, 0x98C311FB), /* ~= 10^132 */
+ U64(0xE16A1DC9, 0xD8545E94), U64(0xF4296DD6, 0xFEF3D67A), /* ~= 10^133 */
+ U64(0x8CE2529E, 0x2734BB1D), U64(0x1899E4A6, 0x5F58660C), /* ~= 10^134 */
+ U64(0xB01AE745, 0xB101E9E4), U64(0x5EC05DCF, 0xF72E7F8F), /* ~= 10^135 */
+ U64(0xDC21A117, 0x1D42645D), U64(0x76707543, 0xF4FA1F73), /* ~= 10^136 */
+ U64(0x899504AE, 0x72497EBA), U64(0x6A06494A, 0x791C53A8), /* ~= 10^137 */
+ U64(0xABFA45DA, 0x0EDBDE69), U64(0x0487DB9D, 0x17636892), /* ~= 10^138 */
+ U64(0xD6F8D750, 0x9292D603), U64(0x45A9D284, 0x5D3C42B6), /* ~= 10^139 */
+ U64(0x865B8692, 0x5B9BC5C2), U64(0x0B8A2392, 0xBA45A9B2), /* ~= 10^140 */
+ U64(0xA7F26836, 0xF282B732), U64(0x8E6CAC77, 0x68D7141E), /* ~= 10^141 */
+ U64(0xD1EF0244, 0xAF2364FF), U64(0x3207D795, 0x430CD926), /* ~= 10^142 */
+ U64(0x8335616A, 0xED761F1F), U64(0x7F44E6BD, 0x49E807B8), /* ~= 10^143 */
+ U64(0xA402B9C5, 0xA8D3A6E7), U64(0x5F16206C, 0x9C6209A6), /* ~= 10^144 */
+ U64(0xCD036837, 0x130890A1), U64(0x36DBA887, 0xC37A8C0F), /* ~= 10^145 */
+ U64(0x80222122, 0x6BE55A64), U64(0xC2494954, 0xDA2C9789), /* ~= 10^146 */
+ U64(0xA02AA96B, 0x06DEB0FD), U64(0xF2DB9BAA, 0x10B7BD6C), /* ~= 10^147 */
+ U64(0xC83553C5, 0xC8965D3D), U64(0x6F928294, 0x94E5ACC7), /* ~= 10^148 */
+ U64(0xFA42A8B7, 0x3ABBF48C), U64(0xCB772339, 0xBA1F17F9), /* ~= 10^149 */
+ U64(0x9C69A972, 0x84B578D7), U64(0xFF2A7604, 0x14536EFB), /* ~= 10^150 */
+ U64(0xC38413CF, 0x25E2D70D), U64(0xFEF51385, 0x19684ABA), /* ~= 10^151 */
+ U64(0xF46518C2, 0xEF5B8CD1), U64(0x7EB25866, 0x5FC25D69), /* ~= 10^152 */
+ U64(0x98BF2F79, 0xD5993802), U64(0xEF2F773F, 0xFBD97A61), /* ~= 10^153 */
+ U64(0xBEEEFB58, 0x4AFF8603), U64(0xAAFB550F, 0xFACFD8FA), /* ~= 10^154 */
+ U64(0xEEAABA2E, 0x5DBF6784), U64(0x95BA2A53, 0xF983CF38), /* ~= 10^155 */
+ U64(0x952AB45C, 0xFA97A0B2), U64(0xDD945A74, 0x7BF26183), /* ~= 10^156 */
+ U64(0xBA756174, 0x393D88DF), U64(0x94F97111, 0x9AEEF9E4), /* ~= 10^157 */
+ U64(0xE912B9D1, 0x478CEB17), U64(0x7A37CD56, 0x01AAB85D), /* ~= 10^158 */
+ U64(0x91ABB422, 0xCCB812EE), U64(0xAC62E055, 0xC10AB33A), /* ~= 10^159 */
+ U64(0xB616A12B, 0x7FE617AA), U64(0x577B986B, 0x314D6009), /* ~= 10^160 */
+ U64(0xE39C4976, 0x5FDF9D94), U64(0xED5A7E85, 0xFDA0B80B), /* ~= 10^161 */
+ U64(0x8E41ADE9, 0xFBEBC27D), U64(0x14588F13, 0xBE847307), /* ~= 10^162 */
+ U64(0xB1D21964, 0x7AE6B31C), U64(0x596EB2D8, 0xAE258FC8), /* ~= 10^163 */
+ U64(0xDE469FBD, 0x99A05FE3), U64(0x6FCA5F8E, 0xD9AEF3BB), /* ~= 10^164 */
+ U64(0x8AEC23D6, 0x80043BEE), U64(0x25DE7BB9, 0x480D5854), /* ~= 10^165 */
+ U64(0xADA72CCC, 0x20054AE9), U64(0xAF561AA7, 0x9A10AE6A), /* ~= 10^166 */
+ U64(0xD910F7FF, 0x28069DA4), U64(0x1B2BA151, 0x8094DA04), /* ~= 10^167 */
+ U64(0x87AA9AFF, 0x79042286), U64(0x90FB44D2, 0xF05D0842), /* ~= 10^168 */
+ U64(0xA99541BF, 0x57452B28), U64(0x353A1607, 0xAC744A53), /* ~= 10^169 */
+ U64(0xD3FA922F, 0x2D1675F2), U64(0x42889B89, 0x97915CE8), /* ~= 10^170 */
+ U64(0x847C9B5D, 0x7C2E09B7), U64(0x69956135, 0xFEBADA11), /* ~= 10^171 */
+ U64(0xA59BC234, 0xDB398C25), U64(0x43FAB983, 0x7E699095), /* ~= 10^172 */
+ U64(0xCF02B2C2, 0x1207EF2E), U64(0x94F967E4, 0x5E03F4BB), /* ~= 10^173 */
+ U64(0x8161AFB9, 0x4B44F57D), U64(0x1D1BE0EE, 0xBAC278F5), /* ~= 10^174 */
+ U64(0xA1BA1BA7, 0x9E1632DC), U64(0x6462D92A, 0x69731732), /* ~= 10^175 */
+ U64(0xCA28A291, 0x859BBF93), U64(0x7D7B8F75, 0x03CFDCFE), /* ~= 10^176 */
+ U64(0xFCB2CB35, 0xE702AF78), U64(0x5CDA7352, 0x44C3D43E), /* ~= 10^177 */
+ U64(0x9DEFBF01, 0xB061ADAB), U64(0x3A088813, 0x6AFA64A7), /* ~= 10^178 */
+ U64(0xC56BAEC2, 0x1C7A1916), U64(0x088AAA18, 0x45B8FDD0), /* ~= 10^179 */
+ U64(0xF6C69A72, 0xA3989F5B), U64(0x8AAD549E, 0x57273D45), /* ~= 10^180 */
+ U64(0x9A3C2087, 0xA63F6399), U64(0x36AC54E2, 0xF678864B), /* ~= 10^181 */
+ U64(0xC0CB28A9, 0x8FCF3C7F), U64(0x84576A1B, 0xB416A7DD), /* ~= 10^182 */
+ U64(0xF0FDF2D3, 0xF3C30B9F), U64(0x656D44A2, 0xA11C51D5), /* ~= 10^183 */
+ U64(0x969EB7C4, 0x7859E743), U64(0x9F644AE5, 0xA4B1B325), /* ~= 10^184 */
+ U64(0xBC4665B5, 0x96706114), U64(0x873D5D9F, 0x0DDE1FEE), /* ~= 10^185 */
+ U64(0xEB57FF22, 0xFC0C7959), U64(0xA90CB506, 0xD155A7EA), /* ~= 10^186 */
+ U64(0x9316FF75, 0xDD87CBD8), U64(0x09A7F124, 0x42D588F2), /* ~= 10^187 */
+ U64(0xB7DCBF53, 0x54E9BECE), U64(0x0C11ED6D, 0x538AEB2F), /* ~= 10^188 */
+ U64(0xE5D3EF28, 0x2A242E81), U64(0x8F1668C8, 0xA86DA5FA), /* ~= 10^189 */
+ U64(0x8FA47579, 0x1A569D10), U64(0xF96E017D, 0x694487BC), /* ~= 10^190 */
+ U64(0xB38D92D7, 0x60EC4455), U64(0x37C981DC, 0xC395A9AC), /* ~= 10^191 */
+ U64(0xE070F78D, 0x3927556A), U64(0x85BBE253, 0xF47B1417), /* ~= 10^192 */
+ U64(0x8C469AB8, 0x43B89562), U64(0x93956D74, 0x78CCEC8E), /* ~= 10^193 */
+ U64(0xAF584166, 0x54A6BABB), U64(0x387AC8D1, 0x970027B2), /* ~= 10^194 */
+ U64(0xDB2E51BF, 0xE9D0696A), U64(0x06997B05, 0xFCC0319E), /* ~= 10^195 */
+ U64(0x88FCF317, 0xF22241E2), U64(0x441FECE3, 0xBDF81F03), /* ~= 10^196 */
+ U64(0xAB3C2FDD, 0xEEAAD25A), U64(0xD527E81C, 0xAD7626C3), /* ~= 10^197 */
+ U64(0xD60B3BD5, 0x6A5586F1), U64(0x8A71E223, 0xD8D3B074), /* ~= 10^198 */
+ U64(0x85C70565, 0x62757456), U64(0xF6872D56, 0x67844E49), /* ~= 10^199 */
+ U64(0xA738C6BE, 0xBB12D16C), U64(0xB428F8AC, 0x016561DB), /* ~= 10^200 */
+ U64(0xD106F86E, 0x69D785C7), U64(0xE13336D7, 0x01BEBA52), /* ~= 10^201 */
+ U64(0x82A45B45, 0x0226B39C), U64(0xECC00246, 0x61173473), /* ~= 10^202 */
+ U64(0xA34D7216, 0x42B06084), U64(0x27F002D7, 0xF95D0190), /* ~= 10^203 */
+ U64(0xCC20CE9B, 0xD35C78A5), U64(0x31EC038D, 0xF7B441F4), /* ~= 10^204 */
+ U64(0xFF290242, 0xC83396CE), U64(0x7E670471, 0x75A15271), /* ~= 10^205 */
+ U64(0x9F79A169, 0xBD203E41), U64(0x0F0062C6, 0xE984D386), /* ~= 10^206 */
+ U64(0xC75809C4, 0x2C684DD1), U64(0x52C07B78, 0xA3E60868), /* ~= 10^207 */
+ U64(0xF92E0C35, 0x37826145), U64(0xA7709A56, 0xCCDF8A82), /* ~= 10^208 */
+ U64(0x9BBCC7A1, 0x42B17CCB), U64(0x88A66076, 0x400BB691), /* ~= 10^209 */
+ U64(0xC2ABF989, 0x935DDBFE), U64(0x6ACFF893, 0xD00EA435), /* ~= 10^210 */
+ U64(0xF356F7EB, 0xF83552FE), U64(0x0583F6B8, 0xC4124D43), /* ~= 10^211 */
+ U64(0x98165AF3, 0x7B2153DE), U64(0xC3727A33, 0x7A8B704A), /* ~= 10^212 */
+ U64(0xBE1BF1B0, 0x59E9A8D6), U64(0x744F18C0, 0x592E4C5C), /* ~= 10^213 */
+ U64(0xEDA2EE1C, 0x7064130C), U64(0x1162DEF0, 0x6F79DF73), /* ~= 10^214 */
+ U64(0x9485D4D1, 0xC63E8BE7), U64(0x8ADDCB56, 0x45AC2BA8), /* ~= 10^215 */
+ U64(0xB9A74A06, 0x37CE2EE1), U64(0x6D953E2B, 0xD7173692), /* ~= 10^216 */
+ U64(0xE8111C87, 0xC5C1BA99), U64(0xC8FA8DB6, 0xCCDD0437), /* ~= 10^217 */
+ U64(0x910AB1D4, 0xDB9914A0), U64(0x1D9C9892, 0x400A22A2), /* ~= 10^218 */
+ U64(0xB54D5E4A, 0x127F59C8), U64(0x2503BEB6, 0xD00CAB4B), /* ~= 10^219 */
+ U64(0xE2A0B5DC, 0x971F303A), U64(0x2E44AE64, 0x840FD61D), /* ~= 10^220 */
+ U64(0x8DA471A9, 0xDE737E24), U64(0x5CEAECFE, 0xD289E5D2), /* ~= 10^221 */
+ U64(0xB10D8E14, 0x56105DAD), U64(0x7425A83E, 0x872C5F47), /* ~= 10^222 */
+ U64(0xDD50F199, 0x6B947518), U64(0xD12F124E, 0x28F77719), /* ~= 10^223 */
+ U64(0x8A5296FF, 0xE33CC92F), U64(0x82BD6B70, 0xD99AAA6F), /* ~= 10^224 */
+ U64(0xACE73CBF, 0xDC0BFB7B), U64(0x636CC64D, 0x1001550B), /* ~= 10^225 */
+ U64(0xD8210BEF, 0xD30EFA5A), U64(0x3C47F7E0, 0x5401AA4E), /* ~= 10^226 */
+ U64(0x8714A775, 0xE3E95C78), U64(0x65ACFAEC, 0x34810A71), /* ~= 10^227 */
+ U64(0xA8D9D153, 0x5CE3B396), U64(0x7F1839A7, 0x41A14D0D), /* ~= 10^228 */
+ U64(0xD31045A8, 0x341CA07C), U64(0x1EDE4811, 0x1209A050), /* ~= 10^229 */
+ U64(0x83EA2B89, 0x2091E44D), U64(0x934AED0A, 0xAB460432), /* ~= 10^230 */
+ U64(0xA4E4B66B, 0x68B65D60), U64(0xF81DA84D, 0x5617853F), /* ~= 10^231 */
+ U64(0xCE1DE406, 0x42E3F4B9), U64(0x36251260, 0xAB9D668E), /* ~= 10^232 */
+ U64(0x80D2AE83, 0xE9CE78F3), U64(0xC1D72B7C, 0x6B426019), /* ~= 10^233 */
+ U64(0xA1075A24, 0xE4421730), U64(0xB24CF65B, 0x8612F81F), /* ~= 10^234 */
+ U64(0xC94930AE, 0x1D529CFC), U64(0xDEE033F2, 0x6797B627), /* ~= 10^235 */
+ U64(0xFB9B7CD9, 0xA4A7443C), U64(0x169840EF, 0x017DA3B1), /* ~= 10^236 */
+ U64(0x9D412E08, 0x06E88AA5), U64(0x8E1F2895, 0x60EE864E), /* ~= 10^237 */
+ U64(0xC491798A, 0x08A2AD4E), U64(0xF1A6F2BA, 0xB92A27E2), /* ~= 10^238 */
+ U64(0xF5B5D7EC, 0x8ACB58A2), U64(0xAE10AF69, 0x6774B1DB), /* ~= 10^239 */
+ U64(0x9991A6F3, 0xD6BF1765), U64(0xACCA6DA1, 0xE0A8EF29), /* ~= 10^240 */
+ U64(0xBFF610B0, 0xCC6EDD3F), U64(0x17FD090A, 0x58D32AF3), /* ~= 10^241 */
+ U64(0xEFF394DC, 0xFF8A948E), U64(0xDDFC4B4C, 0xEF07F5B0), /* ~= 10^242 */
+ U64(0x95F83D0A, 0x1FB69CD9), U64(0x4ABDAF10, 0x1564F98E), /* ~= 10^243 */
+ U64(0xBB764C4C, 0xA7A4440F), U64(0x9D6D1AD4, 0x1ABE37F1), /* ~= 10^244 */
+ U64(0xEA53DF5F, 0xD18D5513), U64(0x84C86189, 0x216DC5ED), /* ~= 10^245 */
+ U64(0x92746B9B, 0xE2F8552C), U64(0x32FD3CF5, 0xB4E49BB4), /* ~= 10^246 */
+ U64(0xB7118682, 0xDBB66A77), U64(0x3FBC8C33, 0x221DC2A1), /* ~= 10^247 */
+ U64(0xE4D5E823, 0x92A40515), U64(0x0FABAF3F, 0xEAA5334A), /* ~= 10^248 */
+ U64(0x8F05B116, 0x3BA6832D), U64(0x29CB4D87, 0xF2A7400E), /* ~= 10^249 */
+ U64(0xB2C71D5B, 0xCA9023F8), U64(0x743E20E9, 0xEF511012), /* ~= 10^250 */
+ U64(0xDF78E4B2, 0xBD342CF6), U64(0x914DA924, 0x6B255416), /* ~= 10^251 */
+ U64(0x8BAB8EEF, 0xB6409C1A), U64(0x1AD089B6, 0xC2F7548E), /* ~= 10^252 */
+ U64(0xAE9672AB, 0xA3D0C320), U64(0xA184AC24, 0x73B529B1), /* ~= 10^253 */
+ U64(0xDA3C0F56, 0x8CC4F3E8), U64(0xC9E5D72D, 0x90A2741E), /* ~= 10^254 */
+ U64(0x88658996, 0x17FB1871), U64(0x7E2FA67C, 0x7A658892), /* ~= 10^255 */
+ U64(0xAA7EEBFB, 0x9DF9DE8D), U64(0xDDBB901B, 0x98FEEAB7), /* ~= 10^256 */
+ U64(0xD51EA6FA, 0x85785631), U64(0x552A7422, 0x7F3EA565), /* ~= 10^257 */
+ U64(0x8533285C, 0x936B35DE), U64(0xD53A8895, 0x8F87275F), /* ~= 10^258 */
+ U64(0xA67FF273, 0xB8460356), U64(0x8A892ABA, 0xF368F137), /* ~= 10^259 */
+ U64(0xD01FEF10, 0xA657842C), U64(0x2D2B7569, 0xB0432D85), /* ~= 10^260 */
+ U64(0x8213F56A, 0x67F6B29B), U64(0x9C3B2962, 0x0E29FC73), /* ~= 10^261 */
+ U64(0xA298F2C5, 0x01F45F42), U64(0x8349F3BA, 0x91B47B8F), /* ~= 10^262 */
+ U64(0xCB3F2F76, 0x42717713), U64(0x241C70A9, 0x36219A73), /* ~= 10^263 */
+ U64(0xFE0EFB53, 0xD30DD4D7), U64(0xED238CD3, 0x83AA0110), /* ~= 10^264 */
+ U64(0x9EC95D14, 0x63E8A506), U64(0xF4363804, 0x324A40AA), /* ~= 10^265 */
+ U64(0xC67BB459, 0x7CE2CE48), U64(0xB143C605, 0x3EDCD0D5), /* ~= 10^266 */
+ U64(0xF81AA16F, 0xDC1B81DA), U64(0xDD94B786, 0x8E94050A), /* ~= 10^267 */
+ U64(0x9B10A4E5, 0xE9913128), U64(0xCA7CF2B4, 0x191C8326), /* ~= 10^268 */
+ U64(0xC1D4CE1F, 0x63F57D72), U64(0xFD1C2F61, 0x1F63A3F0), /* ~= 10^269 */
+ U64(0xF24A01A7, 0x3CF2DCCF), U64(0xBC633B39, 0x673C8CEC), /* ~= 10^270 */
+ U64(0x976E4108, 0x8617CA01), U64(0xD5BE0503, 0xE085D813), /* ~= 10^271 */
+ U64(0xBD49D14A, 0xA79DBC82), U64(0x4B2D8644, 0xD8A74E18), /* ~= 10^272 */
+ U64(0xEC9C459D, 0x51852BA2), U64(0xDDF8E7D6, 0x0ED1219E), /* ~= 10^273 */
+ U64(0x93E1AB82, 0x52F33B45), U64(0xCABB90E5, 0xC942B503), /* ~= 10^274 */
+ U64(0xB8DA1662, 0xE7B00A17), U64(0x3D6A751F, 0x3B936243), /* ~= 10^275 */
+ U64(0xE7109BFB, 0xA19C0C9D), U64(0x0CC51267, 0x0A783AD4), /* ~= 10^276 */
+ U64(0x906A617D, 0x450187E2), U64(0x27FB2B80, 0x668B24C5), /* ~= 10^277 */
+ U64(0xB484F9DC, 0x9641E9DA), U64(0xB1F9F660, 0x802DEDF6), /* ~= 10^278 */
+ U64(0xE1A63853, 0xBBD26451), U64(0x5E7873F8, 0xA0396973), /* ~= 10^279 */
+ U64(0x8D07E334, 0x55637EB2), U64(0xDB0B487B, 0x6423E1E8), /* ~= 10^280 */
+ U64(0xB049DC01, 0x6ABC5E5F), U64(0x91CE1A9A, 0x3D2CDA62), /* ~= 10^281 */
+ U64(0xDC5C5301, 0xC56B75F7), U64(0x7641A140, 0xCC7810FB), /* ~= 10^282 */
+ U64(0x89B9B3E1, 0x1B6329BA), U64(0xA9E904C8, 0x7FCB0A9D), /* ~= 10^283 */
+ U64(0xAC2820D9, 0x623BF429), U64(0x546345FA, 0x9FBDCD44), /* ~= 10^284 */
+ U64(0xD732290F, 0xBACAF133), U64(0xA97C1779, 0x47AD4095), /* ~= 10^285 */
+ U64(0x867F59A9, 0xD4BED6C0), U64(0x49ED8EAB, 0xCCCC485D), /* ~= 10^286 */
+ U64(0xA81F3014, 0x49EE8C70), U64(0x5C68F256, 0xBFFF5A74), /* ~= 10^287 */
+ U64(0xD226FC19, 0x5C6A2F8C), U64(0x73832EEC, 0x6FFF3111), /* ~= 10^288 */
+ U64(0x83585D8F, 0xD9C25DB7), U64(0xC831FD53, 0xC5FF7EAB), /* ~= 10^289 */
+ U64(0xA42E74F3, 0xD032F525), U64(0xBA3E7CA8, 0xB77F5E55), /* ~= 10^290 */
+ U64(0xCD3A1230, 0xC43FB26F), U64(0x28CE1BD2, 0xE55F35EB), /* ~= 10^291 */
+ U64(0x80444B5E, 0x7AA7CF85), U64(0x7980D163, 0xCF5B81B3), /* ~= 10^292 */
+ U64(0xA0555E36, 0x1951C366), U64(0xD7E105BC, 0xC332621F), /* ~= 10^293 */
+ U64(0xC86AB5C3, 0x9FA63440), U64(0x8DD9472B, 0xF3FEFAA7), /* ~= 10^294 */
+ U64(0xFA856334, 0x878FC150), U64(0xB14F98F6, 0xF0FEB951), /* ~= 10^295 */
+ U64(0x9C935E00, 0xD4B9D8D2), U64(0x6ED1BF9A, 0x569F33D3), /* ~= 10^296 */
+ U64(0xC3B83581, 0x09E84F07), U64(0x0A862F80, 0xEC4700C8), /* ~= 10^297 */
+ U64(0xF4A642E1, 0x4C6262C8), U64(0xCD27BB61, 0x2758C0FA), /* ~= 10^298 */
+ U64(0x98E7E9CC, 0xCFBD7DBD), U64(0x8038D51C, 0xB897789C), /* ~= 10^299 */
+ U64(0xBF21E440, 0x03ACDD2C), U64(0xE0470A63, 0xE6BD56C3), /* ~= 10^300 */
+ U64(0xEEEA5D50, 0x04981478), U64(0x1858CCFC, 0xE06CAC74), /* ~= 10^301 */
+ U64(0x95527A52, 0x02DF0CCB), U64(0x0F37801E, 0x0C43EBC8), /* ~= 10^302 */
+ U64(0xBAA718E6, 0x8396CFFD), U64(0xD3056025, 0x8F54E6BA), /* ~= 10^303 */
+ U64(0xE950DF20, 0x247C83FD), U64(0x47C6B82E, 0xF32A2069), /* ~= 10^304 */
+ U64(0x91D28B74, 0x16CDD27E), U64(0x4CDC331D, 0x57FA5441), /* ~= 10^305 */
+ U64(0xB6472E51, 0x1C81471D), U64(0xE0133FE4, 0xADF8E952), /* ~= 10^306 */
+ U64(0xE3D8F9E5, 0x63A198E5), U64(0x58180FDD, 0xD97723A6), /* ~= 10^307 */
+ U64(0x8E679C2F, 0x5E44FF8F), U64(0x570F09EA, 0xA7EA7648), /* ~= 10^308 */
+ U64(0xB201833B, 0x35D63F73), U64(0x2CD2CC65, 0x51E513DA), /* ~= 10^309 */
+ U64(0xDE81E40A, 0x034BCF4F), U64(0xF8077F7E, 0xA65E58D1), /* ~= 10^310 */
+ U64(0x8B112E86, 0x420F6191), U64(0xFB04AFAF, 0x27FAF782), /* ~= 10^311 */
+ U64(0xADD57A27, 0xD29339F6), U64(0x79C5DB9A, 0xF1F9B563), /* ~= 10^312 */
+ U64(0xD94AD8B1, 0xC7380874), U64(0x18375281, 0xAE7822BC), /* ~= 10^313 */
+ U64(0x87CEC76F, 0x1C830548), U64(0x8F229391, 0x0D0B15B5), /* ~= 10^314 */
+ U64(0xA9C2794A, 0xE3A3C69A), U64(0xB2EB3875, 0x504DDB22), /* ~= 10^315 */
+ U64(0xD433179D, 0x9C8CB841), U64(0x5FA60692, 0xA46151EB), /* ~= 10^316 */
+ U64(0x849FEEC2, 0x81D7F328), U64(0xDBC7C41B, 0xA6BCD333), /* ~= 10^317 */
+ U64(0xA5C7EA73, 0x224DEFF3), U64(0x12B9B522, 0x906C0800), /* ~= 10^318 */
+ U64(0xCF39E50F, 0xEAE16BEF), U64(0xD768226B, 0x34870A00), /* ~= 10^319 */
+ U64(0x81842F29, 0xF2CCE375), U64(0xE6A11583, 0x00D46640), /* ~= 10^320 */
+ U64(0xA1E53AF4, 0x6F801C53), U64(0x60495AE3, 0xC1097FD0), /* ~= 10^321 */
+ U64(0xCA5E89B1, 0x8B602368), U64(0x385BB19C, 0xB14BDFC4), /* ~= 10^322 */
+ U64(0xFCF62C1D, 0xEE382C42), U64(0x46729E03, 0xDD9ED7B5), /* ~= 10^323 */
+ U64(0x9E19DB92, 0xB4E31BA9), U64(0x6C07A2C2, 0x6A8346D1) /* ~= 10^324 */
+};
+
+/**
+ Get the cached pow10 value from pow10_sig_table.
+ @param exp10 The exponent of pow(10, e). This value must in range
+ POW10_SIG_TABLE_MIN_EXP to POW10_SIG_TABLE_MAX_EXP.
+ @param hi The highest 64 bits of pow(10, e).
+ @param lo The lower 64 bits after `hi`.
+ */
+static_inline void pow10_table_get_sig(i32 exp10, u64 *hi, u64 *lo) {
+ i32 idx = exp10 - (POW10_SIG_TABLE_MIN_EXP);
+ *hi = pow10_sig_table[idx * 2];
+ *lo = pow10_sig_table[idx * 2 + 1];
+}
+
+/**
+ Get the exponent (base 2) for highest 64 bits significand in pow10_sig_table.
+ */
+static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) {
+ /* e2 = floor(log2(pow(10, e))) - 64 + 1 */
+ /* = floor(e * log2(10) - 63) */
+ *exp2 = (exp10 * 217706 - 4128768) >> 16;
+}
+
+#endif
+
+
+
+/*==============================================================================
+ * JSON Character Matcher
+ *============================================================================*/
+
+/** Character type */
+typedef u8 char_type;
+
+/** Whitespace character: ' ', '\\t', '\\n', '\\r'. */
+static const char_type CHAR_TYPE_SPACE = 1 << 0;
+
+/** Number character: '-', [0-9]. */
+static const char_type CHAR_TYPE_NUMBER = 1 << 1;
+
+/** JSON Escaped character: '"', '\', [0x00-0x1F]. */
+static const char_type CHAR_TYPE_ESC_ASCII = 1 << 2;
+
+/** Non-ASCII character: [0x80-0xFF]. */
+static const char_type CHAR_TYPE_NON_ASCII = 1 << 3;
+
+/** JSON container character: '{', '['. */
+static const char_type CHAR_TYPE_CONTAINER = 1 << 4;
+
+/** Comment character: '/'. */
+static const char_type CHAR_TYPE_COMMENT = 1 << 5;
+
+/** Line end character: '\\n', '\\r', '\0'. */
+static const char_type CHAR_TYPE_LINE_END = 1 << 6;
+
+/** Hexadecimal numeric character: [0-9a-fA-F]. */
+static const char_type CHAR_TYPE_HEX = 1 << 7;
+
+/** Character type table (generate with misc/make_tables.c) */
+static const char_type char_table[256] = {
+ 0x44, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x05, 0x45, 0x04, 0x04, 0x45, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20,
+ 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
+ 0x82, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
+};
+
+/** Match a character with specified type. */
+static_inline bool char_is_type(u8 c, char_type type) {
+ return (char_table[c] & type) != 0;
+}
+
+/** Match a whitespace: ' ', '\\t', '\\n', '\\r'. */
+static_inline bool char_is_space(u8 c) {
+ return char_is_type(c, (char_type)CHAR_TYPE_SPACE);
+}
+
+/** Match a whitespace or comment: ' ', '\\t', '\\n', '\\r', '/'. */
+static_inline bool char_is_space_or_comment(u8 c) {
+ return char_is_type(c, (char_type)(CHAR_TYPE_SPACE | CHAR_TYPE_COMMENT));
+}
+
+/** Match a JSON number: '-', [0-9]. */
+static_inline bool char_is_number(u8 c) {
+ return char_is_type(c, (char_type)CHAR_TYPE_NUMBER);
+}
+
+/** Match a JSON container: '{', '['. */
+static_inline bool char_is_container(u8 c) {
+ return char_is_type(c, (char_type)CHAR_TYPE_CONTAINER);
+}
+
+/** Match a stop character in ASCII string: '"', '\', [0x00-0x1F,0x80-0xFF]. */
+static_inline bool char_is_ascii_stop(u8 c) {
+ return char_is_type(c, (char_type)(CHAR_TYPE_ESC_ASCII |
+ CHAR_TYPE_NON_ASCII));
+}
+
+/** Match a line end character: '\\n', '\\r', '\0'. */
+static_inline bool char_is_line_end(u8 c) {
+ return char_is_type(c, (char_type)CHAR_TYPE_LINE_END);
+}
+
+/** Match a hexadecimal numeric character: [0-9a-fA-F]. */
+static_inline bool char_is_hex(u8 c) {
+ return char_is_type(c, (char_type)CHAR_TYPE_HEX);
+}
+
+
+
+/*==============================================================================
+ * Digit Character Matcher
+ *============================================================================*/
+
+/** Digit type */
+typedef u8 digi_type;
+
+/** Digit: '0'. */
+static const digi_type DIGI_TYPE_ZERO = 1 << 0;
+
+/** Digit: [1-9]. */
+static const digi_type DIGI_TYPE_NONZERO = 1 << 1;
+
+/** Plus sign (positive): '+'. */
+static const digi_type DIGI_TYPE_POS = 1 << 2;
+
+/** Minus sign (negative): '-'. */
+static const digi_type DIGI_TYPE_NEG = 1 << 3;
+
+/** Decimal point: '.' */
+static const digi_type DIGI_TYPE_DOT = 1 << 4;
+
+/** Exponent sign: 'e, 'E'. */
+static const digi_type DIGI_TYPE_EXP = 1 << 5;
+
+/** Digit type table (generate with misc/make_tables.c) */
+static const digi_type digi_table[256] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x10, 0x00,
+ 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/** Match a character with specified type. */
+static_inline bool digi_is_type(u8 d, digi_type type) {
+ return (digi_table[d] & type) != 0;
+}
+
+/** Match a sign: '+', '-' */
+static_inline bool digi_is_sign(u8 d) {
+ return digi_is_type(d, (digi_type)(DIGI_TYPE_POS | DIGI_TYPE_NEG));
+}
+
+/** Match a none zero digit: [1-9] */
+static_inline bool digi_is_nonzero(u8 d) {
+ return digi_is_type(d, (digi_type)DIGI_TYPE_NONZERO);
+}
+
+/** Match a digit: [0-9] */
+static_inline bool digi_is_digit(u8 d) {
+ return digi_is_type(d, (digi_type)(DIGI_TYPE_ZERO | DIGI_TYPE_NONZERO));
+}
+
+/** Match an exponent sign: 'e', 'E'. */
+static_inline bool digi_is_exp(u8 d) {
+ return digi_is_type(d, (digi_type)DIGI_TYPE_EXP);
+}
+
+/** Match a floating point indicator: '.', 'e', 'E'. */
+static_inline bool digi_is_fp(u8 d) {
+ return digi_is_type(d, (digi_type)(DIGI_TYPE_DOT | DIGI_TYPE_EXP));
+}
+
+/** Match a digit or floating point indicator: [0-9], '.', 'e', 'E'. */
+static_inline bool digi_is_digit_or_fp(u8 d) {
+ return digi_is_type(d, (digi_type)(DIGI_TYPE_ZERO | DIGI_TYPE_NONZERO |
+ DIGI_TYPE_DOT | DIGI_TYPE_EXP));
+}
+
+
+
+#if !YYJSON_DISABLE_READER
+
+/*==============================================================================
+ * Hex Character Reader
+ * This function is used by JSON reader to read escaped characters.
+ *============================================================================*/
+
+/**
+ This table is used to convert 4 hex character sequence to a number.
+ A valid hex character [0-9A-Fa-f] will mapped to it's raw number [0x00, 0x0F],
+ an invalid hex character will mapped to [0xF0].
+ (generate with misc/make_tables.c)
+ */
+static const u8 hex_conv_table[256] = {
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0
+};
+
+/**
+ Scans an escaped character sequence as a UTF-16 code unit (branchless).
+ e.g. "\\u005C" should pass "005C" as `cur`.
+
+ This requires the string has 4-byte zero padding.
+ */
+static_inline bool read_hex_u16(const u8 *cur, u16 *val) {
+ u16 c0, c1, c2, c3, t0, t1;
+ c0 = hex_conv_table[cur[0]];
+ c1 = hex_conv_table[cur[1]];
+ c2 = hex_conv_table[cur[2]];
+ c3 = hex_conv_table[cur[3]];
+ t0 = (u16)((c0 << 8) | c2);
+ t1 = (u16)((c1 << 8) | c3);
+ *val = (u16)((t0 << 4) | t1);
+ return ((t0 | t1) & (u16)0xF0F0) == 0;
+}
+
+
+
+/*==============================================================================
+ * JSON Reader Utils
+ * These functions are used by JSON reader to read literals and comments.
+ *============================================================================*/
+
+/** Read 'true' literal, '*cur' should be 't'. */
+static_inline bool read_true(u8 **ptr, yyjson_val *val) {
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ if (likely(byte_match_4(cur, "true"))) {
+ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
+ *end = cur + 4;
+ return true;
+ }
+ return false;
+}
+
+/** Read 'false' literal, '*cur' should be 'f'. */
+static_inline bool read_false(u8 **ptr, yyjson_val *val) {
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ if (likely(byte_match_4(cur + 1, "alse"))) {
+ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
+ *end = cur + 5;
+ return true;
+ }
+ return false;
+}
+
+/** Read 'null' literal, '*cur' should be 'n'. */
+static_inline bool read_null(u8 **ptr, yyjson_val *val) {
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ if (likely(byte_match_4(cur, "null"))) {
+ val->tag = YYJSON_TYPE_NULL;
+ *end = cur + 4;
+ return true;
+ }
+ return false;
+}
+
+/** Read 'Inf' or 'Infinity' literal (ignoring case). */
+static_inline bool read_inf(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) {
+ u8 *hdr = *ptr - sign;
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ if ((cur[0] == 'I' || cur[0] == 'i') &&
+ (cur[1] == 'N' || cur[1] == 'n') &&
+ (cur[2] == 'F' || cur[2] == 'f')) {
+ if ((cur[3] == 'I' || cur[3] == 'i') &&
+ (cur[4] == 'N' || cur[4] == 'n') &&
+ (cur[5] == 'I' || cur[5] == 'i') &&
+ (cur[6] == 'T' || cur[6] == 't') &&
+ (cur[7] == 'Y' || cur[7] == 'y')) {
+ cur += 8;
+ } else {
+ cur += 3;
+ }
+ *end = cur;
+ if (pre) {
+ /* add null-terminator for previous raw string */
+ if (*pre) **pre = '\0';
+ *pre = cur;
+ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW;
+ val->uni.str = (const char *)hdr;
+ } else {
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ val->uni.u64 = f64_raw_get_inf(sign);
+ }
+ return true;
+ }
+ return false;
+}
+
+/** Read 'NaN' literal (ignoring case). */
+static_inline bool read_nan(bool sign, u8 **ptr, u8 **pre, yyjson_val *val) {
+ u8 *hdr = *ptr - sign;
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ if ((cur[0] == 'N' || cur[0] == 'n') &&
+ (cur[1] == 'A' || cur[1] == 'a') &&
+ (cur[2] == 'N' || cur[2] == 'n')) {
+ cur += 3;
+ *end = cur;
+ if (pre) {
+ /* add null-terminator for previous raw string */
+ if (*pre) **pre = '\0';
+ *pre = cur;
+ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW;
+ val->uni.str = (const char *)hdr;
+ } else {
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ val->uni.u64 = f64_raw_get_nan(sign);
+ }
+ return true;
+ }
+ return false;
+}
+
+/** Read 'Inf', 'Infinity' or 'NaN' literal (ignoring case). */
+static_inline bool read_inf_or_nan(bool sign, u8 **ptr, u8 **pre,
+ yyjson_val *val) {
+ if (read_inf(sign, ptr, pre, val)) return true;
+ if (read_nan(sign, ptr, pre, val)) return true;
+ return false;
+}
+
+/** Read a JSON number as raw string. */
+static_noinline bool read_number_raw(u8 **ptr,
+ u8 **pre,
+ yyjson_read_flag flg,
+ yyjson_val *val,
+ const char **msg) {
+
+#define return_err(_pos, _msg) do { \
+ *msg = _msg; \
+ *end = _pos; \
+ return false; \
+} while (false)
+
+#define return_raw() do { \
+ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \
+ val->uni.str = (const char *)hdr; \
+ *pre = cur; *end = cur; return true; \
+} while (false)
+
+ u8 *hdr = *ptr;
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+
+ /* add null-terminator for previous raw string */
+ if (*pre) **pre = '\0';
+
+ /* skip sign */
+ cur += (*cur == '-');
+
+ /* read first digit, check leading zero */
+ if (unlikely(!digi_is_digit(*cur))) {
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_inf_or_nan(*hdr == '-', &cur, pre, val)) return_raw();
+ }
+ return_err(cur, "no digit after minus sign");
+ }
+
+ /* read integral part */
+ if (*cur == '0') {
+ cur++;
+ if (unlikely(digi_is_digit(*cur))) {
+ return_err(cur - 1, "number with leading zero is not allowed");
+ }
+ if (!digi_is_fp(*cur)) return_raw();
+ } else {
+ while (digi_is_digit(*cur)) cur++;
+ if (!digi_is_fp(*cur)) return_raw();
+ }
+
+ /* read fraction part */
+ if (*cur == '.') {
+ cur++;
+ if (!digi_is_digit(*cur++)) {
+ return_err(cur, "no digit after decimal point");
+ }
+ while (digi_is_digit(*cur)) cur++;
+ }
+
+ /* read exponent part */
+ if (digi_is_exp(*cur)) {
+ cur += 1 + digi_is_sign(cur[1]);
+ if (!digi_is_digit(*cur++)) {
+ return_err(cur, "no digit after exponent sign");
+ }
+ while (digi_is_digit(*cur)) cur++;
+ }
+
+ return_raw();
+
+#undef return_err
+#undef return_raw
+}
+
+/**
+ Skips spaces and comments as many as possible.
+
+ It will return false in these cases:
+ 1. No character is skipped. The 'end' pointer is set as input cursor.
+ 2. A multiline comment is not closed. The 'end' pointer is set as the head
+ of this comment block.
+ */
+static_noinline bool skip_spaces_and_comments(u8 **ptr) {
+ u8 *hdr = *ptr;
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ while (true) {
+ if (byte_match_2(cur, "/*")) {
+ hdr = cur;
+ cur += 2;
+ while (true) {
+ if (byte_match_2(cur, "*/")) {
+ cur += 2;
+ break;
+ }
+ if (*cur == 0) {
+ *end = hdr;
+ return false;
+ }
+ cur++;
+ }
+ continue;
+ }
+ if (byte_match_2(cur, "//")) {
+ cur += 2;
+ while (!char_is_line_end(*cur)) cur++;
+ continue;
+ }
+ if (char_is_space(*cur)) {
+ cur += 1;
+ while (char_is_space(*cur)) cur++;
+ continue;
+ }
+ break;
+ }
+ *end = cur;
+ return hdr != cur;
+}
+
+/**
+ Check truncated string.
+ Returns true if `cur` match `str` but is truncated.
+ */
+static_inline bool is_truncated_str(u8 *cur, u8 *end,
+ const char *str,
+ bool case_sensitive) {
+ usize len = strlen(str);
+ if (cur + len <= end || end <= cur) return false;
+ if (case_sensitive) {
+ return memcmp(cur, str, (usize)(end - cur)) == 0;
+ }
+ for (; cur < end; cur++, str++) {
+ if ((*cur != (u8)*str) && (*cur != (u8)*str - 'a' + 'A')) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ Check truncated JSON on parsing errors.
+ Returns true if the input is valid but truncated.
+ */
+static_noinline bool is_truncated_end(u8 *hdr, u8 *cur, u8 *end,
+ yyjson_read_code code,
+ yyjson_read_flag flg) {
+ if (cur >= end) return true;
+ if (code == YYJSON_READ_ERROR_LITERAL) {
+ if (is_truncated_str(cur, end, "true", true) ||
+ is_truncated_str(cur, end, "false", true) ||
+ is_truncated_str(cur, end, "null", true)) {
+ return true;
+ }
+ }
+ if (code == YYJSON_READ_ERROR_UNEXPECTED_CHARACTER ||
+ code == YYJSON_READ_ERROR_INVALID_NUMBER ||
+ code == YYJSON_READ_ERROR_LITERAL) {
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (*cur == '-') cur++;
+ if (is_truncated_str(cur, end, "infinity", false) ||
+ is_truncated_str(cur, end, "nan", false)) {
+ return true;
+ }
+ }
+ }
+ if (code == YYJSON_READ_ERROR_UNEXPECTED_CONTENT) {
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (hdr + 3 <= cur &&
+ is_truncated_str(cur - 3, end, "infinity", false)) {
+ return true; /* e.g. infin would be read as inf + in */
+ }
+ }
+ }
+ if (code == YYJSON_READ_ERROR_INVALID_STRING) {
+ usize len = (usize)(end - cur);
+
+ /* unicode escape sequence */
+ if (*cur == '\\') {
+ if (len == 1) return true;
+ if (len <= 5) {
+ if (*++cur != 'u') return false;
+ for (++cur; cur < end; cur++) {
+ if (!char_is_hex(*cur)) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /* 2 to 4 bytes UTF-8, see `read_string()` for details. */
+ if (*cur & 0x80) {
+ u8 c0 = cur[0], c1 = cur[1], c2 = cur[2];
+ if (len == 1) {
+ /* 2 bytes UTF-8, truncated */
+ if ((c0 & 0xE0) == 0xC0 && (c0 & 0x1E) != 0x00) return true;
+ /* 3 bytes UTF-8, truncated */
+ if ((c0 & 0xF0) == 0xE0) return true;
+ /* 4 bytes UTF-8, truncated */
+ if ((c0 & 0xF8) == 0xF0 && (c0 & 0x07) <= 0x04) return true;
+ }
+ if (len == 2) {
+ /* 3 bytes UTF-8, truncated */
+ if ((c0 & 0xF0) == 0xE0 &&
+ (c1 & 0xC0) == 0x80) {
+ u8 pat = (u8)(((c0 & 0x0F) << 1) | ((c1 & 0x20) >> 5));
+ return 0x01 <= pat && pat != 0x1B;
+ }
+ /* 4 bytes UTF-8, truncated */
+ if ((c0 & 0xF8) == 0xF0 &&
+ (c1 & 0xC0) == 0x80) {
+ u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4));
+ return 0x01 <= pat && pat <= 0x10;
+ }
+ }
+ if (len == 3) {
+ /* 4 bytes UTF-8, truncated */
+ if ((c0 & 0xF8) == 0xF0 &&
+ (c1 & 0xC0) == 0x80 &&
+ (c2 & 0xC0) == 0x80) {
+ u8 pat = (u8)(((c0 & 0x07) << 2) | ((c1 & 0x30) >> 4));
+ return 0x01 <= pat && pat <= 0x10;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+
+#if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_READER */
+
+/*==============================================================================
+ * BigInt For Floating Point Number Reader
+ *
+ * The bigint algorithm is used by floating-point number reader to get correctly
+ * rounded result for numbers with lots of digits. This part of code is rarely
+ * used for common numbers.
+ *============================================================================*/
+
+/** Maximum exponent of exact pow10 */
+#define U64_POW10_MAX_EXP 19
+
+/** Table: [ 10^0, ..., 10^19 ] (generate with misc/make_tables.c) */
+static const u64 u64_pow10_table[U64_POW10_MAX_EXP + 1] = {
+ U64(0x00000000, 0x00000001), U64(0x00000000, 0x0000000A),
+ U64(0x00000000, 0x00000064), U64(0x00000000, 0x000003E8),
+ U64(0x00000000, 0x00002710), U64(0x00000000, 0x000186A0),
+ U64(0x00000000, 0x000F4240), U64(0x00000000, 0x00989680),
+ U64(0x00000000, 0x05F5E100), U64(0x00000000, 0x3B9ACA00),
+ U64(0x00000002, 0x540BE400), U64(0x00000017, 0x4876E800),
+ U64(0x000000E8, 0xD4A51000), U64(0x00000918, 0x4E72A000),
+ U64(0x00005AF3, 0x107A4000), U64(0x00038D7E, 0xA4C68000),
+ U64(0x002386F2, 0x6FC10000), U64(0x01634578, 0x5D8A0000),
+ U64(0x0DE0B6B3, 0xA7640000), U64(0x8AC72304, 0x89E80000)
+};
+
+/** Maximum numbers of chunks used by a bigint (58 is enough here). */
+#define BIGINT_MAX_CHUNKS 64
+
+/** Unsigned arbitrarily large integer */
+typedef struct bigint {
+ u32 used; /* used chunks count, should not be 0 */
+ u64 bits[BIGINT_MAX_CHUNKS]; /* chunks */
+} bigint;
+
+/**
+ Evaluate 'big += val'.
+ @param big A big number (can be 0).
+ @param val An unsigned integer (can be 0).
+ */
+static_inline void bigint_add_u64(bigint *big, u64 val) {
+ u32 idx, max;
+ u64 num = big->bits[0];
+ u64 add = num + val;
+ big->bits[0] = add;
+ if (likely((add >= num) || (add >= val))) return;
+ for ((void)(idx = 1), max = big->used; idx < max; idx++) {
+ if (likely(big->bits[idx] != U64_MAX)) {
+ big->bits[idx] += 1;
+ return;
+ }
+ big->bits[idx] = 0;
+ }
+ big->bits[big->used++] = 1;
+}
+
+/**
+ Evaluate 'big *= val'.
+ @param big A big number (can be 0).
+ @param val An unsigned integer (cannot be 0).
+ */
+static_inline void bigint_mul_u64(bigint *big, u64 val) {
+ u32 idx = 0, max = big->used;
+ u64 hi, lo, carry = 0;
+ for (; idx < max; idx++) {
+ if (big->bits[idx]) break;
+ }
+ for (; idx < max; idx++) {
+ u128_mul_add(big->bits[idx], val, carry, &hi, &lo);
+ big->bits[idx] = lo;
+ carry = hi;
+ }
+ if (carry) big->bits[big->used++] = carry;
+}
+
+/**
+ Evaluate 'big *= 2^exp'.
+ @param big A big number (can be 0).
+ @param exp An exponent integer (can be 0).
+ */
+static_inline void bigint_mul_pow2(bigint *big, u32 exp) {
+ u32 shft = exp % 64;
+ u32 move = exp / 64;
+ u32 idx = big->used;
+ if (unlikely(shft == 0)) {
+ for (; idx > 0; idx--) {
+ big->bits[idx + move - 1] = big->bits[idx - 1];
+ }
+ big->used += move;
+ while (move) big->bits[--move] = 0;
+ } else {
+ big->bits[idx] = 0;
+ for (; idx > 0; idx--) {
+ u64 num = big->bits[idx] << shft;
+ num |= big->bits[idx - 1] >> (64 - shft);
+ big->bits[idx + move] = num;
+ }
+ big->bits[move] = big->bits[0] << shft;
+ big->used += move + (big->bits[big->used + move] > 0);
+ while (move) big->bits[--move] = 0;
+ }
+}
+
+/**
+ Evaluate 'big *= 10^exp'.
+ @param big A big number (can be 0).
+ @param exp An exponent integer (cannot be 0).
+ */
+static_inline void bigint_mul_pow10(bigint *big, i32 exp) {
+ for (; exp >= U64_POW10_MAX_EXP; exp -= U64_POW10_MAX_EXP) {
+ bigint_mul_u64(big, u64_pow10_table[U64_POW10_MAX_EXP]);
+ }
+ if (exp) {
+ bigint_mul_u64(big, u64_pow10_table[exp]);
+ }
+}
+
+/**
+ Compare two bigint.
+ @return -1 if 'a < b', +1 if 'a > b', 0 if 'a == b'.
+ */
+static_inline i32 bigint_cmp(bigint *a, bigint *b) {
+ u32 idx = a->used;
+ if (a->used < b->used) return -1;
+ if (a->used > b->used) return +1;
+ while (idx-- > 0) {
+ u64 av = a->bits[idx];
+ u64 bv = b->bits[idx];
+ if (av < bv) return -1;
+ if (av > bv) return +1;
+ }
+ return 0;
+}
+
+/**
+ Evaluate 'big = val'.
+ @param big A big number (can be 0).
+ @param val An unsigned integer (can be 0).
+ */
+static_inline void bigint_set_u64(bigint *big, u64 val) {
+ big->used = 1;
+ big->bits[0] = val;
+}
+
+/** Set a bigint with floating point number string. */
+static_noinline void bigint_set_buf(bigint *big, u64 sig, i32 *exp,
+ u8 *sig_cut, u8 *sig_end, u8 *dot_pos) {
+
+ if (unlikely(!sig_cut)) {
+ /* no digit cut, set significant part only */
+ bigint_set_u64(big, sig);
+ return;
+
+ } else {
+ /* some digits were cut, read them from 'sig_cut' to 'sig_end' */
+ u8 *hdr = sig_cut;
+ u8 *cur = hdr;
+ u32 len = 0;
+ u64 val = 0;
+ bool dig_big_cut = false;
+ bool has_dot = (hdr < dot_pos) & (dot_pos < sig_end);
+ u32 dig_len_total = U64_SAFE_DIG + (u32)(sig_end - hdr) - has_dot;
+
+ sig -= (*sig_cut >= '5'); /* sig was rounded before */
+ if (dig_len_total > F64_MAX_DEC_DIG) {
+ dig_big_cut = true;
+ sig_end -= dig_len_total - (F64_MAX_DEC_DIG + 1);
+ sig_end -= (dot_pos + 1 == sig_end);
+ dig_len_total = (F64_MAX_DEC_DIG + 1);
+ }
+ *exp -= (i32)dig_len_total - U64_SAFE_DIG;
+
+ big->used = 1;
+ big->bits[0] = sig;
+ while (cur < sig_end) {
+ if (likely(cur != dot_pos)) {
+ val = val * 10 + (u8)(*cur++ - '0');
+ len++;
+ if (unlikely(cur == sig_end && dig_big_cut)) {
+ /* The last digit must be non-zero, */
+ /* set it to '1' for correct rounding. */
+ val = val - (val % 10) + 1;
+ }
+ if (len == U64_SAFE_DIG || cur == sig_end) {
+ bigint_mul_pow10(big, (i32)len);
+ bigint_add_u64(big, val);
+ val = 0;
+ len = 0;
+ }
+ } else {
+ cur++;
+ }
+ }
+ }
+}
+
+
+
+/*==============================================================================
+ * Diy Floating Point
+ *============================================================================*/
+
+/** "Do It Yourself Floating Point" struct. */
+typedef struct diy_fp {
+ u64 sig; /* significand */
+ i32 exp; /* exponent, base 2 */
+ i32 pad; /* padding, useless */
+} diy_fp;
+
+/** Get cached rounded diy_fp with pow(10, e) The input value must in range
+ [POW10_SIG_TABLE_MIN_EXP, POW10_SIG_TABLE_MAX_EXP]. */
+static_inline diy_fp diy_fp_get_cached_pow10(i32 exp10) {
+ diy_fp fp;
+ u64 sig_ext;
+ pow10_table_get_sig(exp10, &fp.sig, &sig_ext);
+ pow10_table_get_exp(exp10, &fp.exp);
+ fp.sig += (sig_ext >> 63);
+ return fp;
+}
+
+/** Returns fp * fp2. */
+static_inline diy_fp diy_fp_mul(diy_fp fp, diy_fp fp2) {
+ u64 hi, lo;
+ u128_mul(fp.sig, fp2.sig, &hi, &lo);
+ fp.sig = hi + (lo >> 63);
+ fp.exp += fp2.exp + 64;
+ return fp;
+}
+
+/** Convert diy_fp to IEEE-754 raw value. */
+static_inline u64 diy_fp_to_ieee_raw(diy_fp fp) {
+ u64 sig = fp.sig;
+ i32 exp = fp.exp;
+ u32 lz_bits;
+ if (unlikely(fp.sig == 0)) return 0;
+
+ lz_bits = u64_lz_bits(sig);
+ sig <<= lz_bits;
+ sig >>= F64_BITS - F64_SIG_FULL_BITS;
+ exp -= (i32)lz_bits;
+ exp += F64_BITS - F64_SIG_FULL_BITS;
+ exp += F64_SIG_BITS;
+
+ if (unlikely(exp >= F64_MAX_BIN_EXP)) {
+ /* overflow */
+ return F64_RAW_INF;
+ } else if (likely(exp >= F64_MIN_BIN_EXP - 1)) {
+ /* normal */
+ exp += F64_EXP_BIAS;
+ return ((u64)exp << F64_SIG_BITS) | (sig & F64_SIG_MASK);
+ } else if (likely(exp >= F64_MIN_BIN_EXP - F64_SIG_FULL_BITS)) {
+ /* subnormal */
+ return sig >> (F64_MIN_BIN_EXP - exp - 1);
+ } else {
+ /* underflow */
+ return 0;
+ }
+}
+
+
+
+/*==============================================================================
+ * JSON Number Reader (IEEE-754)
+ *============================================================================*/
+
+/** Maximum exact pow10 exponent for double value. */
+#define F64_POW10_EXP_MAX_EXACT 22
+
+/** Cached pow10 table. */
+static const f64 f64_pow10_table[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12,
+ 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22
+};
+
+/**
+ Read a JSON number.
+
+ 1. This function assume that the floating-point number is in IEEE-754 format.
+ 2. This function support uint64/int64/double number. If an integer number
+ cannot fit in uint64/int64, it will returns as a double number. If a double
+ number is infinite, the return value is based on flag.
+ 3. This function (with inline attribute) may generate a lot of instructions.
+ */
+static_inline bool read_number(u8 **ptr,
+ u8 **pre,
+ yyjson_read_flag flg,
+ yyjson_val *val,
+ const char **msg) {
+
+#define return_err(_pos, _msg) do { \
+ *msg = _msg; \
+ *end = _pos; \
+ return false; \
+} while (false)
+
+#define return_0() do { \
+ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \
+ val->uni.u64 = 0; \
+ *end = cur; return true; \
+} while (false)
+
+#define return_i64(_v) do { \
+ val->tag = YYJSON_TYPE_NUM | (u8)((u8)sign << 3); \
+ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \
+ *end = cur; return true; \
+} while (false)
+
+#define return_f64(_v) do { \
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \
+ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \
+ *end = cur; return true; \
+} while (false)
+
+#define return_f64_bin(_v) do { \
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \
+ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \
+ *end = cur; return true; \
+} while (false)
+
+#define return_inf() do { \
+ if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); \
+ if (has_read_flag(ALLOW_INF_AND_NAN)) return_f64_bin(F64_RAW_INF); \
+ else return_err(hdr, "number is infinity when parsed as double"); \
+} while (false)
+
+#define return_raw() do { \
+ if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \
+ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \
+ val->uni.str = (const char *)hdr; \
+ *pre = cur; *end = cur; return true; \
+} while (false)
+
+ u8 *sig_cut = NULL; /* significant part cutting position for long number */
+ u8 *sig_end = NULL; /* significant part ending position */
+ u8 *dot_pos = NULL; /* decimal point position */
+
+ u64 sig = 0; /* significant part of the number */
+ i32 exp = 0; /* exponent part of the number */
+
+ bool exp_sign; /* temporary exponent sign from literal part */
+ i64 exp_sig = 0; /* temporary exponent number from significant part */
+ i64 exp_lit = 0; /* temporary exponent number from exponent literal part */
+ u64 num; /* temporary number for reading */
+ u8 *tmp; /* temporary cursor for reading */
+
+ u8 *hdr = *ptr;
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ bool sign;
+
+ /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */
+ if (has_read_flag(NUMBER_AS_RAW)) {
+ return read_number_raw(ptr, pre, flg, val, msg);
+ }
+
+ sign = (*hdr == '-');
+ cur += sign;
+
+ /* begin with a leading zero or non-digit */
+ if (unlikely(!digi_is_nonzero(*cur))) { /* 0 or non-digit char */
+ if (unlikely(*cur != '0')) { /* non-digit char */
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_inf_or_nan(sign, &cur, pre, val)) {
+ *end = cur;
+ return true;
+ }
+ }
+ return_err(cur, "no digit after minus sign");
+ }
+ /* begin with 0 */
+ if (likely(!digi_is_digit_or_fp(*++cur))) return_0();
+ if (likely(*cur == '.')) {
+ dot_pos = cur++;
+ if (unlikely(!digi_is_digit(*cur))) {
+ return_err(cur, "no digit after decimal point");
+ }
+ while (unlikely(*cur == '0')) cur++;
+ if (likely(digi_is_digit(*cur))) {
+ /* first non-zero digit after decimal point */
+ sig = (u64)(*cur - '0'); /* read first digit */
+ cur--;
+ goto digi_frac_1; /* continue read fraction part */
+ }
+ }
+ if (unlikely(digi_is_digit(*cur))) {
+ return_err(cur - 1, "number with leading zero is not allowed");
+ }
+ if (unlikely(digi_is_exp(*cur))) { /* 0 with any exponent is still 0 */
+ cur += (usize)1 + digi_is_sign(cur[1]);
+ if (unlikely(!digi_is_digit(*cur))) {
+ return_err(cur, "no digit after exponent sign");
+ }
+ while (digi_is_digit(*++cur));
+ }
+ return_f64_bin(0);
+ }
+
+ /* begin with non-zero digit */
+ sig = (u64)(*cur - '0');
+
+ /*
+ Read integral part, same as the following code.
+
+ for (int i = 1; i <= 18; i++) {
+ num = cur[i] - '0';
+ if (num <= 9) sig = num + sig * 10;
+ else goto digi_sepr_i;
+ }
+ */
+#define expr_intg(i) \
+ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \
+ else { goto digi_sepr_##i; }
+ repeat_in_1_18(expr_intg)
+#undef expr_intg
+
+
+ cur += 19; /* skip continuous 19 digits */
+ if (!digi_is_digit_or_fp(*cur)) {
+ /* this number is an integer consisting of 19 digits */
+ if (sign && (sig > ((u64)1 << 63))) { /* overflow */
+ if (has_read_flag(BIGNUM_AS_RAW)) return_raw();
+ return_f64(normalized_u64_to_f64(sig));
+ }
+ return_i64(sig);
+ }
+ goto digi_intg_more; /* read more digits in integral part */
+
+
+ /* process first non-digit character */
+#define expr_sepr(i) \
+ digi_sepr_##i: \
+ if (likely(!digi_is_fp(cur[i]))) { cur += i; return_i64(sig); } \
+ dot_pos = cur + i; \
+ if (likely(cur[i] == '.')) goto digi_frac_##i; \
+ cur += i; sig_end = cur; goto digi_exp_more;
+ repeat_in_1_18(expr_sepr)
+#undef expr_sepr
+
+
+ /* read fraction part */
+#define expr_frac(i) \
+ digi_frac_##i: \
+ if (likely((num = (u64)(cur[i + 1] - (u8)'0')) <= 9)) \
+ sig = num + sig * 10; \
+ else { goto digi_stop_##i; }
+ repeat_in_1_18(expr_frac)
+#undef expr_frac
+
+ cur += 20; /* skip 19 digits and 1 decimal point */
+ if (!digi_is_digit(*cur)) goto digi_frac_end; /* fraction part end */
+ goto digi_frac_more; /* read more digits in fraction part */
+
+
+ /* significant part end */
+#define expr_stop(i) \
+ digi_stop_##i: \
+ cur += i + 1; \
+ goto digi_frac_end;
+ repeat_in_1_18(expr_stop)
+#undef expr_stop
+
+
+ /* read more digits in integral part */
+digi_intg_more:
+ if (digi_is_digit(*cur)) {
+ if (!digi_is_digit_or_fp(cur[1])) {
+ /* this number is an integer consisting of 20 digits */
+ num = (u64)(*cur - '0');
+ if ((sig < (U64_MAX / 10)) ||
+ (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) {
+ sig = num + sig * 10;
+ cur++;
+ /* convert to double if overflow */
+ if (sign) {
+ if (has_read_flag(BIGNUM_AS_RAW)) return_raw();
+ return_f64(normalized_u64_to_f64(sig));
+ }
+ return_i64(sig);
+ }
+ }
+ }
+
+ if (digi_is_exp(*cur)) {
+ dot_pos = cur;
+ goto digi_exp_more;
+ }
+
+ if (*cur == '.') {
+ dot_pos = cur++;
+ if (!digi_is_digit(*cur)) {
+ return_err(cur, "no digit after decimal point");
+ }
+ }
+
+
+ /* read more digits in fraction part */
+digi_frac_more:
+ sig_cut = cur; /* too large to fit in u64, excess digits need to be cut */
+ sig += (*cur >= '5'); /* round */
+ while (digi_is_digit(*++cur));
+ if (!dot_pos) {
+ if (!digi_is_fp(*cur) && has_read_flag(BIGNUM_AS_RAW)) {
+ return_raw(); /* it's a large integer */
+ }
+ dot_pos = cur;
+ if (*cur == '.') {
+ if (!digi_is_digit(*++cur)) {
+ return_err(cur, "no digit after decimal point");
+ }
+ while (digi_is_digit(*cur)) cur++;
+ }
+ }
+ exp_sig = (i64)(dot_pos - sig_cut);
+ exp_sig += (dot_pos < sig_cut);
+
+ /* ignore trailing zeros */
+ tmp = cur - 1;
+ while (*tmp == '0' || *tmp == '.') tmp--;
+ if (tmp < sig_cut) {
+ sig_cut = NULL;
+ } else {
+ sig_end = cur;
+ }
+
+ if (digi_is_exp(*cur)) goto digi_exp_more;
+ goto digi_exp_finish;
+
+
+ /* fraction part end */
+digi_frac_end:
+ if (unlikely(dot_pos + 1 == cur)) {
+ return_err(cur, "no digit after decimal point");
+ }
+ sig_end = cur;
+ exp_sig = -(i64)((u64)(cur - dot_pos) - 1);
+ if (likely(!digi_is_exp(*cur))) {
+ if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) {
+ return_f64_bin(0); /* underflow */
+ }
+ exp = (i32)exp_sig;
+ goto digi_finish;
+ } else {
+ goto digi_exp_more;
+ }
+
+
+ /* read exponent part */
+digi_exp_more:
+ exp_sign = (*++cur == '-');
+ cur += digi_is_sign(*cur);
+ if (unlikely(!digi_is_digit(*cur))) {
+ return_err(cur, "no digit after exponent sign");
+ }
+ while (*cur == '0') cur++;
+
+ /* read exponent literal */
+ tmp = cur;
+ while (digi_is_digit(*cur)) {
+ exp_lit = (i64)((u8)(*cur++ - '0') + (u64)exp_lit * 10);
+ }
+ if (unlikely(cur - tmp >= U64_SAFE_DIG)) {
+ if (exp_sign) {
+ return_f64_bin(0); /* underflow */
+ } else {
+ return_inf(); /* overflow */
+ }
+ }
+ exp_sig += exp_sign ? -exp_lit : exp_lit;
+
+
+ /* validate exponent value */
+digi_exp_finish:
+ if (unlikely(exp_sig < F64_MIN_DEC_EXP - 19)) {
+ return_f64_bin(0); /* underflow */
+ }
+ if (unlikely(exp_sig > F64_MAX_DEC_EXP)) {
+ return_inf(); /* overflow */
+ }
+ exp = (i32)exp_sig;
+
+
+ /* all digit read finished */
+digi_finish:
+
+ /*
+ Fast path 1:
+
+ 1. The floating-point number calculation should be accurate, see the
+ comments of macro `YYJSON_DOUBLE_MATH_CORRECT`.
+ 2. Correct rounding should be performed (fegetround() == FE_TONEAREST).
+ 3. The input of floating point number calculation does not lose precision,
+ which means: 64 - leading_zero(input) - trailing_zero(input) < 53.
+
+ We don't check all available inputs here, because that would make the code
+ more complicated, and not friendly to branch predictor.
+ */
+#if YYJSON_DOUBLE_MATH_CORRECT
+ if (sig < ((u64)1 << 53) &&
+ exp >= -F64_POW10_EXP_MAX_EXACT &&
+ exp <= +F64_POW10_EXP_MAX_EXACT) {
+ f64 dbl = (f64)sig;
+ if (exp < 0) {
+ dbl /= f64_pow10_table[-exp];
+ } else {
+ dbl *= f64_pow10_table[+exp];
+ }
+ return_f64(dbl);
+ }
+#endif
+
+ /*
+ Fast path 2:
+
+ To keep it simple, we only accept normal number here,
+ let the slow path to handle subnormal and infinity number.
+ */
+ if (likely(!sig_cut &&
+ exp > -F64_MAX_DEC_EXP + 1 &&
+ exp < +F64_MAX_DEC_EXP - 20)) {
+ /*
+ The result value is exactly equal to (sig * 10^exp),
+ the exponent part (10^exp) can be converted to (sig2 * 2^exp2).
+
+ The sig2 can be an infinite length number, only the highest 128 bits
+ is cached in the pow10_sig_table.
+
+ Now we have these bits:
+ sig1 (normalized 64bit) : aaaaaaaa
+ sig2 (higher 64bit) : bbbbbbbb
+ sig2_ext (lower 64bit) : cccccccc
+ sig2_cut (extra unknown bits) : dddddddddddd....
+
+ And the calculation process is:
+ ----------------------------------------
+ aaaaaaaa *
+ bbbbbbbbccccccccdddddddddddd....
+ ----------------------------------------
+ abababababababab +
+ acacacacacacacac +
+ adadadadadadadadadad....
+ ----------------------------------------
+ [hi____][lo____] +
+ [hi2___][lo2___] +
+ [unknown___________....]
+ ----------------------------------------
+
+ The addition with carry may affect higher bits, but if there is a 0
+ in higher bits, the bits higher than 0 will not be affected.
+
+ `lo2` + `unknown` may get a carry bit and may affect `hi2`, the max
+ value of `hi2` is 0xFFFFFFFFFFFFFFFE, so `hi2` will not overflow.
+
+ `lo` + `hi2` may also get a carry bit and may affect `hi`, but only
+ the highest significant 53 bits of `hi` is needed. If there is a 0
+ in the lower bits of `hi`, then all the following bits can be dropped.
+
+ To convert the result to IEEE-754 double number, we need to perform
+ correct rounding:
+ 1. if bit 54 is 0, round down,
+ 2. if bit 54 is 1 and any bit beyond bit 54 is 1, round up,
+ 3. if bit 54 is 1 and all bits beyond bit 54 are 0, round to even,
+ as the extra bits is unknown, this case will not be handled here.
+ */
+
+ u64 raw;
+ u64 sig1, sig2, sig2_ext, hi, lo, hi2, lo2, add, bits;
+ i32 exp2;
+ u32 lz;
+ bool exact = false, carry, round_up;
+
+ /* convert (10^exp) to (sig2 * 2^exp2) */
+ pow10_table_get_sig(exp, &sig2, &sig2_ext);
+ pow10_table_get_exp(exp, &exp2);
+
+ /* normalize and multiply */
+ lz = u64_lz_bits(sig);
+ sig1 = sig << lz;
+ exp2 -= (i32)lz;
+ u128_mul(sig1, sig2, &hi, &lo);
+
+ /*
+ The `hi` is in range [0x4000000000000000, 0xFFFFFFFFFFFFFFFE],
+ To get normalized value, `hi` should be shifted to the left by 0 or 1.
+
+ The highest significant 53 bits is used by IEEE-754 double number,
+ and the bit 54 is used to detect rounding direction.
+
+ The lowest (64 - 54 - 1) bits is used to check whether it contains 0.
+ */
+ bits = hi & (((u64)1 << (64 - 54 - 1)) - 1);
+ if (bits - 1 < (((u64)1 << (64 - 54 - 1)) - 2)) {
+ /*
+ (bits != 0 && bits != 0x1FF) => (bits - 1 < 0x1FF - 1)
+ The `bits` is not zero, so we don't need to check `round to even`
+ case. The `bits` contains bit `0`, so we can drop the extra bits
+ after `0`.
+ */
+ exact = true;
+
+ } else {
+ /*
+ (bits == 0 || bits == 0x1FF)
+ The `bits` is filled with all `0` or all `1`, so we need to check
+ lower bits with another 64-bit multiplication.
+ */
+ u128_mul(sig1, sig2_ext, &hi2, &lo2);
+
+ add = lo + hi2;
+ if (add + 1 > (u64)1) {
+ /*
+ (add != 0 && add != U64_MAX) => (add + 1 > 1)
+ The `add` is not zero, so we don't need to check `round to
+ even` case. The `add` contains bit `0`, so we can drop the
+ extra bits after `0`. The `hi` cannot be U64_MAX, so it will
+ not overflow.
+ */
+ carry = add < lo || add < hi2;
+ hi += carry;
+ exact = true;
+ }
+ }
+
+ if (exact) {
+ /* normalize */
+ lz = hi < ((u64)1 << 63);
+ hi <<= lz;
+ exp2 -= (i32)lz;
+ exp2 += 64;
+
+ /* test the bit 54 and get rounding direction */
+ round_up = (hi & ((u64)1 << (64 - 54))) > (u64)0;
+ hi += (round_up ? ((u64)1 << (64 - 54)) : (u64)0);
+
+ /* test overflow */
+ if (hi < ((u64)1 << (64 - 54))) {
+ hi = ((u64)1 << 63);
+ exp2 += 1;
+ }
+
+ /* This is a normal number, convert it to IEEE-754 format. */
+ hi >>= F64_BITS - F64_SIG_FULL_BITS;
+ exp2 += F64_BITS - F64_SIG_FULL_BITS + F64_SIG_BITS;
+ exp2 += F64_EXP_BIAS;
+ raw = ((u64)exp2 << F64_SIG_BITS) | (hi & F64_SIG_MASK);
+ return_f64_bin(raw);
+ }
+ }
+
+ /*
+ Slow path: read double number exactly with diyfp.
+ 1. Use cached diyfp to get an approximation value.
+ 2. Use bigcomp to check the approximation value if needed.
+
+ This algorithm refers to google's double-conversion project:
+ https://github.com/google/double-conversion
+ */
+ {
+ const i32 ERR_ULP_LOG = 3;
+ const i32 ERR_ULP = 1 << ERR_ULP_LOG;
+ const i32 ERR_CACHED_POW = ERR_ULP / 2;
+ const i32 ERR_MUL_FIXED = ERR_ULP / 2;
+ const i32 DIY_SIG_BITS = 64;
+ const i32 EXP_BIAS = F64_EXP_BIAS + F64_SIG_BITS;
+ const i32 EXP_SUBNORMAL = -EXP_BIAS + 1;
+
+ u64 fp_err;
+ u32 bits;
+ i32 order_of_magnitude;
+ i32 effective_significand_size;
+ i32 precision_digits_count;
+ u64 precision_bits;
+ u64 half_way;
+
+ u64 raw;
+ diy_fp fp, fp_upper;
+ bigint big_full, big_comp;
+ i32 cmp;
+
+ fp.sig = sig;
+ fp.exp = 0;
+ fp_err = sig_cut ? (u64)(ERR_ULP / 2) : (u64)0;
+
+ /* normalize */
+ bits = u64_lz_bits(fp.sig);
+ fp.sig <<= bits;
+ fp.exp -= (i32)bits;
+ fp_err <<= bits;
+
+ /* multiply and add error */
+ fp = diy_fp_mul(fp, diy_fp_get_cached_pow10(exp));
+ fp_err += (u64)ERR_CACHED_POW + (fp_err != 0) + (u64)ERR_MUL_FIXED;
+
+ /* normalize */
+ bits = u64_lz_bits(fp.sig);
+ fp.sig <<= bits;
+ fp.exp -= (i32)bits;
+ fp_err <<= bits;
+
+ /* effective significand */
+ order_of_magnitude = DIY_SIG_BITS + fp.exp;
+ if (likely(order_of_magnitude >= EXP_SUBNORMAL + F64_SIG_FULL_BITS)) {
+ effective_significand_size = F64_SIG_FULL_BITS;
+ } else if (order_of_magnitude <= EXP_SUBNORMAL) {
+ effective_significand_size = 0;
+ } else {
+ effective_significand_size = order_of_magnitude - EXP_SUBNORMAL;
+ }
+
+ /* precision digits count */
+ precision_digits_count = DIY_SIG_BITS - effective_significand_size;
+ if (unlikely(precision_digits_count + ERR_ULP_LOG >= DIY_SIG_BITS)) {
+ i32 shr = (precision_digits_count + ERR_ULP_LOG) - DIY_SIG_BITS + 1;
+ fp.sig >>= shr;
+ fp.exp += shr;
+ fp_err = (fp_err >> shr) + 1 + (u32)ERR_ULP;
+ precision_digits_count -= shr;
+ }
+
+ /* half way */
+ precision_bits = fp.sig & (((u64)1 << precision_digits_count) - 1);
+ precision_bits *= (u32)ERR_ULP;
+ half_way = (u64)1 << (precision_digits_count - 1);
+ half_way *= (u32)ERR_ULP;
+
+ /* rounding */
+ fp.sig >>= precision_digits_count;
+ fp.sig += (precision_bits >= half_way + fp_err);
+ fp.exp += precision_digits_count;
+
+ /* get IEEE double raw value */
+ raw = diy_fp_to_ieee_raw(fp);
+ if (unlikely(raw == F64_RAW_INF)) return_inf();
+ if (likely(precision_bits <= half_way - fp_err ||
+ precision_bits >= half_way + fp_err)) {
+ return_f64_bin(raw); /* number is accurate */
+ }
+ /* now the number is the correct value, or the next lower value */
+
+ /* upper boundary */
+ if (raw & F64_EXP_MASK) {
+ fp_upper.sig = (raw & F64_SIG_MASK) + ((u64)1 << F64_SIG_BITS);
+ fp_upper.exp = (i32)((raw & F64_EXP_MASK) >> F64_SIG_BITS);
+ } else {
+ fp_upper.sig = (raw & F64_SIG_MASK);
+ fp_upper.exp = 1;
+ }
+ fp_upper.exp -= F64_EXP_BIAS + F64_SIG_BITS;
+ fp_upper.sig <<= 1;
+ fp_upper.exp -= 1;
+ fp_upper.sig += 1; /* add half ulp */
+
+ /* compare with bigint */
+ bigint_set_buf(&big_full, sig, &exp, sig_cut, sig_end, dot_pos);
+ bigint_set_u64(&big_comp, fp_upper.sig);
+ if (exp >= 0) {
+ bigint_mul_pow10(&big_full, +exp);
+ } else {
+ bigint_mul_pow10(&big_comp, -exp);
+ }
+ if (fp_upper.exp > 0) {
+ bigint_mul_pow2(&big_comp, (u32)+fp_upper.exp);
+ } else {
+ bigint_mul_pow2(&big_full, (u32)-fp_upper.exp);
+ }
+ cmp = bigint_cmp(&big_full, &big_comp);
+ if (likely(cmp != 0)) {
+ /* round down or round up */
+ raw += (cmp > 0);
+ } else {
+ /* falls midway, round to even */
+ raw += (raw & 1);
+ }
+
+ if (unlikely(raw == F64_RAW_INF)) return_inf();
+ return_f64_bin(raw);
+ }
+
+#undef return_err
+#undef return_inf
+#undef return_0
+#undef return_i64
+#undef return_f64
+#undef return_f64_bin
+#undef return_raw
+}
+
+
+
+#else /* FP_READER */
+
+/**
+ Read a JSON number.
+ This is a fallback function if the custom number reader is disabled.
+ This function use libc's strtod() to read floating-point number.
+ */
+static_inline bool read_number(u8 **ptr,
+ u8 **pre,
+ yyjson_read_flag flg,
+ yyjson_val *val,
+ const char **msg) {
+
+#define return_err(_pos, _msg) do { \
+ *msg = _msg; \
+ *end = _pos; \
+ return false; \
+} while (false)
+
+#define return_0() do { \
+ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \
+ val->uni.u64 = 0; \
+ *end = cur; return true; \
+} while (false)
+
+#define return_i64(_v) do { \
+ val->tag = YYJSON_TYPE_NUM | (u64)((u8)sign << 3); \
+ val->uni.u64 = (u64)(sign ? (u64)(~(_v) + 1) : (u64)(_v)); \
+ *end = cur; return true; \
+} while (false)
+
+#define return_f64(_v) do { \
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \
+ val->uni.f64 = sign ? -(f64)(_v) : (f64)(_v); \
+ *end = cur; return true; \
+} while (false)
+
+#define return_f64_bin(_v) do { \
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL; \
+ val->uni.u64 = ((u64)sign << 63) | (u64)(_v); \
+ *end = cur; return true; \
+} while (false)
+
+#define return_inf() do { \
+ if (has_read_flag(BIGNUM_AS_RAW)) return_raw(); \
+ if (has_read_flag(ALLOW_INF_AND_NAN)) return_f64_bin(F64_RAW_INF); \
+ else return_err(hdr, "number is infinity when parsed as double"); \
+} while (false)
+
+#define return_raw() do { \
+ if (*pre) **pre = '\0'; /* add null-terminator for previous raw string */ \
+ val->tag = ((u64)(cur - hdr) << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW; \
+ val->uni.str = (const char *)hdr; \
+ *pre = cur; *end = cur; return true; \
+} while (false)
+
+ u64 sig, num;
+ u8 *hdr = *ptr;
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ u8 *dot = NULL;
+ u8 *f64_end = NULL;
+ bool sign;
+
+ /* read number as raw string if has `YYJSON_READ_NUMBER_AS_RAW` flag */
+ if (has_read_flag(NUMBER_AS_RAW)) {
+ return read_number_raw(ptr, pre, flg, val, msg);
+ }
+
+ sign = (*hdr == '-');
+ cur += sign;
+ sig = (u8)(*cur - '0');
+
+ /* read first digit, check leading zero */
+ if (unlikely(!digi_is_digit(*cur))) {
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_inf_or_nan(sign, &cur, pre, val)) {
+ *end = cur;
+ return true;
+ }
+ }
+ return_err(cur, "no digit after minus sign");
+ }
+ if (*cur == '0') {
+ cur++;
+ if (unlikely(digi_is_digit(*cur))) {
+ return_err(cur - 1, "number with leading zero is not allowed");
+ }
+ if (!digi_is_fp(*cur)) return_0();
+ goto read_double;
+ }
+
+ /* read continuous digits, up to 19 characters */
+#define expr_intg(i) \
+ if (likely((num = (u64)(cur[i] - (u8)'0')) <= 9)) sig = num + sig * 10; \
+ else { cur += i; goto intg_end; }
+ repeat_in_1_18(expr_intg)
+#undef expr_intg
+
+ /* here are 19 continuous digits, skip them */
+ cur += 19;
+ if (digi_is_digit(cur[0]) && !digi_is_digit_or_fp(cur[1])) {
+ /* this number is an integer consisting of 20 digits */
+ num = (u8)(*cur - '0');
+ if ((sig < (U64_MAX / 10)) ||
+ (sig == (U64_MAX / 10) && num <= (U64_MAX % 10))) {
+ sig = num + sig * 10;
+ cur++;
+ if (sign) {
+ if (has_read_flag(BIGNUM_AS_RAW)) return_raw();
+ return_f64(normalized_u64_to_f64(sig));
+ }
+ return_i64(sig);
+ }
+ }
+
+intg_end:
+ /* continuous digits ended */
+ if (!digi_is_digit_or_fp(*cur)) {
+ /* this number is an integer consisting of 1 to 19 digits */
+ if (sign && (sig > ((u64)1 << 63))) {
+ if (has_read_flag(BIGNUM_AS_RAW)) return_raw();
+ return_f64(normalized_u64_to_f64(sig));
+ }
+ return_i64(sig);
+ }
+
+read_double:
+ /* this number should be read as double */
+ while (digi_is_digit(*cur)) cur++;
+ if (!digi_is_fp(*cur) && has_read_flag(BIGNUM_AS_RAW)) {
+ return_raw(); /* it's a large integer */
+ }
+ if (*cur == '.') {
+ /* skip fraction part */
+ dot = cur;
+ cur++;
+ if (!digi_is_digit(*cur)) {
+ return_err(cur, "no digit after decimal point");
+ }
+ cur++;
+ while (digi_is_digit(*cur)) cur++;
+ }
+ if (digi_is_exp(*cur)) {
+ /* skip exponent part */
+ cur += 1 + digi_is_sign(cur[1]);
+ if (!digi_is_digit(*cur)) {
+ return_err(cur, "no digit after exponent sign");
+ }
+ cur++;
+ while (digi_is_digit(*cur)) cur++;
+ }
+
+ /*
+ libc's strtod() is used to parse the floating-point number.
+
+ Note that the decimal point character used by strtod() is locale-dependent,
+ and the rounding direction may affected by fesetround().
+
+ For currently known locales, (en, zh, ja, ko, am, he, hi) use '.' as the
+ decimal point, while other locales use ',' as the decimal point.
+
+ Here strtod() is called twice for different locales, but if another thread
+ happens calls setlocale() between two strtod(), parsing may still fail.
+ */
+ val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end);
+ if (unlikely(f64_end != cur)) {
+ /* replace '.' with ',' for locale */
+ bool cut = (*cur == ',');
+ if (cut) *cur = ' ';
+ if (dot) *dot = ',';
+ val->uni.f64 = strtod((const char *)hdr, (char **)&f64_end);
+ /* restore ',' to '.' */
+ if (cut) *cur = ',';
+ if (dot) *dot = '.';
+ if (unlikely(f64_end != cur)) {
+ return_err(hdr, "strtod() failed to parse the number");
+ }
+ }
+ if (unlikely(val->uni.f64 >= HUGE_VAL || val->uni.f64 <= -HUGE_VAL)) {
+ return_inf();
+ }
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ *end = cur;
+ return true;
+
+#undef return_err
+#undef return_0
+#undef return_i64
+#undef return_f64
+#undef return_f64_bin
+#undef return_inf
+#undef return_raw
+}
+
+#endif /* FP_READER */
+
+
+
+/*==============================================================================
+ * JSON String Reader
+ *============================================================================*/
+
+/**
+ Read a JSON string.
+ @param ptr The head pointer of string before '"' prefix (inout).
+ @param lst JSON last position.
+ @param inv Allow invalid unicode.
+ @param val The string value to be written.
+ @param msg The error message pointer.
+ @return Whether success.
+ */
+static_inline bool read_string(u8 **ptr,
+ u8 *lst,
+ bool inv,
+ yyjson_val *val,
+ const char **msg) {
+ /*
+ Each unicode code point is encoded as 1 to 4 bytes in UTF-8 encoding,
+ we use 4-byte mask and pattern value to validate UTF-8 byte sequence,
+ this requires the input data to have 4-byte zero padding.
+ ---------------------------------------------------
+ 1 byte
+ unicode range [U+0000, U+007F]
+ unicode min [.......0]
+ unicode max [.1111111]
+ bit pattern [0.......]
+ ---------------------------------------------------
+ 2 byte
+ unicode range [U+0080, U+07FF]
+ unicode min [......10 ..000000]
+ unicode max [...11111 ..111111]
+ bit require [...xxxx. ........] (1E 00)
+ bit mask [xxx..... xx......] (E0 C0)
+ bit pattern [110..... 10......] (C0 80)
+ ---------------------------------------------------
+ 3 byte
+ unicode range [U+0800, U+FFFF]
+ unicode min [........ ..100000 ..000000]
+ unicode max [....1111 ..111111 ..111111]
+ bit require [....xxxx ..x..... ........] (0F 20 00)
+ bit mask [xxxx.... xx...... xx......] (F0 C0 C0)
+ bit pattern [1110.... 10...... 10......] (E0 80 80)
+ ---------------------------------------------------
+ 3 byte invalid (reserved for surrogate halves)
+ unicode range [U+D800, U+DFFF]
+ unicode min [....1101 ..100000 ..000000]
+ unicode max [....1101 ..111111 ..111111]
+ bit mask [....xxxx ..x..... ........] (0F 20 00)
+ bit pattern [....1101 ..1..... ........] (0D 20 00)
+ ---------------------------------------------------
+ 4 byte
+ unicode range [U+10000, U+10FFFF]
+ unicode min [........ ...10000 ..000000 ..000000]
+ unicode max [.....100 ..001111 ..111111 ..111111]
+ bit require [.....xxx ..xx.... ........ ........] (07 30 00 00)
+ bit mask [xxxxx... xx...... xx...... xx......] (F8 C0 C0 C0)
+ bit pattern [11110... 10...... 10...... 10......] (F0 80 80 80)
+ ---------------------------------------------------
+ */
+#if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN
+ const u32 b1_mask = 0x80000000UL;
+ const u32 b1_patt = 0x00000000UL;
+ const u32 b2_mask = 0xE0C00000UL;
+ const u32 b2_patt = 0xC0800000UL;
+ const u32 b2_requ = 0x1E000000UL;
+ const u32 b3_mask = 0xF0C0C000UL;
+ const u32 b3_patt = 0xE0808000UL;
+ const u32 b3_requ = 0x0F200000UL;
+ const u32 b3_erro = 0x0D200000UL;
+ const u32 b4_mask = 0xF8C0C0C0UL;
+ const u32 b4_patt = 0xF0808080UL;
+ const u32 b4_requ = 0x07300000UL;
+ const u32 b4_err0 = 0x04000000UL;
+ const u32 b4_err1 = 0x03300000UL;
+#elif YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN
+ const u32 b1_mask = 0x00000080UL;
+ const u32 b1_patt = 0x00000000UL;
+ const u32 b2_mask = 0x0000C0E0UL;
+ const u32 b2_patt = 0x000080C0UL;
+ const u32 b2_requ = 0x0000001EUL;
+ const u32 b3_mask = 0x00C0C0F0UL;
+ const u32 b3_patt = 0x008080E0UL;
+ const u32 b3_requ = 0x0000200FUL;
+ const u32 b3_erro = 0x0000200DUL;
+ const u32 b4_mask = 0xC0C0C0F8UL;
+ const u32 b4_patt = 0x808080F0UL;
+ const u32 b4_requ = 0x00003007UL;
+ const u32 b4_err0 = 0x00000004UL;
+ const u32 b4_err1 = 0x00003003UL;
+#else
+ /* this should be evaluated at compile-time */
+ v32_uni b1_mask_uni = {{ 0x80, 0x00, 0x00, 0x00 }};
+ v32_uni b1_patt_uni = {{ 0x00, 0x00, 0x00, 0x00 }};
+ v32_uni b2_mask_uni = {{ 0xE0, 0xC0, 0x00, 0x00 }};
+ v32_uni b2_patt_uni = {{ 0xC0, 0x80, 0x00, 0x00 }};
+ v32_uni b2_requ_uni = {{ 0x1E, 0x00, 0x00, 0x00 }};
+ v32_uni b3_mask_uni = {{ 0xF0, 0xC0, 0xC0, 0x00 }};
+ v32_uni b3_patt_uni = {{ 0xE0, 0x80, 0x80, 0x00 }};
+ v32_uni b3_requ_uni = {{ 0x0F, 0x20, 0x00, 0x00 }};
+ v32_uni b3_erro_uni = {{ 0x0D, 0x20, 0x00, 0x00 }};
+ v32_uni b4_mask_uni = {{ 0xF8, 0xC0, 0xC0, 0xC0 }};
+ v32_uni b4_patt_uni = {{ 0xF0, 0x80, 0x80, 0x80 }};
+ v32_uni b4_requ_uni = {{ 0x07, 0x30, 0x00, 0x00 }};
+ v32_uni b4_err0_uni = {{ 0x04, 0x00, 0x00, 0x00 }};
+ v32_uni b4_err1_uni = {{ 0x03, 0x30, 0x00, 0x00 }};
+ u32 b1_mask = b1_mask_uni.u;
+ u32 b1_patt = b1_patt_uni.u;
+ u32 b2_mask = b2_mask_uni.u;
+ u32 b2_patt = b2_patt_uni.u;
+ u32 b2_requ = b2_requ_uni.u;
+ u32 b3_mask = b3_mask_uni.u;
+ u32 b3_patt = b3_patt_uni.u;
+ u32 b3_requ = b3_requ_uni.u;
+ u32 b3_erro = b3_erro_uni.u;
+ u32 b4_mask = b4_mask_uni.u;
+ u32 b4_patt = b4_patt_uni.u;
+ u32 b4_requ = b4_requ_uni.u;
+ u32 b4_err0 = b4_err0_uni.u;
+ u32 b4_err1 = b4_err1_uni.u;
+#endif
+
+#define is_valid_seq_1(uni) ( \
+ ((uni & b1_mask) == b1_patt) \
+)
+
+#define is_valid_seq_2(uni) ( \
+ ((uni & b2_mask) == b2_patt) && \
+ ((uni & b2_requ)) \
+)
+
+#define is_valid_seq_3(uni) ( \
+ ((uni & b3_mask) == b3_patt) && \
+ ((tmp = (uni & b3_requ))) && \
+ ((tmp != b3_erro)) \
+)
+
+#define is_valid_seq_4(uni) ( \
+ ((uni & b4_mask) == b4_patt) && \
+ ((tmp = (uni & b4_requ))) && \
+ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \
+)
+
+#define return_err(_end, _msg) do { \
+ *msg = _msg; \
+ *end = _end; \
+ return false; \
+} while (false)
+
+ u8 *cur = *ptr;
+ u8 **end = ptr;
+ u8 *src = ++cur, *dst, *pos;
+ u16 hi, lo;
+ u32 uni, tmp;
+
+skip_ascii:
+ /* Most strings have no escaped characters, so we can jump them quickly. */
+
+skip_ascii_begin:
+ /*
+ We want to make loop unrolling, as shown in the following code. Some
+ compiler may not generate instructions as expected, so we rewrite it with
+ explicit goto statements. We hope the compiler can generate instructions
+ like this: https://godbolt.org/z/8vjsYq
+
+ while (true) repeat16({
+ if (likely(!(char_is_ascii_stop(*src)))) src++;
+ else break;
+ })
+ */
+#define expr_jump(i) \
+ if (likely(!char_is_ascii_stop(src[i]))) {} \
+ else goto skip_ascii_stop##i;
+
+#define expr_stop(i) \
+ skip_ascii_stop##i: \
+ src += i; \
+ goto skip_ascii_end;
+
+ repeat16_incr(expr_jump)
+ src += 16;
+ goto skip_ascii_begin;
+ repeat16_incr(expr_stop)
+
+#undef expr_jump
+#undef expr_stop
+
+skip_ascii_end:
+
+ /*
+ GCC may store src[i] in a register at each line of expr_jump(i) above.
+ These instructions are useless and will degrade performance.
+ This inline asm is a hint for gcc: "the memory has been modified,
+ do not cache it".
+
+ MSVC, Clang, ICC can generate expected instructions without this hint.
+ */
+#if YYJSON_IS_REAL_GCC
+ __asm__ volatile("":"=m"(*src));
+#endif
+ if (likely(*src == '"')) {
+ val->tag = ((u64)(src - cur) << YYJSON_TAG_BIT) |
+ (u64)(YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC);
+ val->uni.str = (const char *)cur;
+ *src = '\0';
+ *end = src + 1;
+ return true;
+ }
+
+skip_utf8:
+ if (*src & 0x80) { /* non-ASCII character */
+ /*
+ Non-ASCII character appears here, which means that the text is likely
+ to be written in non-English or emoticons. According to some common
+ data set statistics, byte sequences of the same length may appear
+ consecutively. We process the byte sequences of the same length in each
+ loop, which is more friendly to branch prediction.
+ */
+ pos = src;
+#if YYJSON_DISABLE_UTF8_VALIDATION
+ while (true) repeat8({
+ if (likely((*src & 0xF0) == 0xE0)) src += 3;
+ else break;
+ })
+ if (*src < 0x80) goto skip_ascii;
+ while (true) repeat8({
+ if (likely((*src & 0xE0) == 0xC0)) src += 2;
+ else break;
+ })
+ while (true) repeat8({
+ if (likely((*src & 0xF8) == 0xF0)) src += 4;
+ else break;
+ })
+#else
+ uni = byte_load_4(src);
+ while (is_valid_seq_3(uni)) {
+ src += 3;
+ uni = byte_load_4(src);
+ }
+ if (is_valid_seq_1(uni)) goto skip_ascii;
+ while (is_valid_seq_2(uni)) {
+ src += 2;
+ uni = byte_load_4(src);
+ }
+ while (is_valid_seq_4(uni)) {
+ src += 4;
+ uni = byte_load_4(src);
+ }
+#endif
+ if (unlikely(pos == src)) {
+ if (!inv) return_err(src, "invalid UTF-8 encoding in string");
+ ++src;
+ }
+ goto skip_ascii;
+ }
+
+ /* The escape character appears, we need to copy it. */
+ dst = src;
+copy_escape:
+ if (likely(*src == '\\')) {
+ switch (*++src) {
+ case '"': *dst++ = '"'; src++; break;
+ case '\\': *dst++ = '\\'; src++; break;
+ case '/': *dst++ = '/'; src++; break;
+ case 'b': *dst++ = '\b'; src++; break;
+ case 'f': *dst++ = '\f'; src++; break;
+ case 'n': *dst++ = '\n'; src++; break;
+ case 'r': *dst++ = '\r'; src++; break;
+ case 't': *dst++ = '\t'; src++; break;
+ case 'u':
+ if (unlikely(!read_hex_u16(++src, &hi))) {
+ return_err(src - 2, "invalid escaped sequence in string");
+ }
+ src += 4;
+ if (likely((hi & 0xF800) != 0xD800)) {
+ /* a BMP character */
+ if (hi >= 0x800) {
+ *dst++ = (u8)(0xE0 | (hi >> 12));
+ *dst++ = (u8)(0x80 | ((hi >> 6) & 0x3F));
+ *dst++ = (u8)(0x80 | (hi & 0x3F));
+ } else if (hi >= 0x80) {
+ *dst++ = (u8)(0xC0 | (hi >> 6));
+ *dst++ = (u8)(0x80 | (hi & 0x3F));
+ } else {
+ *dst++ = (u8)hi;
+ }
+ } else {
+ /* a non-BMP character, represented as a surrogate pair */
+ if (unlikely((hi & 0xFC00) != 0xD800)) {
+ return_err(src - 6, "invalid high surrogate in string");
+ }
+ if (unlikely(!byte_match_2(src, "\\u"))) {
+ return_err(src, "no low surrogate in string");
+ }
+ if (unlikely(!read_hex_u16(src + 2, &lo))) {
+ return_err(src, "invalid escaped sequence in string");
+ }
+ if (unlikely((lo & 0xFC00) != 0xDC00)) {
+ return_err(src, "invalid low surrogate in string");
+ }
+ uni = ((((u32)hi - 0xD800) << 10) |
+ ((u32)lo - 0xDC00)) + 0x10000;
+ *dst++ = (u8)(0xF0 | (uni >> 18));
+ *dst++ = (u8)(0x80 | ((uni >> 12) & 0x3F));
+ *dst++ = (u8)(0x80 | ((uni >> 6) & 0x3F));
+ *dst++ = (u8)(0x80 | (uni & 0x3F));
+ src += 6;
+ }
+ break;
+ default: return_err(src, "invalid escaped character in string");
+ }
+ } else if (likely(*src == '"')) {
+ val->tag = ((u64)(dst - cur) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = (const char *)cur;
+ *dst = '\0';
+ *end = src + 1;
+ return true;
+ } else {
+ if (!inv) return_err(src, "unexpected control character in string");
+ if (src >= lst) return_err(src, "unclosed string");
+ *dst++ = *src++;
+ }
+
+copy_ascii:
+ /*
+ Copy continuous ASCII, loop unrolling, same as the following code:
+
+ while (true) repeat16({
+ if (unlikely(char_is_ascii_stop(*src))) break;
+ *dst++ = *src++;
+ })
+ */
+#if YYJSON_IS_REAL_GCC
+# define expr_jump(i) \
+ if (likely(!(char_is_ascii_stop(src[i])))) {} \
+ else { __asm__ volatile("":"=m"(src[i])); goto copy_ascii_stop_##i; }
+#else
+# define expr_jump(i) \
+ if (likely(!(char_is_ascii_stop(src[i])))) {} \
+ else { goto copy_ascii_stop_##i; }
+#endif
+ repeat16_incr(expr_jump)
+#undef expr_jump
+
+ byte_move_16(dst, src);
+ src += 16;
+ dst += 16;
+ goto copy_ascii;
+
+ /*
+ The memory will be moved forward by at least 1 byte. So the `byte_move`
+ can be one byte more than needed to reduce the number of instructions.
+ */
+copy_ascii_stop_0:
+ goto copy_utf8;
+copy_ascii_stop_1:
+ byte_move_2(dst, src);
+ src += 1;
+ dst += 1;
+ goto copy_utf8;
+copy_ascii_stop_2:
+ byte_move_2(dst, src);
+ src += 2;
+ dst += 2;
+ goto copy_utf8;
+copy_ascii_stop_3:
+ byte_move_4(dst, src);
+ src += 3;
+ dst += 3;
+ goto copy_utf8;
+copy_ascii_stop_4:
+ byte_move_4(dst, src);
+ src += 4;
+ dst += 4;
+ goto copy_utf8;
+copy_ascii_stop_5:
+ byte_move_4(dst, src);
+ byte_move_2(dst + 4, src + 4);
+ src += 5;
+ dst += 5;
+ goto copy_utf8;
+copy_ascii_stop_6:
+ byte_move_4(dst, src);
+ byte_move_2(dst + 4, src + 4);
+ src += 6;
+ dst += 6;
+ goto copy_utf8;
+copy_ascii_stop_7:
+ byte_move_8(dst, src);
+ src += 7;
+ dst += 7;
+ goto copy_utf8;
+copy_ascii_stop_8:
+ byte_move_8(dst, src);
+ src += 8;
+ dst += 8;
+ goto copy_utf8;
+copy_ascii_stop_9:
+ byte_move_8(dst, src);
+ byte_move_2(dst + 8, src + 8);
+ src += 9;
+ dst += 9;
+ goto copy_utf8;
+copy_ascii_stop_10:
+ byte_move_8(dst, src);
+ byte_move_2(dst + 8, src + 8);
+ src += 10;
+ dst += 10;
+ goto copy_utf8;
+copy_ascii_stop_11:
+ byte_move_8(dst, src);
+ byte_move_4(dst + 8, src + 8);
+ src += 11;
+ dst += 11;
+ goto copy_utf8;
+copy_ascii_stop_12:
+ byte_move_8(dst, src);
+ byte_move_4(dst + 8, src + 8);
+ src += 12;
+ dst += 12;
+ goto copy_utf8;
+copy_ascii_stop_13:
+ byte_move_8(dst, src);
+ byte_move_4(dst + 8, src + 8);
+ byte_move_2(dst + 12, src + 12);
+ src += 13;
+ dst += 13;
+ goto copy_utf8;
+copy_ascii_stop_14:
+ byte_move_8(dst, src);
+ byte_move_4(dst + 8, src + 8);
+ byte_move_2(dst + 12, src + 12);
+ src += 14;
+ dst += 14;
+ goto copy_utf8;
+copy_ascii_stop_15:
+ byte_move_16(dst, src);
+ src += 15;
+ dst += 15;
+ goto copy_utf8;
+
+copy_utf8:
+ if (*src & 0x80) { /* non-ASCII character */
+ pos = src;
+ uni = byte_load_4(src);
+#if YYJSON_DISABLE_UTF8_VALIDATION
+ while (true) repeat4({
+ if ((uni & b3_mask) == b3_patt) {
+ byte_copy_4(dst, &uni);
+ dst += 3;
+ src += 3;
+ uni = byte_load_4(src);
+ } else break;
+ })
+ if ((uni & b1_mask) == b1_patt) goto copy_ascii;
+ while (true) repeat4({
+ if ((uni & b2_mask) == b2_patt) {
+ byte_copy_2(dst, &uni);
+ dst += 2;
+ src += 2;
+ uni = byte_load_4(src);
+ } else break;
+ })
+ while (true) repeat4({
+ if ((uni & b4_mask) == b4_patt) {
+ byte_copy_4(dst, &uni);
+ dst += 4;
+ src += 4;
+ uni = byte_load_4(src);
+ } else break;
+ })
+#else
+ while (is_valid_seq_3(uni)) {
+ byte_copy_4(dst, &uni);
+ dst += 3;
+ src += 3;
+ uni = byte_load_4(src);
+ }
+ if (is_valid_seq_1(uni)) goto copy_ascii;
+ while (is_valid_seq_2(uni)) {
+ byte_copy_2(dst, &uni);
+ dst += 2;
+ src += 2;
+ uni = byte_load_4(src);
+ }
+ while (is_valid_seq_4(uni)) {
+ byte_copy_4(dst, &uni);
+ dst += 4;
+ src += 4;
+ uni = byte_load_4(src);
+ }
+#endif
+ if (unlikely(pos == src)) {
+ if (!inv) return_err(src, "invalid UTF-8 encoding in string");
+ goto copy_ascii_stop_1;
+ }
+ goto copy_ascii;
+ }
+ goto copy_escape;
+
+#undef return_err
+#undef is_valid_seq_1
+#undef is_valid_seq_2
+#undef is_valid_seq_3
+#undef is_valid_seq_4
+}
+
+
+
+/*==============================================================================
+ * JSON Reader Implementation
+ *
+ * We use goto statements to build the finite state machine (FSM).
+ * The FSM's state was held by program counter (PC) and the 'goto' make the
+ * state transitions.
+ *============================================================================*/
+
+/** Read single value JSON document. */
+static_noinline yyjson_doc *read_root_single(u8 *hdr,
+ u8 *cur,
+ u8 *end,
+ yyjson_alc alc,
+ yyjson_read_flag flg,
+ yyjson_read_err *err) {
+
+#define return_err(_pos, _code, _msg) do { \
+ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \
+ err->pos = (usize)(end - hdr); \
+ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \
+ err->msg = "unexpected end of data"; \
+ } else { \
+ err->pos = (usize)(_pos - hdr); \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ err->msg = _msg; \
+ } \
+ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \
+ return NULL; \
+} while (false)
+
+ usize hdr_len; /* value count used by doc */
+ usize alc_num; /* value count capacity */
+ yyjson_val *val_hdr; /* the head of allocated values */
+ yyjson_val *val; /* current value */
+ yyjson_doc *doc; /* the JSON document, equals to val_hdr */
+ const char *msg; /* error message */
+
+ bool raw; /* read number as raw */
+ bool inv; /* allow invalid unicode */
+ u8 *raw_end; /* raw end for null-terminator */
+ u8 **pre; /* previous raw end pointer */
+
+ hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val);
+ hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0;
+ alc_num = hdr_len + 1; /* single value */
+
+ val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_num * sizeof(yyjson_val));
+ if (unlikely(!val_hdr)) goto fail_alloc;
+ val = val_hdr + hdr_len;
+ raw = has_read_flag(NUMBER_AS_RAW) || has_read_flag(BIGNUM_AS_RAW);
+ inv = has_read_flag(ALLOW_INVALID_UNICODE) != 0;
+ raw_end = NULL;
+ pre = raw ? &raw_end : NULL;
+
+ if (char_is_number(*cur)) {
+ if (likely(read_number(&cur, pre, flg, val, &msg))) goto doc_end;
+ goto fail_number;
+ }
+ if (*cur == '"') {
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto doc_end;
+ goto fail_string;
+ }
+ if (*cur == 't') {
+ if (likely(read_true(&cur, val))) goto doc_end;
+ goto fail_literal_true;
+ }
+ if (*cur == 'f') {
+ if (likely(read_false(&cur, val))) goto doc_end;
+ goto fail_literal_false;
+ }
+ if (*cur == 'n') {
+ if (likely(read_null(&cur, val))) goto doc_end;
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_nan(false, &cur, pre, val)) goto doc_end;
+ }
+ goto fail_literal_null;
+ }
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_inf_or_nan(false, &cur, pre, val)) goto doc_end;
+ }
+ goto fail_character;
+
+doc_end:
+ /* check invalid contents after json document */
+ if (unlikely(cur < end) && !has_read_flag(STOP_WHEN_DONE)) {
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (!skip_spaces_and_comments(&cur)) {
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ } else {
+ while (char_is_space(*cur)) cur++;
+ }
+ if (unlikely(cur < end)) goto fail_garbage;
+ }
+
+ if (pre && *pre) **pre = '\0';
+ doc = (yyjson_doc *)val_hdr;
+ doc->root = val_hdr + hdr_len;
+ doc->alc = alc;
+ doc->dat_read = (usize)(cur - hdr);
+ doc->val_read = 1;
+ doc->str_pool = has_read_flag(INSITU) ? NULL : (char *)hdr;
+ return doc;
+
+fail_string:
+ return_err(cur, INVALID_STRING, msg);
+fail_number:
+ return_err(cur, INVALID_NUMBER, msg);
+fail_alloc:
+ return_err(cur, MEMORY_ALLOCATION,
+ "memory allocation failed");
+fail_literal_true:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'true'");
+fail_literal_false:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'false'");
+fail_literal_null:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'null'");
+fail_character:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a valid root value");
+fail_comment:
+ return_err(cur, INVALID_COMMENT,
+ "unclosed multiline comment");
+fail_garbage:
+ return_err(cur, UNEXPECTED_CONTENT,
+ "unexpected content after document");
+
+#undef return_err
+}
+
+/** Read JSON document (accept all style, but optimized for minify). */
+static_inline yyjson_doc *read_root_minify(u8 *hdr,
+ u8 *cur,
+ u8 *end,
+ yyjson_alc alc,
+ yyjson_read_flag flg,
+ yyjson_read_err *err) {
+
+#define return_err(_pos, _code, _msg) do { \
+ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \
+ err->pos = (usize)(end - hdr); \
+ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \
+ err->msg = "unexpected end of data"; \
+ } else { \
+ err->pos = (usize)(_pos - hdr); \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ err->msg = _msg; \
+ } \
+ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \
+ return NULL; \
+} while (false)
+
+#define val_incr() do { \
+ val++; \
+ if (unlikely(val >= val_end)) { \
+ usize alc_old = alc_len; \
+ alc_len += alc_len / 2; \
+ if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \
+ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \
+ alc_old * sizeof(yyjson_val), \
+ alc_len * sizeof(yyjson_val)); \
+ if ((!val_tmp)) goto fail_alloc; \
+ val = val_tmp + (usize)(val - val_hdr); \
+ ctn = val_tmp + (usize)(ctn - val_hdr); \
+ val_hdr = val_tmp; \
+ val_end = val_tmp + (alc_len - 2); \
+ } \
+} while (false)
+
+ usize dat_len; /* data length in bytes, hint for allocator */
+ usize hdr_len; /* value count used by yyjson_doc */
+ usize alc_len; /* value count allocated */
+ usize alc_max; /* maximum value count for allocator */
+ usize ctn_len; /* the number of elements in current container */
+ yyjson_val *val_hdr; /* the head of allocated values */
+ yyjson_val *val_end; /* the end of allocated values */
+ yyjson_val *val_tmp; /* temporary pointer for realloc */
+ yyjson_val *val; /* current JSON value */
+ yyjson_val *ctn; /* current container */
+ yyjson_val *ctn_parent; /* parent of current container */
+ yyjson_doc *doc; /* the JSON document, equals to val_hdr */
+ const char *msg; /* error message */
+
+ bool raw; /* read number as raw */
+ bool inv; /* allow invalid unicode */
+ u8 *raw_end; /* raw end for null-terminator */
+ u8 **pre; /* previous raw end pointer */
+
+ dat_len = has_read_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur);
+ hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val);
+ hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0;
+ alc_max = USIZE_MAX / sizeof(yyjson_val);
+ alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_MINIFY_RATIO) + 4;
+ alc_len = yyjson_min(alc_len, alc_max);
+
+ val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val));
+ if (unlikely(!val_hdr)) goto fail_alloc;
+ val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */
+ val = val_hdr + hdr_len;
+ ctn = val;
+ ctn_len = 0;
+ raw = has_read_flag(NUMBER_AS_RAW) || has_read_flag(BIGNUM_AS_RAW);
+ inv = has_read_flag(ALLOW_INVALID_UNICODE) != 0;
+ raw_end = NULL;
+ pre = raw ? &raw_end : NULL;
+
+ if (*cur++ == '{') {
+ ctn->tag = YYJSON_TYPE_OBJ;
+ ctn->uni.ofs = 0;
+ goto obj_key_begin;
+ } else {
+ ctn->tag = YYJSON_TYPE_ARR;
+ ctn->uni.ofs = 0;
+ goto arr_val_begin;
+ }
+
+arr_begin:
+ /* save current container */
+ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) |
+ (ctn->tag & YYJSON_TAG_MASK);
+
+ /* create a new array value, save parent container offset */
+ val_incr();
+ val->tag = YYJSON_TYPE_ARR;
+ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn);
+
+ /* push the new array value as current container */
+ ctn = val;
+ ctn_len = 0;
+
+arr_val_begin:
+ if (*cur == '{') {
+ cur++;
+ goto obj_begin;
+ }
+ if (*cur == '[') {
+ cur++;
+ goto arr_begin;
+ }
+ if (char_is_number(*cur)) {
+ val_incr();
+ ctn_len++;
+ if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end;
+ goto fail_number;
+ }
+ if (*cur == '"') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto arr_val_end;
+ goto fail_string;
+ }
+ if (*cur == 't') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_true(&cur, val))) goto arr_val_end;
+ goto fail_literal_true;
+ }
+ if (*cur == 'f') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_false(&cur, val))) goto arr_val_end;
+ goto fail_literal_false;
+ }
+ if (*cur == 'n') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_null(&cur, val))) goto arr_val_end;
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_nan(false, &cur, pre, val)) goto arr_val_end;
+ }
+ goto fail_literal_null;
+ }
+ if (*cur == ']') {
+ cur++;
+ if (likely(ctn_len == 0)) goto arr_end;
+ if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto arr_end;
+ while (*cur != ',') cur--;
+ goto fail_trailing_comma;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto arr_val_begin;
+ }
+ if (has_read_flag(ALLOW_INF_AND_NAN) &&
+ (*cur == 'i' || *cur == 'I' || *cur == 'N')) {
+ val_incr();
+ ctn_len++;
+ if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end;
+ goto fail_character_val;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto arr_val_begin;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_val;
+
+arr_val_end:
+ if (*cur == ',') {
+ cur++;
+ goto arr_val_begin;
+ }
+ if (*cur == ']') {
+ cur++;
+ goto arr_end;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto arr_val_end;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto arr_val_end;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_arr_end;
+
+arr_end:
+ /* get parent container */
+ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs);
+
+ /* save the next sibling value offset */
+ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val);
+ ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR;
+ if (unlikely(ctn == ctn_parent)) goto doc_end;
+
+ /* pop parent as current container */
+ ctn = ctn_parent;
+ ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT);
+ if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) {
+ goto obj_val_end;
+ } else {
+ goto arr_val_end;
+ }
+
+obj_begin:
+ /* push container */
+ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) |
+ (ctn->tag & YYJSON_TAG_MASK);
+ val_incr();
+ val->tag = YYJSON_TYPE_OBJ;
+ /* offset to the parent */
+ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn);
+ ctn = val;
+ ctn_len = 0;
+
+obj_key_begin:
+ if (likely(*cur == '"')) {
+ val_incr();
+ ctn_len++;
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_key_end;
+ goto fail_string;
+ }
+ if (likely(*cur == '}')) {
+ cur++;
+ if (likely(ctn_len == 0)) goto obj_end;
+ if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto obj_end;
+ while (*cur != ',') cur--;
+ goto fail_trailing_comma;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_key_begin;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_key_begin;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_obj_key;
+
+obj_key_end:
+ if (*cur == ':') {
+ cur++;
+ goto obj_val_begin;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_key_end;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_key_end;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_obj_sep;
+
+obj_val_begin:
+ if (*cur == '"') {
+ val++;
+ ctn_len++;
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_val_end;
+ goto fail_string;
+ }
+ if (char_is_number(*cur)) {
+ val++;
+ ctn_len++;
+ if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end;
+ goto fail_number;
+ }
+ if (*cur == '{') {
+ cur++;
+ goto obj_begin;
+ }
+ if (*cur == '[') {
+ cur++;
+ goto arr_begin;
+ }
+ if (*cur == 't') {
+ val++;
+ ctn_len++;
+ if (likely(read_true(&cur, val))) goto obj_val_end;
+ goto fail_literal_true;
+ }
+ if (*cur == 'f') {
+ val++;
+ ctn_len++;
+ if (likely(read_false(&cur, val))) goto obj_val_end;
+ goto fail_literal_false;
+ }
+ if (*cur == 'n') {
+ val++;
+ ctn_len++;
+ if (likely(read_null(&cur, val))) goto obj_val_end;
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_nan(false, &cur, pre, val)) goto obj_val_end;
+ }
+ goto fail_literal_null;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_val_begin;
+ }
+ if (has_read_flag(ALLOW_INF_AND_NAN) &&
+ (*cur == 'i' || *cur == 'I' || *cur == 'N')) {
+ val++;
+ ctn_len++;
+ if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end;
+ goto fail_character_val;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_val_begin;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_val;
+
+obj_val_end:
+ if (likely(*cur == ',')) {
+ cur++;
+ goto obj_key_begin;
+ }
+ if (likely(*cur == '}')) {
+ cur++;
+ goto obj_end;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_val_end;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_val_end;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_obj_end;
+
+obj_end:
+ /* pop container */
+ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs);
+ /* point to the next value */
+ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val);
+ ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ;
+ if (unlikely(ctn == ctn_parent)) goto doc_end;
+ ctn = ctn_parent;
+ ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT);
+ if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) {
+ goto obj_val_end;
+ } else {
+ goto arr_val_end;
+ }
+
+doc_end:
+ /* check invalid contents after json document */
+ if (unlikely(cur < end) && !has_read_flag(STOP_WHEN_DONE)) {
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ skip_spaces_and_comments(&cur);
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ } else {
+ while (char_is_space(*cur)) cur++;
+ }
+ if (unlikely(cur < end)) goto fail_garbage;
+ }
+
+ if (pre && *pre) **pre = '\0';
+ doc = (yyjson_doc *)val_hdr;
+ doc->root = val_hdr + hdr_len;
+ doc->alc = alc;
+ doc->dat_read = (usize)(cur - hdr);
+ doc->val_read = (usize)((val - doc->root) + 1);
+ doc->str_pool = has_read_flag(INSITU) ? NULL : (char *)hdr;
+ return doc;
+
+fail_string:
+ return_err(cur, INVALID_STRING, msg);
+fail_number:
+ return_err(cur, INVALID_NUMBER, msg);
+fail_alloc:
+ return_err(cur, MEMORY_ALLOCATION,
+ "memory allocation failed");
+fail_trailing_comma:
+ return_err(cur, JSON_STRUCTURE,
+ "trailing comma is not allowed");
+fail_literal_true:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'true'");
+fail_literal_false:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'false'");
+fail_literal_null:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'null'");
+fail_character_val:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a valid JSON value");
+fail_character_arr_end:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a comma or a closing bracket");
+fail_character_obj_key:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a string for object key");
+fail_character_obj_sep:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a colon after object key");
+fail_character_obj_end:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a comma or a closing brace");
+fail_comment:
+ return_err(cur, INVALID_COMMENT,
+ "unclosed multiline comment");
+fail_garbage:
+ return_err(cur, UNEXPECTED_CONTENT,
+ "unexpected content after document");
+
+#undef val_incr
+#undef return_err
+}
+
+/** Read JSON document (accept all style, but optimized for pretty). */
+static_inline yyjson_doc *read_root_pretty(u8 *hdr,
+ u8 *cur,
+ u8 *end,
+ yyjson_alc alc,
+ yyjson_read_flag flg,
+ yyjson_read_err *err) {
+
+#define return_err(_pos, _code, _msg) do { \
+ if (is_truncated_end(hdr, _pos, end, YYJSON_READ_ERROR_##_code, flg)) { \
+ err->pos = (usize)(end - hdr); \
+ err->code = YYJSON_READ_ERROR_UNEXPECTED_END; \
+ err->msg = "unexpected end of data"; \
+ } else { \
+ err->pos = (usize)(_pos - hdr); \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ err->msg = _msg; \
+ } \
+ if (val_hdr) alc.free(alc.ctx, (void *)val_hdr); \
+ return NULL; \
+} while (false)
+
+#define val_incr() do { \
+ val++; \
+ if (unlikely(val >= val_end)) { \
+ usize alc_old = alc_len; \
+ alc_len += alc_len / 2; \
+ if ((sizeof(usize) < 8) && (alc_len >= alc_max)) goto fail_alloc; \
+ val_tmp = (yyjson_val *)alc.realloc(alc.ctx, (void *)val_hdr, \
+ alc_old * sizeof(yyjson_val), \
+ alc_len * sizeof(yyjson_val)); \
+ if ((!val_tmp)) goto fail_alloc; \
+ val = val_tmp + (usize)(val - val_hdr); \
+ ctn = val_tmp + (usize)(ctn - val_hdr); \
+ val_hdr = val_tmp; \
+ val_end = val_tmp + (alc_len - 2); \
+ } \
+} while (false)
+
+ usize dat_len; /* data length in bytes, hint for allocator */
+ usize hdr_len; /* value count used by yyjson_doc */
+ usize alc_len; /* value count allocated */
+ usize alc_max; /* maximum value count for allocator */
+ usize ctn_len; /* the number of elements in current container */
+ yyjson_val *val_hdr; /* the head of allocated values */
+ yyjson_val *val_end; /* the end of allocated values */
+ yyjson_val *val_tmp; /* temporary pointer for realloc */
+ yyjson_val *val; /* current JSON value */
+ yyjson_val *ctn; /* current container */
+ yyjson_val *ctn_parent; /* parent of current container */
+ yyjson_doc *doc; /* the JSON document, equals to val_hdr */
+ const char *msg; /* error message */
+
+ bool raw; /* read number as raw */
+ bool inv; /* allow invalid unicode */
+ u8 *raw_end; /* raw end for null-terminator */
+ u8 **pre; /* previous raw end pointer */
+
+ dat_len = has_read_flag(STOP_WHEN_DONE) ? 256 : (usize)(end - cur);
+ hdr_len = sizeof(yyjson_doc) / sizeof(yyjson_val);
+ hdr_len += (sizeof(yyjson_doc) % sizeof(yyjson_val)) > 0;
+ alc_max = USIZE_MAX / sizeof(yyjson_val);
+ alc_len = hdr_len + (dat_len / YYJSON_READER_ESTIMATED_PRETTY_RATIO) + 4;
+ alc_len = yyjson_min(alc_len, alc_max);
+
+ val_hdr = (yyjson_val *)alc.malloc(alc.ctx, alc_len * sizeof(yyjson_val));
+ if (unlikely(!val_hdr)) goto fail_alloc;
+ val_end = val_hdr + (alc_len - 2); /* padding for key-value pair reading */
+ val = val_hdr + hdr_len;
+ ctn = val;
+ ctn_len = 0;
+ raw = has_read_flag(NUMBER_AS_RAW) || has_read_flag(BIGNUM_AS_RAW);
+ inv = has_read_flag(ALLOW_INVALID_UNICODE) != 0;
+ raw_end = NULL;
+ pre = raw ? &raw_end : NULL;
+
+ if (*cur++ == '{') {
+ ctn->tag = YYJSON_TYPE_OBJ;
+ ctn->uni.ofs = 0;
+ if (*cur == '\n') cur++;
+ goto obj_key_begin;
+ } else {
+ ctn->tag = YYJSON_TYPE_ARR;
+ ctn->uni.ofs = 0;
+ if (*cur == '\n') cur++;
+ goto arr_val_begin;
+ }
+
+arr_begin:
+ /* save current container */
+ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) |
+ (ctn->tag & YYJSON_TAG_MASK);
+
+ /* create a new array value, save parent container offset */
+ val_incr();
+ val->tag = YYJSON_TYPE_ARR;
+ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn);
+
+ /* push the new array value as current container */
+ ctn = val;
+ ctn_len = 0;
+ if (*cur == '\n') cur++;
+
+arr_val_begin:
+#if YYJSON_IS_REAL_GCC
+ while (true) repeat16({
+ if (byte_match_2(cur, " ")) cur += 2;
+ else break;
+ })
+#else
+ while (true) repeat16({
+ if (likely(byte_match_2(cur, " "))) cur += 2;
+ else break;
+ })
+#endif
+
+ if (*cur == '{') {
+ cur++;
+ goto obj_begin;
+ }
+ if (*cur == '[') {
+ cur++;
+ goto arr_begin;
+ }
+ if (char_is_number(*cur)) {
+ val_incr();
+ ctn_len++;
+ if (likely(read_number(&cur, pre, flg, val, &msg))) goto arr_val_end;
+ goto fail_number;
+ }
+ if (*cur == '"') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto arr_val_end;
+ goto fail_string;
+ }
+ if (*cur == 't') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_true(&cur, val))) goto arr_val_end;
+ goto fail_literal_true;
+ }
+ if (*cur == 'f') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_false(&cur, val))) goto arr_val_end;
+ goto fail_literal_false;
+ }
+ if (*cur == 'n') {
+ val_incr();
+ ctn_len++;
+ if (likely(read_null(&cur, val))) goto arr_val_end;
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_nan(false, &cur, pre, val)) goto arr_val_end;
+ }
+ goto fail_literal_null;
+ }
+ if (*cur == ']') {
+ cur++;
+ if (likely(ctn_len == 0)) goto arr_end;
+ if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto arr_end;
+ while (*cur != ',') cur--;
+ goto fail_trailing_comma;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto arr_val_begin;
+ }
+ if (has_read_flag(ALLOW_INF_AND_NAN) &&
+ (*cur == 'i' || *cur == 'I' || *cur == 'N')) {
+ val_incr();
+ ctn_len++;
+ if (read_inf_or_nan(false, &cur, pre, val)) goto arr_val_end;
+ goto fail_character_val;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto arr_val_begin;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_val;
+
+arr_val_end:
+ if (byte_match_2(cur, ",\n")) {
+ cur += 2;
+ goto arr_val_begin;
+ }
+ if (*cur == ',') {
+ cur++;
+ goto arr_val_begin;
+ }
+ if (*cur == ']') {
+ cur++;
+ goto arr_end;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto arr_val_end;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto arr_val_end;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_arr_end;
+
+arr_end:
+ /* get parent container */
+ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs);
+
+ /* save the next sibling value offset */
+ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val);
+ ctn->tag = ((ctn_len) << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR;
+ if (unlikely(ctn == ctn_parent)) goto doc_end;
+
+ /* pop parent as current container */
+ ctn = ctn_parent;
+ ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT);
+ if (*cur == '\n') cur++;
+ if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) {
+ goto obj_val_end;
+ } else {
+ goto arr_val_end;
+ }
+
+obj_begin:
+ /* push container */
+ ctn->tag = (((u64)ctn_len + 1) << YYJSON_TAG_BIT) |
+ (ctn->tag & YYJSON_TAG_MASK);
+ val_incr();
+ val->tag = YYJSON_TYPE_OBJ;
+ /* offset to the parent */
+ val->uni.ofs = (usize)((u8 *)val - (u8 *)ctn);
+ ctn = val;
+ ctn_len = 0;
+ if (*cur == '\n') cur++;
+
+obj_key_begin:
+#if YYJSON_IS_REAL_GCC
+ while (true) repeat16({
+ if (byte_match_2(cur, " ")) cur += 2;
+ else break;
+ })
+#else
+ while (true) repeat16({
+ if (likely(byte_match_2(cur, " "))) cur += 2;
+ else break;
+ })
+#endif
+ if (likely(*cur == '"')) {
+ val_incr();
+ ctn_len++;
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_key_end;
+ goto fail_string;
+ }
+ if (likely(*cur == '}')) {
+ cur++;
+ if (likely(ctn_len == 0)) goto obj_end;
+ if (has_read_flag(ALLOW_TRAILING_COMMAS)) goto obj_end;
+ while (*cur != ',') cur--;
+ goto fail_trailing_comma;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_key_begin;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_key_begin;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_obj_key;
+
+obj_key_end:
+ if (byte_match_2(cur, ": ")) {
+ cur += 2;
+ goto obj_val_begin;
+ }
+ if (*cur == ':') {
+ cur++;
+ goto obj_val_begin;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_key_end;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_key_end;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_obj_sep;
+
+obj_val_begin:
+ if (*cur == '"') {
+ val++;
+ ctn_len++;
+ if (likely(read_string(&cur, end, inv, val, &msg))) goto obj_val_end;
+ goto fail_string;
+ }
+ if (char_is_number(*cur)) {
+ val++;
+ ctn_len++;
+ if (likely(read_number(&cur, pre, flg, val, &msg))) goto obj_val_end;
+ goto fail_number;
+ }
+ if (*cur == '{') {
+ cur++;
+ goto obj_begin;
+ }
+ if (*cur == '[') {
+ cur++;
+ goto arr_begin;
+ }
+ if (*cur == 't') {
+ val++;
+ ctn_len++;
+ if (likely(read_true(&cur, val))) goto obj_val_end;
+ goto fail_literal_true;
+ }
+ if (*cur == 'f') {
+ val++;
+ ctn_len++;
+ if (likely(read_false(&cur, val))) goto obj_val_end;
+ goto fail_literal_false;
+ }
+ if (*cur == 'n') {
+ val++;
+ ctn_len++;
+ if (likely(read_null(&cur, val))) goto obj_val_end;
+ if (has_read_flag(ALLOW_INF_AND_NAN)) {
+ if (read_nan(false, &cur, pre, val)) goto obj_val_end;
+ }
+ goto fail_literal_null;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_val_begin;
+ }
+ if (has_read_flag(ALLOW_INF_AND_NAN) &&
+ (*cur == 'i' || *cur == 'I' || *cur == 'N')) {
+ val++;
+ ctn_len++;
+ if (read_inf_or_nan(false, &cur, pre, val)) goto obj_val_end;
+ goto fail_character_val;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_val_begin;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_val;
+
+obj_val_end:
+ if (byte_match_2(cur, ",\n")) {
+ cur += 2;
+ goto obj_key_begin;
+ }
+ if (likely(*cur == ',')) {
+ cur++;
+ goto obj_key_begin;
+ }
+ if (likely(*cur == '}')) {
+ cur++;
+ goto obj_end;
+ }
+ if (char_is_space(*cur)) {
+ while (char_is_space(*++cur));
+ goto obj_val_end;
+ }
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (skip_spaces_and_comments(&cur)) goto obj_val_end;
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ }
+ goto fail_character_obj_end;
+
+obj_end:
+ /* pop container */
+ ctn_parent = (yyjson_val *)(void *)((u8 *)ctn - ctn->uni.ofs);
+ /* point to the next value */
+ ctn->uni.ofs = (usize)((u8 *)val - (u8 *)ctn) + sizeof(yyjson_val);
+ ctn->tag = (ctn_len << (YYJSON_TAG_BIT - 1)) | YYJSON_TYPE_OBJ;
+ if (unlikely(ctn == ctn_parent)) goto doc_end;
+ ctn = ctn_parent;
+ ctn_len = (usize)(ctn->tag >> YYJSON_TAG_BIT);
+ if (*cur == '\n') cur++;
+ if ((ctn->tag & YYJSON_TYPE_MASK) == YYJSON_TYPE_OBJ) {
+ goto obj_val_end;
+ } else {
+ goto arr_val_end;
+ }
+
+doc_end:
+ /* check invalid contents after json document */
+ if (unlikely(cur < end) && !has_read_flag(STOP_WHEN_DONE)) {
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ skip_spaces_and_comments(&cur);
+ if (byte_match_2(cur, "/*")) goto fail_comment;
+ } else {
+ while (char_is_space(*cur)) cur++;
+ }
+ if (unlikely(cur < end)) goto fail_garbage;
+ }
+
+ if (pre && *pre) **pre = '\0';
+ doc = (yyjson_doc *)val_hdr;
+ doc->root = val_hdr + hdr_len;
+ doc->alc = alc;
+ doc->dat_read = (usize)(cur - hdr);
+ doc->val_read = (usize)((val - val_hdr)) - hdr_len + 1;
+ doc->str_pool = has_read_flag(INSITU) ? NULL : (char *)hdr;
+ return doc;
+
+fail_string:
+ return_err(cur, INVALID_STRING, msg);
+fail_number:
+ return_err(cur, INVALID_NUMBER, msg);
+fail_alloc:
+ return_err(cur, MEMORY_ALLOCATION,
+ "memory allocation failed");
+fail_trailing_comma:
+ return_err(cur, JSON_STRUCTURE,
+ "trailing comma is not allowed");
+fail_literal_true:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'true'");
+fail_literal_false:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'false'");
+fail_literal_null:
+ return_err(cur, LITERAL,
+ "invalid literal, expected a valid literal such as 'null'");
+fail_character_val:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a valid JSON value");
+fail_character_arr_end:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a comma or a closing bracket");
+fail_character_obj_key:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a string for object key");
+fail_character_obj_sep:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a colon after object key");
+fail_character_obj_end:
+ return_err(cur, UNEXPECTED_CHARACTER,
+ "unexpected character, expected a comma or a closing brace");
+fail_comment:
+ return_err(cur, INVALID_COMMENT,
+ "unclosed multiline comment");
+fail_garbage:
+ return_err(cur, UNEXPECTED_CONTENT,
+ "unexpected content after document");
+
+#undef val_incr
+#undef return_err
+}
+
+
+
+/*==============================================================================
+ * JSON Reader Entrance
+ *============================================================================*/
+
+yyjson_doc *yyjson_read_opts(char *dat,
+ usize len,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_read_err *err) {
+
+#define return_err(_pos, _code, _msg) do { \
+ err->pos = (usize)(_pos); \
+ err->msg = _msg; \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ if (!has_read_flag(INSITU) && hdr) alc.free(alc.ctx, (void *)hdr); \
+ return NULL; \
+} while (false)
+
+ yyjson_read_err dummy_err;
+ yyjson_alc alc;
+ yyjson_doc *doc;
+ u8 *hdr = NULL, *end, *cur;
+
+ /* validate input parameters */
+ if (!err) err = &dummy_err;
+ if (likely(!alc_ptr)) {
+ alc = YYJSON_DEFAULT_ALC;
+ } else {
+ alc = *alc_ptr;
+ }
+ if (unlikely(!dat)) {
+ return_err(0, INVALID_PARAMETER, "input data is NULL");
+ }
+ if (unlikely(!len)) {
+ return_err(0, INVALID_PARAMETER, "input length is 0");
+ }
+
+ /* add 4-byte zero padding for input data if necessary */
+ if (has_read_flag(INSITU)) {
+ hdr = (u8 *)dat;
+ end = (u8 *)dat + len;
+ cur = (u8 *)dat;
+ } else {
+ if (unlikely(len >= USIZE_MAX - YYJSON_PADDING_SIZE)) {
+ return_err(0, MEMORY_ALLOCATION, "memory allocation failed");
+ }
+ hdr = (u8 *)alc.malloc(alc.ctx, len + YYJSON_PADDING_SIZE);
+ if (unlikely(!hdr)) {
+ return_err(0, MEMORY_ALLOCATION, "memory allocation failed");
+ }
+ end = hdr + len;
+ cur = hdr;
+ memcpy(hdr, dat, len);
+ memset(end, 0, YYJSON_PADDING_SIZE);
+ }
+
+ /* skip empty contents before json document */
+ if (unlikely(char_is_space_or_comment(*cur))) {
+ if (has_read_flag(ALLOW_COMMENTS)) {
+ if (!skip_spaces_and_comments(&cur)) {
+ return_err(cur - hdr, INVALID_COMMENT,
+ "unclosed multiline comment");
+ }
+ } else {
+ if (likely(char_is_space(*cur))) {
+ while (char_is_space(*++cur));
+ }
+ }
+ if (unlikely(cur >= end)) {
+ return_err(0, EMPTY_CONTENT, "input data is empty");
+ }
+ }
+
+ /* read json document */
+ if (likely(char_is_container(*cur))) {
+ if (char_is_space(cur[1]) && char_is_space(cur[2])) {
+ doc = read_root_pretty(hdr, cur, end, alc, flg, err);
+ } else {
+ doc = read_root_minify(hdr, cur, end, alc, flg, err);
+ }
+ } else {
+ doc = read_root_single(hdr, cur, end, alc, flg, err);
+ }
+
+ /* check result */
+ if (likely(doc)) {
+ memset(err, 0, sizeof(yyjson_read_err));
+ } else {
+ /* RFC 8259: JSON text MUST be encoded using UTF-8 */
+ if (err->pos == 0 && err->code != YYJSON_READ_ERROR_MEMORY_ALLOCATION) {
+ if ((hdr[0] == 0xEF && hdr[1] == 0xBB && hdr[2] == 0xBF)) {
+ err->msg = "byte order mark (BOM) is not supported";
+ } else if (len >= 4 &&
+ ((hdr[0] == 0x00 && hdr[1] == 0x00 &&
+ hdr[2] == 0xFE && hdr[3] == 0xFF) ||
+ (hdr[0] == 0xFF && hdr[1] == 0xFE &&
+ hdr[2] == 0x00 && hdr[3] == 0x00))) {
+ err->msg = "UTF-32 encoding is not supported";
+ } else if (len >= 2 &&
+ ((hdr[0] == 0xFE && hdr[1] == 0xFF) ||
+ (hdr[0] == 0xFF && hdr[1] == 0xFE))) {
+ err->msg = "UTF-16 encoding is not supported";
+ }
+ }
+ if (!has_read_flag(INSITU)) alc.free(alc.ctx, (void *)hdr);
+ }
+ return doc;
+
+#undef return_err
+}
+
+yyjson_doc *yyjson_read_file(const char *path,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_read_err *err) {
+#define return_err(_code, _msg) do { \
+ err->pos = 0; \
+ err->msg = _msg; \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ return NULL; \
+} while (false)
+
+ yyjson_read_err dummy_err;
+ yyjson_doc *doc;
+ FILE *file;
+
+ if (!err) err = &dummy_err;
+ if (unlikely(!path)) return_err(INVALID_PARAMETER, "input path is NULL");
+
+ file = fopen_readonly(path);
+ if (unlikely(!file)) return_err(FILE_OPEN, "file opening failed");
+
+ doc = yyjson_read_fp(file, flg, alc_ptr, err);
+ fclose(file);
+ return doc;
+
+#undef return_err
+}
+
+yyjson_doc *yyjson_read_fp(FILE *file,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_read_err *err) {
+#define return_err(_code, _msg) do { \
+ err->pos = 0; \
+ err->msg = _msg; \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ if (buf) alc.free(alc.ctx, buf); \
+ return NULL; \
+} while (false)
+
+ yyjson_read_err dummy_err;
+ yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC;
+ yyjson_doc *doc;
+
+ long file_size = 0, file_pos;
+ void *buf = NULL;
+ usize buf_size = 0;
+
+ /* validate input parameters */
+ if (!err) err = &dummy_err;
+ if (unlikely(!file)) return_err(INVALID_PARAMETER, "input file is NULL");
+
+ /* get current position */
+ file_pos = ftell(file);
+ if (file_pos != -1) {
+ /* get total file size, may fail */
+ if (fseek(file, 0, SEEK_END) == 0) file_size = ftell(file);
+ /* reset to original position, may fail */
+ if (fseek(file, file_pos, SEEK_SET) != 0) file_size = 0;
+ /* get file size from current postion to end */
+ if (file_size > 0) file_size -= file_pos;
+ }
+
+ /* read file */
+ if (file_size > 0) {
+ /* read the entire file in one call */
+ buf_size = (usize)file_size + YYJSON_PADDING_SIZE;
+ buf = alc.malloc(alc.ctx, buf_size);
+ if (buf == NULL) {
+ return_err(MEMORY_ALLOCATION, "fail to alloc memory");
+ }
+ if (fread_safe(buf, (usize)file_size, file) != (usize)file_size) {
+ return_err(FILE_READ, "file reading failed");
+ }
+ } else {
+ /* failed to get file size, read it as a stream */
+ usize chunk_min = (usize)64;
+ usize chunk_max = (usize)512 * 1024 * 1024;
+ usize chunk_now = chunk_min;
+ usize read_size;
+ void *tmp;
+
+ buf_size = YYJSON_PADDING_SIZE;
+ while (true) {
+ if (buf_size + chunk_now < buf_size) { /* overflow */
+ return_err(MEMORY_ALLOCATION, "fail to alloc memory");
+ }
+ buf_size += chunk_now;
+ if (!buf) {
+ buf = alc.malloc(alc.ctx, buf_size);
+ if (!buf) return_err(MEMORY_ALLOCATION, "fail to alloc memory");
+ } else {
+ tmp = alc.realloc(alc.ctx, buf, buf_size - chunk_now, buf_size);
+ if (!tmp) return_err(MEMORY_ALLOCATION, "fail to alloc memory");
+ buf = tmp;
+ }
+ tmp = ((u8 *)buf) + buf_size - YYJSON_PADDING_SIZE - chunk_now;
+ read_size = fread_safe(tmp, chunk_now, file);
+ file_size += (long)read_size;
+ if (read_size != chunk_now) break;
+
+ chunk_now *= 2;
+ if (chunk_now > chunk_max) chunk_now = chunk_max;
+ }
+ }
+
+ /* read JSON */
+ memset((u8 *)buf + file_size, 0, YYJSON_PADDING_SIZE);
+ flg |= YYJSON_READ_INSITU;
+ doc = yyjson_read_opts((char *)buf, (usize)file_size, flg, &alc, err);
+ if (doc) {
+ doc->str_pool = (char *)buf;
+ return doc;
+ } else {
+ alc.free(alc.ctx, buf);
+ return NULL;
+ }
+
+#undef return_err
+}
+
+const char *yyjson_read_number(const char *dat,
+ yyjson_val *val,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc,
+ yyjson_read_err *err) {
+#define return_err(_pos, _code, _msg) do { \
+ err->pos = _pos > hdr ? (usize)(_pos - hdr) : 0; \
+ err->msg = _msg; \
+ err->code = YYJSON_READ_ERROR_##_code; \
+ return NULL; \
+} while (false)
+
+ u8 *hdr = constcast(u8 *)dat, *cur = hdr;
+ bool raw; /* read number as raw */
+ u8 *raw_end; /* raw end for null-terminator */
+ u8 **pre; /* previous raw end pointer */
+ const char *msg;
+ yyjson_read_err dummy_err;
+
+#if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV
+ u8 buf[128];
+ usize dat_len;
+#endif
+
+ if (!err) err = &dummy_err;
+ if (unlikely(!dat)) {
+ return_err(cur, INVALID_PARAMETER, "input data is NULL");
+ }
+ if (unlikely(!val)) {
+ return_err(cur, INVALID_PARAMETER, "output value is NULL");
+ }
+
+#if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV
+ if (!alc) alc = &YYJSON_DEFAULT_ALC;
+ dat_len = strlen(dat);
+ if (dat_len < sizeof(buf)) {
+ memcpy(buf, dat, dat_len + 1);
+ hdr = buf;
+ cur = hdr;
+ } else {
+ hdr = (u8 *)alc->malloc(alc->ctx, dat_len + 1);
+ cur = hdr;
+ if (unlikely(!hdr)) {
+ return_err(cur, MEMORY_ALLOCATION, "memory allocation failed");
+ }
+ memcpy(hdr, dat, dat_len + 1);
+ }
+ hdr[dat_len] = 0;
+#endif
+
+ raw = (flg & (YYJSON_READ_NUMBER_AS_RAW | YYJSON_READ_BIGNUM_AS_RAW)) != 0;
+ raw_end = NULL;
+ pre = raw ? &raw_end : NULL;
+
+#if !YYJSON_HAS_IEEE_754 || YYJSON_DISABLE_FAST_FP_CONV
+ if (!read_number(&cur, pre, flg, val, &msg)) {
+ if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr);
+ return_err(cur, INVALID_NUMBER, msg);
+ }
+ if (dat_len >= sizeof(buf)) alc->free(alc->ctx, hdr);
+ if (yyjson_is_raw(val)) val->uni.str = dat;
+ return dat + (cur - hdr);
+#else
+ if (!read_number(&cur, pre, flg, val, &msg)) {
+ return_err(cur, INVALID_NUMBER, msg);
+ }
+ return (const char *)cur;
+#endif
+
+#undef return_err
+}
+
+#endif /* YYJSON_DISABLE_READER */
+
+
+
+#if !YYJSON_DISABLE_WRITER
+
+/*==============================================================================
+ * Integer Writer
+ *
+ * The maximum value of uint32_t is 4294967295 (10 digits),
+ * these digits are named as 'aabbccddee' here.
+ *
+ * Although most compilers may convert the "division by constant value" into
+ * "multiply and shift", manual conversion can still help some compilers
+ * generate fewer and better instructions.
+ *
+ * Reference:
+ * Division by Invariant Integers using Multiplication, 1994.
+ * https://gmplib.org/~tege/divcnst-pldi94.pdf
+ * Improved division by invariant integers, 2011.
+ * https://gmplib.org/~tege/division-paper.pdf
+ *============================================================================*/
+
+/** Digit table from 00 to 99. */
+yyjson_align(2)
+static const char digit_table[200] = {
+ '0', '0', '0', '1', '0', '2', '0', '3', '0', '4',
+ '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
+ '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
+ '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
+ '2', '0', '2', '1', '2', '2', '2', '3', '2', '4',
+ '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
+ '3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
+ '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
+ '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
+ '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
+ '5', '0', '5', '1', '5', '2', '5', '3', '5', '4',
+ '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
+ '6', '0', '6', '1', '6', '2', '6', '3', '6', '4',
+ '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
+ '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
+ '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
+ '8', '0', '8', '1', '8', '2', '8', '3', '8', '4',
+ '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
+ '9', '0', '9', '1', '9', '2', '9', '3', '9', '4',
+ '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
+};
+
+static_inline u8 *write_u32_len_8(u32 val, u8 *buf) {
+ u32 aa, bb, cc, dd, aabb, ccdd; /* 8 digits: aabbccdd */
+ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */
+ ccdd = val - aabb * 10000; /* (val % 10000) */
+ aa = (aabb * 5243) >> 19; /* (aabb / 100) */
+ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */
+ bb = aabb - aa * 100; /* (aabb % 100) */
+ dd = ccdd - cc * 100; /* (ccdd % 100) */
+ byte_copy_2(buf + 0, digit_table + aa * 2);
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ byte_copy_2(buf + 4, digit_table + cc * 2);
+ byte_copy_2(buf + 6, digit_table + dd * 2);
+ return buf + 8;
+}
+
+static_inline u8 *write_u32_len_4(u32 val, u8 *buf) {
+ u32 aa, bb; /* 4 digits: aabb */
+ aa = (val * 5243) >> 19; /* (val / 100) */
+ bb = val - aa * 100; /* (val % 100) */
+ byte_copy_2(buf + 0, digit_table + aa * 2);
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ return buf + 4;
+}
+
+static_inline u8 *write_u32_len_1_8(u32 val, u8 *buf) {
+ u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz;
+
+ if (val < 100) { /* 1-2 digits: aa */
+ lz = val < 10; /* leading zero: 0 or 1 */
+ byte_copy_2(buf + 0, digit_table + val * 2 + lz);
+ buf -= lz;
+ return buf + 2;
+
+ } else if (val < 10000) { /* 3-4 digits: aabb */
+ aa = (val * 5243) >> 19; /* (val / 100) */
+ bb = val - aa * 100; /* (val % 100) */
+ lz = aa < 10; /* leading zero: 0 or 1 */
+ byte_copy_2(buf + 0, digit_table + aa * 2 + lz);
+ buf -= lz;
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ return buf + 4;
+
+ } else if (val < 1000000) { /* 5-6 digits: aabbcc */
+ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */
+ bbcc = val - aa * 10000; /* (val % 10000) */
+ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */
+ cc = bbcc - bb * 100; /* (bbcc % 100) */
+ lz = aa < 10; /* leading zero: 0 or 1 */
+ byte_copy_2(buf + 0, digit_table + aa * 2 + lz);
+ buf -= lz;
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ byte_copy_2(buf + 4, digit_table + cc * 2);
+ return buf + 6;
+
+ } else { /* 7-8 digits: aabbccdd */
+ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */
+ ccdd = val - aabb * 10000; /* (val % 10000) */
+ aa = (aabb * 5243) >> 19; /* (aabb / 100) */
+ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */
+ bb = aabb - aa * 100; /* (aabb % 100) */
+ dd = ccdd - cc * 100; /* (ccdd % 100) */
+ lz = aa < 10; /* leading zero: 0 or 1 */
+ byte_copy_2(buf + 0, digit_table + aa * 2 + lz);
+ buf -= lz;
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ byte_copy_2(buf + 4, digit_table + cc * 2);
+ byte_copy_2(buf + 6, digit_table + dd * 2);
+ return buf + 8;
+ }
+}
+
+static_inline u8 *write_u64_len_5_8(u32 val, u8 *buf) {
+ u32 aa, bb, cc, dd, aabb, bbcc, ccdd, lz;
+
+ if (val < 1000000) { /* 5-6 digits: aabbcc */
+ aa = (u32)(((u64)val * 429497) >> 32); /* (val / 10000) */
+ bbcc = val - aa * 10000; /* (val % 10000) */
+ bb = (bbcc * 5243) >> 19; /* (bbcc / 100) */
+ cc = bbcc - bb * 100; /* (bbcc % 100) */
+ lz = aa < 10; /* leading zero: 0 or 1 */
+ byte_copy_2(buf + 0, digit_table + aa * 2 + lz);
+ buf -= lz;
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ byte_copy_2(buf + 4, digit_table + cc * 2);
+ return buf + 6;
+
+ } else { /* 7-8 digits: aabbccdd */
+ aabb = (u32)(((u64)val * 109951163) >> 40); /* (val / 10000) */
+ ccdd = val - aabb * 10000; /* (val % 10000) */
+ aa = (aabb * 5243) >> 19; /* (aabb / 100) */
+ cc = (ccdd * 5243) >> 19; /* (ccdd / 100) */
+ bb = aabb - aa * 100; /* (aabb % 100) */
+ dd = ccdd - cc * 100; /* (ccdd % 100) */
+ lz = aa < 10; /* leading zero: 0 or 1 */
+ byte_copy_2(buf + 0, digit_table + aa * 2 + lz);
+ buf -= lz;
+ byte_copy_2(buf + 2, digit_table + bb * 2);
+ byte_copy_2(buf + 4, digit_table + cc * 2);
+ byte_copy_2(buf + 6, digit_table + dd * 2);
+ return buf + 8;
+ }
+}
+
+static_inline u8 *write_u64(u64 val, u8 *buf) {
+ u64 tmp, hgh;
+ u32 mid, low;
+
+ if (val < 100000000) { /* 1-8 digits */
+ buf = write_u32_len_1_8((u32)val, buf);
+ return buf;
+
+ } else if (val < (u64)100000000 * 100000000) { /* 9-16 digits */
+ hgh = val / 100000000; /* (val / 100000000) */
+ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */
+ buf = write_u32_len_1_8((u32)hgh, buf);
+ buf = write_u32_len_8(low, buf);
+ return buf;
+
+ } else { /* 17-20 digits */
+ tmp = val / 100000000; /* (val / 100000000) */
+ low = (u32)(val - tmp * 100000000); /* (val % 100000000) */
+ hgh = (u32)(tmp / 10000); /* (tmp / 10000) */
+ mid = (u32)(tmp - hgh * 10000); /* (tmp % 10000) */
+ buf = write_u64_len_5_8((u32)hgh, buf);
+ buf = write_u32_len_4(mid, buf);
+ buf = write_u32_len_8(low, buf);
+ return buf;
+ }
+}
+
+
+
+/*==============================================================================
+ * Number Writer
+ *============================================================================*/
+
+#if YYJSON_HAS_IEEE_754 && !YYJSON_DISABLE_FAST_FP_CONV /* FP_WRITER */
+
+/** Trailing zero count table for number 0 to 99.
+ (generate with misc/make_tables.c) */
+static const u8 dec_trailing_zero_table[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/** Write an unsigned integer with a length of 1 to 16. */
+static_inline u8 *write_u64_len_1_to_16(u64 val, u8 *buf) {
+ u64 hgh;
+ u32 low;
+ if (val < 100000000) { /* 1-8 digits */
+ buf = write_u32_len_1_8((u32)val, buf);
+ return buf;
+ } else { /* 9-16 digits */
+ hgh = val / 100000000; /* (val / 100000000) */
+ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */
+ buf = write_u32_len_1_8((u32)hgh, buf);
+ buf = write_u32_len_8(low, buf);
+ return buf;
+ }
+}
+
+/** Write an unsigned integer with a length of 1 to 17. */
+static_inline u8 *write_u64_len_1_to_17(u64 val, u8 *buf) {
+ u64 hgh;
+ u32 mid, low, one;
+ if (val >= (u64)100000000 * 10000000) { /* len: 16 to 17 */
+ hgh = val / 100000000; /* (val / 100000000) */
+ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */
+ one = (u32)(hgh / 100000000); /* (hgh / 100000000) */
+ mid = (u32)(hgh - (u64)one * 100000000); /* (hgh % 100000000) */
+ *buf = (u8)((u8)one + (u8)'0');
+ buf += one > 0;
+ buf = write_u32_len_8(mid, buf);
+ buf = write_u32_len_8(low, buf);
+ return buf;
+ } else if (val >= (u64)100000000){ /* len: 9 to 15 */
+ hgh = val / 100000000; /* (val / 100000000) */
+ low = (u32)(val - hgh * 100000000); /* (val % 100000000) */
+ buf = write_u32_len_1_8((u32)hgh, buf);
+ buf = write_u32_len_8(low, buf);
+ return buf;
+ } else { /* len: 1 to 8 */
+ buf = write_u32_len_1_8((u32)val, buf);
+ return buf;
+ }
+}
+
+/**
+ Write an unsigned integer with a length of 15 to 17 with trailing zero trimmed.
+ These digits are named as "aabbccddeeffgghhii" here.
+ For example, input 1234567890123000, output "1234567890123".
+ */
+static_inline u8 *write_u64_len_15_to_17_trim(u8 *buf, u64 sig) {
+ bool lz; /* leading zero */
+ u32 tz1, tz2, tz; /* trailing zero */
+
+ u32 abbccddee = (u32)(sig / 100000000);
+ u32 ffgghhii = (u32)(sig - (u64)abbccddee * 100000000);
+ u32 abbcc = abbccddee / 10000; /* (abbccddee / 10000) */
+ u32 ddee = abbccddee - abbcc * 10000; /* (abbccddee % 10000) */
+ u32 abb = (u32)(((u64)abbcc * 167773) >> 24); /* (abbcc / 100) */
+ u32 a = (abb * 41) >> 12; /* (abb / 100) */
+ u32 bb = abb - a * 100; /* (abb % 100) */
+ u32 cc = abbcc - abb * 100; /* (abbcc % 100) */
+
+ /* write abbcc */
+ buf[0] = (u8)(a + '0');
+ buf += a > 0;
+ lz = bb < 10 && a == 0;
+ byte_copy_2(buf + 0, digit_table + bb * 2 + lz);
+ buf -= lz;
+ byte_copy_2(buf + 2, digit_table + cc * 2);
+
+ if (ffgghhii) {
+ u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */
+ u32 ee = ddee - dd * 100; /* (ddee % 100) */
+ u32 ffgg = (u32)(((u64)ffgghhii * 109951163) >> 40); /* (val / 10000) */
+ u32 hhii = ffgghhii - ffgg * 10000; /* (val % 10000) */
+ u32 ff = (ffgg * 5243) >> 19; /* (aabb / 100) */
+ u32 gg = ffgg - ff * 100; /* (aabb % 100) */
+ byte_copy_2(buf + 4, digit_table + dd * 2);
+ byte_copy_2(buf + 6, digit_table + ee * 2);
+ byte_copy_2(buf + 8, digit_table + ff * 2);
+ byte_copy_2(buf + 10, digit_table + gg * 2);
+ if (hhii) {
+ u32 hh = (hhii * 5243) >> 19; /* (ccdd / 100) */
+ u32 ii = hhii - hh * 100; /* (ccdd % 100) */
+ byte_copy_2(buf + 12, digit_table + hh * 2);
+ byte_copy_2(buf + 14, digit_table + ii * 2);
+ tz1 = dec_trailing_zero_table[hh];
+ tz2 = dec_trailing_zero_table[ii];
+ tz = ii ? tz2 : (tz1 + 2);
+ buf += 16 - tz;
+ return buf;
+ } else {
+ tz1 = dec_trailing_zero_table[ff];
+ tz2 = dec_trailing_zero_table[gg];
+ tz = gg ? tz2 : (tz1 + 2);
+ buf += 12 - tz;
+ return buf;
+ }
+ } else {
+ if (ddee) {
+ u32 dd = (ddee * 5243) >> 19; /* (ddee / 100) */
+ u32 ee = ddee - dd * 100; /* (ddee % 100) */
+ byte_copy_2(buf + 4, digit_table + dd * 2);
+ byte_copy_2(buf + 6, digit_table + ee * 2);
+ tz1 = dec_trailing_zero_table[dd];
+ tz2 = dec_trailing_zero_table[ee];
+ tz = ee ? tz2 : (tz1 + 2);
+ buf += 8 - tz;
+ return buf;
+ } else {
+ tz1 = dec_trailing_zero_table[bb];
+ tz2 = dec_trailing_zero_table[cc];
+ tz = cc ? tz2 : (tz1 + tz2);
+ buf += 4 - tz;
+ return buf;
+ }
+ }
+}
+
+/** Write a signed integer in the range -324 to 308. */
+static_inline u8 *write_f64_exp(i32 exp, u8 *buf) {
+ buf[0] = '-';
+ buf += exp < 0;
+ exp = exp < 0 ? -exp : exp;
+ if (exp < 100) {
+ u32 lz = exp < 10;
+ byte_copy_2(buf + 0, digit_table + (u32)exp * 2 + lz);
+ return buf + 2 - lz;
+ } else {
+ u32 hi = ((u32)exp * 656) >> 16; /* exp / 100 */
+ u32 lo = (u32)exp - hi * 100; /* exp % 100 */
+ buf[0] = (u8)((u8)hi + (u8)'0');
+ byte_copy_2(buf + 1, digit_table + lo * 2);
+ return buf + 3;
+ }
+}
+
+/** Multiplies 128-bit integer and returns highest 64-bit rounded value. */
+static_inline u64 round_to_odd(u64 hi, u64 lo, u64 cp) {
+ u64 x_hi, x_lo, y_hi, y_lo;
+ u128_mul(cp, lo, &x_hi, &x_lo);
+ u128_mul_add(cp, hi, x_hi, &y_hi, &y_lo);
+ return y_hi | (y_lo > 1);
+}
+
+/**
+ Convert double number from binary to decimal.
+ The output significand is shortest decimal but may have trailing zeros.
+
+ This function use the Schubfach algorithm:
+ Raffaello Giulietti, The Schubfach way to render doubles (5th version), 2022.
+ https://drive.google.com/file/d/1gp5xv4CAa78SVgCeWfGqqI4FfYYYuNFb
+ https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-November/083536.html
+ https://github.com/openjdk/jdk/pull/3402 (Java implementation)
+ https://github.com/abolz/Drachennest (C++ implementation)
+
+ See also:
+ Dragonbox: A New Floating-Point Binary-to-Decimal Conversion Algorithm, 2022.
+ https://github.com/jk-jeon/dragonbox/blob/master/other_files/Dragonbox.pdf
+ https://github.com/jk-jeon/dragonbox
+
+ @param sig_raw The raw value of significand in IEEE 754 format.
+ @param exp_raw The raw value of exponent in IEEE 754 format.
+ @param sig_bin The decoded value of significand in binary.
+ @param exp_bin The decoded value of exponent in binary.
+ @param sig_dec The output value of significand in decimal.
+ @param exp_dec The output value of exponent in decimal.
+ @warning The input double number should not be 0, inf, nan.
+ */
+static_inline void f64_bin_to_dec(u64 sig_raw, u32 exp_raw,
+ u64 sig_bin, i32 exp_bin,
+ u64 *sig_dec, i32 *exp_dec) {
+
+ bool is_even, regular_spacing, u_inside, w_inside, round_up;
+ u64 s, sp, cb, cbl, cbr, vb, vbl, vbr, pow10hi, pow10lo, upper, lower, mid;
+ i32 k, h, exp10;
+
+ is_even = !(sig_bin & 1);
+ regular_spacing = (sig_raw == 0 && exp_raw > 1);
+
+ cbl = 4 * sig_bin - 2 + regular_spacing;
+ cb = 4 * sig_bin;
+ cbr = 4 * sig_bin + 2;
+
+ /* exp_bin: [-1074, 971] */
+ /* k = regular_spacing ? floor(log10(pow(2, exp_bin))) */
+ /* : floor(log10(pow(2, exp_bin) * 3.0 / 4.0)) */
+ /* = regular_spacing ? floor(exp_bin * log10(2)) */
+ /* : floor(exp_bin * log10(2) + log10(3.0 / 4.0)) */
+ k = (i32)(exp_bin * 315653 - (regular_spacing ? 131237 : 0)) >> 20;
+
+ /* k: [-324, 292] */
+ /* h = exp_bin + floor(log2(pow(10, e))) */
+ /* = exp_bin + floor(log2(10) * e) */
+ exp10 = -k;
+ h = exp_bin + ((exp10 * 217707) >> 16) + 1;
+
+ pow10_table_get_sig(exp10, &pow10hi, &pow10lo);
+ pow10lo += (exp10 < POW10_SIG_TABLE_MIN_EXACT_EXP ||
+ exp10 > POW10_SIG_TABLE_MAX_EXACT_EXP);
+ vbl = round_to_odd(pow10hi, pow10lo, cbl << h);
+ vb = round_to_odd(pow10hi, pow10lo, cb << h);
+ vbr = round_to_odd(pow10hi, pow10lo, cbr << h);
+
+ lower = vbl + !is_even;
+ upper = vbr - !is_even;
+
+ s = vb / 4;
+ if (s >= 10) {
+ sp = s / 10;
+ u_inside = (lower <= 40 * sp);
+ w_inside = (upper >= 40 * sp + 40);
+ if (u_inside != w_inside) {
+ *sig_dec = sp + w_inside;
+ *exp_dec = k + 1;
+ return;
+ }
+ }
+
+ u_inside = (lower <= 4 * s);
+ w_inside = (upper >= 4 * s + 4);
+
+ mid = 4 * s + 2;
+ round_up = (vb > mid) || (vb == mid && (s & 1) != 0);
+
+ *sig_dec = s + ((u_inside != w_inside) ? w_inside : round_up);
+ *exp_dec = k;
+}
+
+/**
+ Write a double number (requires 32 bytes buffer).
+
+ We follows the ECMAScript specification to print floating point numbers,
+ but with the following changes:
+ 1. Keep the negative sign of 0.0 to preserve input information.
+ 2. Keep decimal point to indicate the number is floating point.
+ 3. Remove positive sign of exponent part.
+ */
+static_inline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) {
+ u64 sig_bin, sig_dec, sig_raw;
+ i32 exp_bin, exp_dec, sig_len, dot_pos, i, max;
+ u32 exp_raw, hi, lo;
+ u8 *hdr, *num_hdr, *num_end, *dot_end;
+ bool sign;
+
+ /* decode raw bytes from IEEE-754 double format. */
+ sign = (bool)(raw >> (F64_BITS - 1));
+ sig_raw = raw & F64_SIG_MASK;
+ exp_raw = (u32)((raw & F64_EXP_MASK) >> F64_SIG_BITS);
+
+ /* return inf and nan */
+ if (unlikely(exp_raw == ((u32)1 << F64_EXP_BITS) - 1)) {
+ if (has_write_flag(INF_AND_NAN_AS_NULL)) {
+ byte_copy_4(buf, "null");
+ return buf + 4;
+ }
+ else if (has_write_flag(ALLOW_INF_AND_NAN)) {
+ if (sig_raw == 0) {
+ buf[0] = '-';
+ buf += sign;
+ byte_copy_8(buf, "Infinity");
+ buf += 8;
+ return buf;
+ } else {
+ byte_copy_4(buf, "NaN");
+ return buf + 3;
+ }
+ }
+ return NULL;
+ }
+
+ /* add sign for all finite double value, including 0.0 and inf */
+ buf[0] = '-';
+ buf += sign;
+ hdr = buf;
+
+ /* return zero */
+ if ((raw << 1) == 0) {
+ byte_copy_4(buf, "0.0");
+ buf += 3;
+ return buf;
+ }
+
+ if (likely(exp_raw != 0)) {
+ /* normal number */
+ sig_bin = sig_raw | ((u64)1 << F64_SIG_BITS);
+ exp_bin = (i32)exp_raw - F64_EXP_BIAS - F64_SIG_BITS;
+
+ /* fast path for small integer number without fraction */
+ if (-F64_SIG_BITS <= exp_bin && exp_bin <= 0) {
+ if (u64_tz_bits(sig_bin) >= (u32)-exp_bin) {
+ /* number is integer in range 1 to 0x1FFFFFFFFFFFFF */
+ sig_dec = sig_bin >> -exp_bin;
+ buf = write_u64_len_1_to_16(sig_dec, buf);
+ byte_copy_2(buf, ".0");
+ buf += 2;
+ return buf;
+ }
+ }
+
+ /* binary to decimal */
+ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec);
+
+ /* the sig length is 15 to 17 */
+ sig_len = 17;
+ sig_len -= (sig_dec < (u64)100000000 * 100000000);
+ sig_len -= (sig_dec < (u64)100000000 * 10000000);
+
+ /* the decimal point position relative to the first digit */
+ dot_pos = sig_len + exp_dec;
+
+ if (-6 < dot_pos && dot_pos <= 21) {
+ /* no need to write exponent part */
+ if (dot_pos <= 0) {
+ /* dot before first digit */
+ /* such as 0.1234, 0.000001234 */
+ num_hdr = hdr + (2 - dot_pos);
+ num_end = write_u64_len_15_to_17_trim(num_hdr, sig_dec);
+ hdr[0] = '0';
+ hdr[1] = '.';
+ hdr += 2;
+ max = -dot_pos;
+ for (i = 0; i < max; i++) hdr[i] = '0';
+ return num_end;
+ } else {
+ /* dot after first digit */
+ /* such as 1.234, 1234.0, 123400000000000000000.0 */
+ memset(hdr + 0, '0', 8);
+ memset(hdr + 8, '0', 8);
+ memset(hdr + 16, '0', 8);
+ num_hdr = hdr + 1;
+ num_end = write_u64_len_15_to_17_trim(num_hdr, sig_dec);
+ for (i = 0; i < dot_pos; i++) hdr[i] = hdr[i + 1];
+ hdr[dot_pos] = '.';
+ dot_end = hdr + dot_pos + 2;
+ return dot_end < num_end ? num_end : dot_end;
+ }
+ } else {
+ /* write with scientific notation */
+ /* such as 1.234e56 */
+ u8 *end = write_u64_len_15_to_17_trim(buf + 1, sig_dec);
+ end -= (end == buf + 2); /* remove '.0', e.g. 2.0e34 -> 2e34 */
+ exp_dec += sig_len - 1;
+ hdr[0] = hdr[1];
+ hdr[1] = '.';
+ end[0] = 'e';
+ buf = write_f64_exp(exp_dec, end + 1);
+ return buf;
+ }
+
+ } else {
+ /* subnormal number */
+ sig_bin = sig_raw;
+ exp_bin = 1 - F64_EXP_BIAS - F64_SIG_BITS;
+
+ /* binary to decimal */
+ f64_bin_to_dec(sig_raw, exp_raw, sig_bin, exp_bin, &sig_dec, &exp_dec);
+
+ /* write significand part */
+ buf = write_u64_len_1_to_17(sig_dec, buf + 1);
+ hdr[0] = hdr[1];
+ hdr[1] = '.';
+ do {
+ buf--;
+ exp_dec++;
+ } while (*buf == '0');
+ exp_dec += (i32)(buf - hdr - 2);
+ buf += (*buf != '.');
+ buf[0] = 'e';
+ buf++;
+
+ /* write exponent part */
+ buf[0] = '-';
+ buf++;
+ exp_dec = -exp_dec;
+ hi = ((u32)exp_dec * 656) >> 16; /* exp / 100 */
+ lo = (u32)exp_dec - hi * 100; /* exp % 100 */
+ buf[0] = (u8)((u8)hi + (u8)'0');
+ byte_copy_2(buf + 1, digit_table + lo * 2);
+ buf += 3;
+ return buf;
+ }
+}
+
+#else /* FP_WRITER */
+
+/** Write a double number (requires 32 bytes buffer). */
+static_inline u8 *write_f64_raw(u8 *buf, u64 raw, yyjson_write_flag flg) {
+ /*
+ For IEEE 754, `DBL_DECIMAL_DIG` is 17 for round-trip.
+ For non-IEEE formats, 17 is used to avoid buffer overflow,
+ round-trip is not guaranteed.
+ */
+#if defined(DBL_DECIMAL_DIG) && DBL_DECIMAL_DIG != 17
+ int dig = DBL_DECIMAL_DIG > 17 ? 17 : DBL_DECIMAL_DIG;
+#else
+ int dig = 17;
+#endif
+
+ /*
+ The snprintf() function is locale-dependent. For currently known locales,
+ (en, zh, ja, ko, am, he, hi) use '.' as the decimal point, while other
+ locales use ',' as the decimal point. we need to replace ',' with '.'
+ to avoid the locale setting.
+ */
+ f64 val = f64_from_raw(raw);
+#if YYJSON_MSC_VER >= 1400
+ int len = sprintf_s((char *)buf, 32, "%.*g", dig, val);
+#elif defined(snprintf) || (YYJSON_STDC_VER >= 199901L)
+ int len = snprintf((char *)buf, 32, "%.*g", dig, val);
+#else
+ int len = sprintf((char *)buf, "%.*g", dig, val);
+#endif
+
+ u8 *cur = buf;
+ if (unlikely(len < 1)) return NULL;
+ cur += (*cur == '-');
+ if (unlikely(!digi_is_digit(*cur))) {
+ /* nan, inf, or bad output */
+ if (has_write_flag(INF_AND_NAN_AS_NULL)) {
+ byte_copy_4(buf, "null");
+ return buf + 4;
+ }
+ else if (has_write_flag(ALLOW_INF_AND_NAN)) {
+ if (*cur == 'i') {
+ byte_copy_8(cur, "Infinity");
+ cur += 8;
+ return cur;
+ } else if (*cur == 'n') {
+ byte_copy_4(buf, "NaN");
+ return buf + 3;
+ }
+ }
+ return NULL;
+ } else {
+ /* finite number */
+ int i = 0;
+ bool fp = false;
+ for (; i < len; i++) {
+ if (buf[i] == ',') buf[i] = '.';
+ if (digi_is_fp((u8)buf[i])) fp = true;
+ }
+ if (!fp) {
+ buf[len++] = '.';
+ buf[len++] = '0';
+ }
+ }
+ return buf + len;
+}
+
+#endif /* FP_WRITER */
+
+/** Write a JSON number (requires 32 bytes buffer). */
+static_inline u8 *write_number(u8 *cur, yyjson_val *val,
+ yyjson_write_flag flg) {
+ if (val->tag & YYJSON_SUBTYPE_REAL) {
+ u64 raw = val->uni.u64;
+ return write_f64_raw(cur, raw, flg);
+ } else {
+ u64 pos = val->uni.u64;
+ u64 neg = ~pos + 1;
+ usize sgn = ((val->tag & YYJSON_SUBTYPE_SINT) > 0) & ((i64)pos < 0);
+ *cur = '-';
+ return write_u64(sgn ? neg : pos, cur + sgn);
+ }
+}
+
+
+
+/*==============================================================================
+ * String Writer
+ *============================================================================*/
+
+/** Character encode type, if (type > CHAR_ENC_ERR_1) bytes = type / 2; */
+typedef u8 char_enc_type;
+#define CHAR_ENC_CPY_1 0 /* 1-byte UTF-8, copy. */
+#define CHAR_ENC_ERR_1 1 /* 1-byte UTF-8, error. */
+#define CHAR_ENC_ESC_A 2 /* 1-byte ASCII, escaped as '\x'. */
+#define CHAR_ENC_ESC_1 3 /* 1-byte UTF-8, escaped as '\uXXXX'. */
+#define CHAR_ENC_CPY_2 4 /* 2-byte UTF-8, copy. */
+#define CHAR_ENC_ESC_2 5 /* 2-byte UTF-8, escaped as '\uXXXX'. */
+#define CHAR_ENC_CPY_3 6 /* 3-byte UTF-8, copy. */
+#define CHAR_ENC_ESC_3 7 /* 3-byte UTF-8, escaped as '\uXXXX'. */
+#define CHAR_ENC_CPY_4 8 /* 4-byte UTF-8, copy. */
+#define CHAR_ENC_ESC_4 9 /* 4-byte UTF-8, escaped as '\uXXXX\uXXXX'. */
+
+/** Character encode type table: don't escape unicode, don't escape '/'.
+ (generate with misc/make_tables.c) */
+static const char_enc_type enc_table_cpy[256] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/** Character encode type table: don't escape unicode, escape '/'.
+ (generate with misc/make_tables.c) */
+static const char_enc_type enc_table_cpy_slash[256] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/** Character encode type table: escape unicode, don't escape '/'.
+ (generate with misc/make_tables.c) */
+static const char_enc_type enc_table_esc[256] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/** Character encode type table: escape unicode, escape '/'.
+ (generate with misc/make_tables.c) */
+static const char_enc_type enc_table_esc_slash[256] = {
+ 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 9, 9, 9, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/** Escaped hex character table: ["00" "01" "02" ... "FD" "FE" "FF"].
+ (generate with misc/make_tables.c) */
+yyjson_align(2)
+static const u8 esc_hex_char_table[512] = {
+ '0', '0', '0', '1', '0', '2', '0', '3',
+ '0', '4', '0', '5', '0', '6', '0', '7',
+ '0', '8', '0', '9', '0', 'A', '0', 'B',
+ '0', 'C', '0', 'D', '0', 'E', '0', 'F',
+ '1', '0', '1', '1', '1', '2', '1', '3',
+ '1', '4', '1', '5', '1', '6', '1', '7',
+ '1', '8', '1', '9', '1', 'A', '1', 'B',
+ '1', 'C', '1', 'D', '1', 'E', '1', 'F',
+ '2', '0', '2', '1', '2', '2', '2', '3',
+ '2', '4', '2', '5', '2', '6', '2', '7',
+ '2', '8', '2', '9', '2', 'A', '2', 'B',
+ '2', 'C', '2', 'D', '2', 'E', '2', 'F',
+ '3', '0', '3', '1', '3', '2', '3', '3',
+ '3', '4', '3', '5', '3', '6', '3', '7',
+ '3', '8', '3', '9', '3', 'A', '3', 'B',
+ '3', 'C', '3', 'D', '3', 'E', '3', 'F',
+ '4', '0', '4', '1', '4', '2', '4', '3',
+ '4', '4', '4', '5', '4', '6', '4', '7',
+ '4', '8', '4', '9', '4', 'A', '4', 'B',
+ '4', 'C', '4', 'D', '4', 'E', '4', 'F',
+ '5', '0', '5', '1', '5', '2', '5', '3',
+ '5', '4', '5', '5', '5', '6', '5', '7',
+ '5', '8', '5', '9', '5', 'A', '5', 'B',
+ '5', 'C', '5', 'D', '5', 'E', '5', 'F',
+ '6', '0', '6', '1', '6', '2', '6', '3',
+ '6', '4', '6', '5', '6', '6', '6', '7',
+ '6', '8', '6', '9', '6', 'A', '6', 'B',
+ '6', 'C', '6', 'D', '6', 'E', '6', 'F',
+ '7', '0', '7', '1', '7', '2', '7', '3',
+ '7', '4', '7', '5', '7', '6', '7', '7',
+ '7', '8', '7', '9', '7', 'A', '7', 'B',
+ '7', 'C', '7', 'D', '7', 'E', '7', 'F',
+ '8', '0', '8', '1', '8', '2', '8', '3',
+ '8', '4', '8', '5', '8', '6', '8', '7',
+ '8', '8', '8', '9', '8', 'A', '8', 'B',
+ '8', 'C', '8', 'D', '8', 'E', '8', 'F',
+ '9', '0', '9', '1', '9', '2', '9', '3',
+ '9', '4', '9', '5', '9', '6', '9', '7',
+ '9', '8', '9', '9', '9', 'A', '9', 'B',
+ '9', 'C', '9', 'D', '9', 'E', '9', 'F',
+ 'A', '0', 'A', '1', 'A', '2', 'A', '3',
+ 'A', '4', 'A', '5', 'A', '6', 'A', '7',
+ 'A', '8', 'A', '9', 'A', 'A', 'A', 'B',
+ 'A', 'C', 'A', 'D', 'A', 'E', 'A', 'F',
+ 'B', '0', 'B', '1', 'B', '2', 'B', '3',
+ 'B', '4', 'B', '5', 'B', '6', 'B', '7',
+ 'B', '8', 'B', '9', 'B', 'A', 'B', 'B',
+ 'B', 'C', 'B', 'D', 'B', 'E', 'B', 'F',
+ 'C', '0', 'C', '1', 'C', '2', 'C', '3',
+ 'C', '4', 'C', '5', 'C', '6', 'C', '7',
+ 'C', '8', 'C', '9', 'C', 'A', 'C', 'B',
+ 'C', 'C', 'C', 'D', 'C', 'E', 'C', 'F',
+ 'D', '0', 'D', '1', 'D', '2', 'D', '3',
+ 'D', '4', 'D', '5', 'D', '6', 'D', '7',
+ 'D', '8', 'D', '9', 'D', 'A', 'D', 'B',
+ 'D', 'C', 'D', 'D', 'D', 'E', 'D', 'F',
+ 'E', '0', 'E', '1', 'E', '2', 'E', '3',
+ 'E', '4', 'E', '5', 'E', '6', 'E', '7',
+ 'E', '8', 'E', '9', 'E', 'A', 'E', 'B',
+ 'E', 'C', 'E', 'D', 'E', 'E', 'E', 'F',
+ 'F', '0', 'F', '1', 'F', '2', 'F', '3',
+ 'F', '4', 'F', '5', 'F', '6', 'F', '7',
+ 'F', '8', 'F', '9', 'F', 'A', 'F', 'B',
+ 'F', 'C', 'F', 'D', 'F', 'E', 'F', 'F'
+};
+
+/** Escaped single character table. (generate with misc/make_tables.c) */
+yyjson_align(2)
+static const u8 esc_single_char_table[512] = {
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ '\\', 'b', '\\', 't', '\\', 'n', ' ', ' ',
+ '\\', 'f', '\\', 'r', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', '\\', '"', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', '\\', '/',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ '\\', '\\', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+};
+
+/** Returns the encode table with options. */
+static_inline const char_enc_type *get_enc_table_with_flag(
+ yyjson_write_flag flg) {
+ if (has_write_flag(ESCAPE_UNICODE)) {
+ if (has_write_flag(ESCAPE_SLASHES)) {
+ return enc_table_esc_slash;
+ } else {
+ return enc_table_esc;
+ }
+ } else {
+ if (has_write_flag(ESCAPE_SLASHES)) {
+ return enc_table_cpy_slash;
+ } else {
+ return enc_table_cpy;
+ }
+ }
+}
+
+/** Write raw string. */
+static_inline u8 *write_raw(u8 *cur, const u8 *raw, usize raw_len) {
+ memcpy(cur, raw, raw_len);
+ return cur + raw_len;
+}
+
+/**
+ Write string no-escape.
+ @param cur Buffer cursor.
+ @param str A UTF-8 string, null-terminator is not required.
+ @param str_len Length of string in bytes.
+ @return The buffer cursor after string.
+ */
+static_inline u8 *write_string_noesc(u8 *cur, const u8 *str, usize str_len) {
+ *cur++ = '"';
+ while (str_len >= 16) {
+ byte_copy_16(cur, str);
+ cur += 16;
+ str += 16;
+ str_len -= 16;
+ }
+ while (str_len >= 4) {
+ byte_copy_4(cur, str);
+ cur += 4;
+ str += 4;
+ str_len -= 4;
+ }
+ while (str_len) {
+ *cur++ = *str++;
+ str_len -= 1;
+ }
+ *cur++ = '"';
+ return cur;
+}
+
+/**
+ Write UTF-8 string (requires len * 6 + 2 bytes buffer).
+ @param cur Buffer cursor.
+ @param esc Escape unicode.
+ @param inv Allow invalid unicode.
+ @param str A UTF-8 string, null-terminator is not required.
+ @param str_len Length of string in bytes.
+ @param enc_table Encode type table for character.
+ @return The buffer cursor after string, or NULL on invalid unicode.
+ */
+static_inline u8 *write_string(u8 *cur, bool esc, bool inv,
+ const u8 *str, usize str_len,
+ const char_enc_type *enc_table) {
+
+ /* UTF-8 character mask and pattern, see `read_string()` for details. */
+#if YYJSON_ENDIAN == YYJSON_BIG_ENDIAN
+ const u16 b2_mask = 0xE0C0UL;
+ const u16 b2_patt = 0xC080UL;
+ const u16 b2_requ = 0x1E00UL;
+ const u32 b3_mask = 0xF0C0C000UL;
+ const u32 b3_patt = 0xE0808000UL;
+ const u32 b3_requ = 0x0F200000UL;
+ const u32 b3_erro = 0x0D200000UL;
+ const u32 b4_mask = 0xF8C0C0C0UL;
+ const u32 b4_patt = 0xF0808080UL;
+ const u32 b4_requ = 0x07300000UL;
+ const u32 b4_err0 = 0x04000000UL;
+ const u32 b4_err1 = 0x03300000UL;
+#elif YYJSON_ENDIAN == YYJSON_LITTLE_ENDIAN
+ const u16 b2_mask = 0xC0E0UL;
+ const u16 b2_patt = 0x80C0UL;
+ const u16 b2_requ = 0x001EUL;
+ const u32 b3_mask = 0x00C0C0F0UL;
+ const u32 b3_patt = 0x008080E0UL;
+ const u32 b3_requ = 0x0000200FUL;
+ const u32 b3_erro = 0x0000200DUL;
+ const u32 b4_mask = 0xC0C0C0F8UL;
+ const u32 b4_patt = 0x808080F0UL;
+ const u32 b4_requ = 0x00003007UL;
+ const u32 b4_err0 = 0x00000004UL;
+ const u32 b4_err1 = 0x00003003UL;
+#else
+ /* this should be evaluated at compile-time */
+ v16_uni b2_mask_uni = {{ 0xE0, 0xC0 }};
+ v16_uni b2_patt_uni = {{ 0xC0, 0x80 }};
+ v16_uni b2_requ_uni = {{ 0x1E, 0x00 }};
+ v32_uni b3_mask_uni = {{ 0xF0, 0xC0, 0xC0, 0x00 }};
+ v32_uni b3_patt_uni = {{ 0xE0, 0x80, 0x80, 0x00 }};
+ v32_uni b3_requ_uni = {{ 0x0F, 0x20, 0x00, 0x00 }};
+ v32_uni b3_erro_uni = {{ 0x0D, 0x20, 0x00, 0x00 }};
+ v32_uni b4_mask_uni = {{ 0xF8, 0xC0, 0xC0, 0xC0 }};
+ v32_uni b4_patt_uni = {{ 0xF0, 0x80, 0x80, 0x80 }};
+ v32_uni b4_requ_uni = {{ 0x07, 0x30, 0x00, 0x00 }};
+ v32_uni b4_err0_uni = {{ 0x04, 0x00, 0x00, 0x00 }};
+ v32_uni b4_err1_uni = {{ 0x03, 0x30, 0x00, 0x00 }};
+ u16 b2_mask = b2_mask_uni.u;
+ u16 b2_patt = b2_patt_uni.u;
+ u16 b2_requ = b2_requ_uni.u;
+ u32 b3_mask = b3_mask_uni.u;
+ u32 b3_patt = b3_patt_uni.u;
+ u32 b3_requ = b3_requ_uni.u;
+ u32 b3_erro = b3_erro_uni.u;
+ u32 b4_mask = b4_mask_uni.u;
+ u32 b4_patt = b4_patt_uni.u;
+ u32 b4_requ = b4_requ_uni.u;
+ u32 b4_err0 = b4_err0_uni.u;
+ u32 b4_err1 = b4_err1_uni.u;
+#endif
+
+#define is_valid_seq_2(uni) ( \
+ ((uni & b2_mask) == b2_patt) && \
+ ((uni & b2_requ)) \
+)
+
+#define is_valid_seq_3(uni) ( \
+ ((uni & b3_mask) == b3_patt) && \
+ ((tmp = (uni & b3_requ))) && \
+ ((tmp != b3_erro)) \
+)
+
+#define is_valid_seq_4(uni) ( \
+ ((uni & b4_mask) == b4_patt) && \
+ ((tmp = (uni & b4_requ))) && \
+ ((tmp & b4_err0) == 0 || (tmp & b4_err1) == 0) \
+)
+
+ /* The replacement character U+FFFD, used to indicate invalid character. */
+ const v32 rep = {{ 'F', 'F', 'F', 'D' }};
+ const v32 pre = {{ '\\', 'u', '0', '0' }};
+
+ const u8 *src = str;
+ const u8 *end = str + str_len;
+ *cur++ = '"';
+
+copy_ascii:
+ /*
+ Copy continuous ASCII, loop unrolling, same as the following code:
+
+ while (end > src) (
+ if (unlikely(enc_table[*src])) break;
+ *cur++ = *src++;
+ );
+ */
+#define expr_jump(i) \
+ if (unlikely(enc_table[src[i]])) goto stop_char_##i;
+
+#define expr_stop(i) \
+ stop_char_##i: \
+ memcpy(cur, src, i); \
+ cur += i; src += i; goto copy_utf8;
+
+ while (end - src >= 16) {
+ repeat16_incr(expr_jump)
+ byte_copy_16(cur, src);
+ cur += 16; src += 16;
+ }
+
+ while (end - src >= 4) {
+ repeat4_incr(expr_jump)
+ byte_copy_4(cur, src);
+ cur += 4; src += 4;
+ }
+
+ while (end > src) {
+ expr_jump(0)
+ *cur++ = *src++;
+ }
+
+ *cur++ = '"';
+ return cur;
+
+ repeat16_incr(expr_stop)
+
+#undef expr_jump
+#undef expr_stop
+
+copy_utf8:
+ if (unlikely(src + 4 > end)) {
+ if (end == src) goto copy_end;
+ if (end - src < enc_table[*src] / 2) goto err_one;
+ }
+ switch (enc_table[*src]) {
+ case CHAR_ENC_CPY_1: {
+ *cur++ = *src++;
+ goto copy_ascii;
+ }
+ case CHAR_ENC_CPY_2: {
+ u16 v;
+#if YYJSON_DISABLE_UTF8_VALIDATION
+ byte_copy_2(cur, src);
+#else
+ v = byte_load_2(src);
+ if (unlikely(!is_valid_seq_2(v))) goto err_cpy;
+ byte_copy_2(cur, src);
+#endif
+ cur += 2;
+ src += 2;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_CPY_3: {
+ u32 v, tmp;
+#if YYJSON_DISABLE_UTF8_VALIDATION
+ if (likely(src + 4 <= end)) {
+ byte_copy_4(cur, src);
+ } else {
+ byte_copy_2(cur, src);
+ cur[2] = src[2];
+ }
+#else
+ if (likely(src + 4 <= end)) {
+ v = byte_load_4(src);
+ if (unlikely(!is_valid_seq_3(v))) goto err_cpy;
+ byte_copy_4(cur, src);
+ } else {
+ v = byte_load_3(src);
+ if (unlikely(!is_valid_seq_3(v))) goto err_cpy;
+ byte_copy_4(cur, &v);
+ }
+#endif
+ cur += 3;
+ src += 3;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_CPY_4: {
+ u32 v, tmp;
+#if YYJSON_DISABLE_UTF8_VALIDATION
+ byte_copy_4(cur, src);
+#else
+ v = byte_load_4(src);
+ if (unlikely(!is_valid_seq_4(v))) goto err_cpy;
+ byte_copy_4(cur, src);
+#endif
+ cur += 4;
+ src += 4;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_ESC_A: {
+ byte_copy_2(cur, &esc_single_char_table[*src * 2]);
+ cur += 2;
+ src += 1;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_ESC_1: {
+ byte_copy_4(cur + 0, &pre);
+ byte_copy_2(cur + 4, &esc_hex_char_table[*src * 2]);
+ cur += 6;
+ src += 1;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_ESC_2: {
+ u16 u, v;
+#if !YYJSON_DISABLE_UTF8_VALIDATION
+ v = byte_load_2(src);
+ if (unlikely(!is_valid_seq_2(v))) goto err_esc;
+#endif
+ u = (u16)(((u16)(src[0] & 0x1F) << 6) |
+ ((u16)(src[1] & 0x3F) << 0));
+ byte_copy_2(cur + 0, &pre);
+ byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]);
+ byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]);
+ cur += 6;
+ src += 2;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_ESC_3: {
+ u16 u;
+ u32 v, tmp;
+#if !YYJSON_DISABLE_UTF8_VALIDATION
+ v = byte_load_3(src);
+ if (unlikely(!is_valid_seq_3(v))) goto err_esc;
+#endif
+ u = (u16)(((u16)(src[0] & 0x0F) << 12) |
+ ((u16)(src[1] & 0x3F) << 6) |
+ ((u16)(src[2] & 0x3F) << 0));
+ byte_copy_2(cur + 0, &pre);
+ byte_copy_2(cur + 2, &esc_hex_char_table[(u >> 8) * 2]);
+ byte_copy_2(cur + 4, &esc_hex_char_table[(u & 0xFF) * 2]);
+ cur += 6;
+ src += 3;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_ESC_4: {
+ u32 hi, lo, u, v, tmp;
+#if !YYJSON_DISABLE_UTF8_VALIDATION
+ v = byte_load_4(src);
+ if (unlikely(!is_valid_seq_4(v))) goto err_esc;
+#endif
+ u = ((u32)(src[0] & 0x07) << 18) |
+ ((u32)(src[1] & 0x3F) << 12) |
+ ((u32)(src[2] & 0x3F) << 6) |
+ ((u32)(src[3] & 0x3F) << 0);
+ u -= 0x10000;
+ hi = (u >> 10) + 0xD800;
+ lo = (u & 0x3FF) + 0xDC00;
+ byte_copy_2(cur + 0, &pre);
+ byte_copy_2(cur + 2, &esc_hex_char_table[(hi >> 8) * 2]);
+ byte_copy_2(cur + 4, &esc_hex_char_table[(hi & 0xFF) * 2]);
+ byte_copy_2(cur + 6, &pre);
+ byte_copy_2(cur + 8, &esc_hex_char_table[(lo >> 8) * 2]);
+ byte_copy_2(cur + 10, &esc_hex_char_table[(lo & 0xFF) * 2]);
+ cur += 12;
+ src += 4;
+ goto copy_utf8;
+ }
+ case CHAR_ENC_ERR_1: {
+ goto err_one;
+ }
+ default: break;
+ }
+
+copy_end:
+ *cur++ = '"';
+ return cur;
+
+err_one:
+ if (esc) goto err_esc;
+ else goto err_cpy;
+
+err_cpy:
+ if (!inv) return NULL;
+ *cur++ = *src++;
+ goto copy_utf8;
+
+err_esc:
+ if (!inv) return NULL;
+ byte_copy_2(cur + 0, &pre);
+ byte_copy_4(cur + 2, &rep);
+ cur += 6;
+ src += 1;
+ goto copy_utf8;
+
+#undef is_valid_seq_2
+#undef is_valid_seq_3
+#undef is_valid_seq_4
+}
+
+
+
+/*==============================================================================
+ * Writer Utilities
+ *============================================================================*/
+
+/** Write null (requires 8 bytes buffer). */
+static_inline u8 *write_null(u8 *cur) {
+ v64 v = {{ 'n', 'u', 'l', 'l', ',', '\n', 0, 0 }};
+ byte_copy_8(cur, &v);
+ return cur + 4;
+}
+
+/** Write bool (requires 8 bytes buffer). */
+static_inline u8 *write_bool(u8 *cur, bool val) {
+ v64 v0 = {{ 'f', 'a', 'l', 's', 'e', ',', '\n', 0 }};
+ v64 v1 = {{ 't', 'r', 'u', 'e', ',', '\n', 0, 0 }};
+ if (val) {
+ byte_copy_8(cur, &v1);
+ } else {
+ byte_copy_8(cur, &v0);
+ }
+ return cur + 5 - val;
+}
+
+/** Write indent (requires level x 4 bytes buffer).
+ Param spaces should not larger than 4. */
+static_inline u8 *write_indent(u8 *cur, usize level, usize spaces) {
+ while (level-- > 0) {
+ byte_copy_4(cur, " ");
+ cur += spaces;
+ }
+ return cur;
+}
+
+/** Write data to file pointer. */
+static bool write_dat_to_fp(FILE *fp, u8 *dat, usize len,
+ yyjson_write_err *err) {
+ if (fwrite(dat, len, 1, fp) != 1) {
+ err->msg = "file writing failed";
+ err->code = YYJSON_WRITE_ERROR_FILE_WRITE;
+ return false;
+ }
+ return true;
+}
+
+/** Write data to file. */
+static bool write_dat_to_file(const char *path, u8 *dat, usize len,
+ yyjson_write_err *err) {
+
+#define return_err(_code, _msg) do { \
+ err->msg = _msg; \
+ err->code = YYJSON_WRITE_ERROR_##_code; \
+ if (file) fclose(file); \
+ return false; \
+} while (false)
+
+ FILE *file = fopen_writeonly(path);
+ if (file == NULL) {
+ return_err(FILE_OPEN, "file opening failed");
+ }
+ if (fwrite(dat, len, 1, file) != 1) {
+ return_err(FILE_WRITE, "file writing failed");
+ }
+ if (fclose(file) != 0) {
+ file = NULL;
+ return_err(FILE_WRITE, "file closing failed");
+ }
+ return true;
+
+#undef return_err
+}
+
+
+
+/*==============================================================================
+ * JSON Writer Implementation
+ *============================================================================*/
+
+typedef struct yyjson_write_ctx {
+ usize tag;
+} yyjson_write_ctx;
+
+static_inline void yyjson_write_ctx_set(yyjson_write_ctx *ctx,
+ usize size, bool is_obj) {
+ ctx->tag = (size << 1) | (usize)is_obj;
+}
+
+static_inline void yyjson_write_ctx_get(yyjson_write_ctx *ctx,
+ usize *size, bool *is_obj) {
+ usize tag = ctx->tag;
+ *size = tag >> 1;
+ *is_obj = (bool)(tag & 1);
+}
+
+/** Write single JSON value. */
+static_inline u8 *yyjson_write_single(yyjson_val *val,
+ yyjson_write_flag flg,
+ yyjson_alc alc,
+ usize *dat_len,
+ yyjson_write_err *err) {
+
+#define return_err(_code, _msg) do { \
+ if (hdr) alc.free(alc.ctx, (void *)hdr); \
+ *dat_len = 0; \
+ err->code = YYJSON_WRITE_ERROR_##_code; \
+ err->msg = _msg; \
+ return NULL; \
+} while (false)
+
+#define incr_len(_len) do { \
+ hdr = (u8 *)alc.malloc(alc.ctx, _len); \
+ if (!hdr) goto fail_alloc; \
+ cur = hdr; \
+} while (false)
+
+#define check_str_len(_len) do { \
+ if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \
+ goto fail_alloc; \
+} while (false)
+
+ u8 *hdr = NULL, *cur;
+ usize str_len;
+ const u8 *str_ptr;
+ const char_enc_type *enc_table = get_enc_table_with_flag(flg);
+ bool cpy = (enc_table == enc_table_cpy);
+ bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
+ bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
+ bool newline = has_write_flag(NEWLINE_AT_END) != 0;
+ const usize end_len = 2; /* '\n' and '\0' */
+
+ switch (unsafe_yyjson_get_type(val)) {
+ case YYJSON_TYPE_RAW:
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len + end_len);
+ cur = write_raw(cur, str_ptr, str_len);
+ break;
+
+ case YYJSON_TYPE_STR:
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len * 6 + 2 + end_len);
+ if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
+ cur = write_string_noesc(cur, str_ptr, str_len);
+ } else {
+ cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table);
+ if (unlikely(!cur)) goto fail_str;
+ }
+ break;
+
+ case YYJSON_TYPE_NUM:
+ incr_len(32 + end_len);
+ cur = write_number(cur, val, flg);
+ if (unlikely(!cur)) goto fail_num;
+ break;
+
+ case YYJSON_TYPE_BOOL:
+ incr_len(8);
+ cur = write_bool(cur, unsafe_yyjson_get_bool(val));
+ break;
+
+ case YYJSON_TYPE_NULL:
+ incr_len(8);
+ cur = write_null(cur);
+ break;
+
+ case YYJSON_TYPE_ARR:
+ incr_len(2 + end_len);
+ byte_copy_2(cur, "[]");
+ cur += 2;
+ break;
+
+ case YYJSON_TYPE_OBJ:
+ incr_len(2 + end_len);
+ byte_copy_2(cur, "{}");
+ cur += 2;
+ break;
+
+ default:
+ goto fail_type;
+ }
+
+ if (newline) *cur++ = '\n';
+ *cur = '\0';
+ *dat_len = (usize)(cur - hdr);
+ memset(err, 0, sizeof(yyjson_write_err));
+ return hdr;
+
+fail_alloc:
+ return_err(MEMORY_ALLOCATION, "memory allocation failed");
+fail_type:
+ return_err(INVALID_VALUE_TYPE, "invalid JSON value type");
+fail_num:
+ return_err(NAN_OR_INF, "nan or inf number is not allowed");
+fail_str:
+ return_err(INVALID_STRING, "invalid utf-8 encoding in string");
+
+#undef return_err
+#undef check_str_len
+#undef incr_len
+}
+
+/** Write JSON document minify.
+ The root of this document should be a non-empty container. */
+static_inline u8 *yyjson_write_minify(const yyjson_val *root,
+ const yyjson_write_flag flg,
+ const yyjson_alc alc,
+ usize *dat_len,
+ yyjson_write_err *err) {
+
+#define return_err(_code, _msg) do { \
+ *dat_len = 0; \
+ err->code = YYJSON_WRITE_ERROR_##_code; \
+ err->msg = _msg; \
+ if (hdr) alc.free(alc.ctx, hdr); \
+ return NULL; \
+} while (false)
+
+#define incr_len(_len) do { \
+ ext_len = (usize)(_len); \
+ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \
+ alc_inc = yyjson_max(alc_len / 2, ext_len); \
+ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \
+ if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \
+ goto fail_alloc; \
+ alc_len += alc_inc; \
+ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \
+ if (unlikely(!tmp)) goto fail_alloc; \
+ ctx_len = (usize)(end - (u8 *)ctx); \
+ ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \
+ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \
+ ctx = ctx_tmp; \
+ cur = tmp + (cur - hdr); \
+ end = tmp + alc_len; \
+ hdr = tmp; \
+ } \
+} while (false)
+
+#define check_str_len(_len) do { \
+ if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \
+ goto fail_alloc; \
+} while (false)
+
+ yyjson_val *val;
+ yyjson_type val_type;
+ usize ctn_len, ctn_len_tmp;
+ bool ctn_obj, ctn_obj_tmp, is_key;
+ u8 *hdr, *cur, *end, *tmp;
+ yyjson_write_ctx *ctx, *ctx_tmp;
+ usize alc_len, alc_inc, ctx_len, ext_len, str_len;
+ const u8 *str_ptr;
+ const char_enc_type *enc_table = get_enc_table_with_flag(flg);
+ bool cpy = (enc_table == enc_table_cpy);
+ bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
+ bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
+ bool newline = has_write_flag(NEWLINE_AT_END) != 0;
+
+ alc_len = root->uni.ofs / sizeof(yyjson_val);
+ alc_len = alc_len * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64;
+ alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx));
+ hdr = (u8 *)alc.malloc(alc.ctx, alc_len);
+ if (!hdr) goto fail_alloc;
+ cur = hdr;
+ end = hdr + alc_len;
+ ctx = (yyjson_write_ctx *)(void *)end;
+
+doc_begin:
+ val = constcast(yyjson_val *)root;
+ val_type = unsafe_yyjson_get_type(val);
+ ctn_obj = (val_type == YYJSON_TYPE_OBJ);
+ ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ val++;
+
+val_begin:
+ val_type = unsafe_yyjson_get_type(val);
+ if (val_type == YYJSON_TYPE_STR) {
+ is_key = ((u8)ctn_obj & (u8)~ctn_len);
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len * 6 + 16);
+ if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
+ cur = write_string_noesc(cur, str_ptr, str_len);
+ } else {
+ cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table);
+ if (unlikely(!cur)) goto fail_str;
+ }
+ *cur++ = is_key ? ':' : ',';
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NUM) {
+ incr_len(32);
+ cur = write_number(cur, val, flg);
+ if (unlikely(!cur)) goto fail_num;
+ *cur++ = ',';
+ goto val_end;
+ }
+ if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) ==
+ (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) {
+ ctn_len_tmp = unsafe_yyjson_get_len(val);
+ ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ);
+ incr_len(16);
+ if (unlikely(ctn_len_tmp == 0)) {
+ /* write empty container */
+ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = ',';
+ goto val_end;
+ } else {
+ /* push context, setup new container */
+ yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj);
+ ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp;
+ ctn_obj = ctn_obj_tmp;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ val++;
+ goto val_begin;
+ }
+ }
+ if (val_type == YYJSON_TYPE_BOOL) {
+ incr_len(16);
+ cur = write_bool(cur, unsafe_yyjson_get_bool(val));
+ cur++;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NULL) {
+ incr_len(16);
+ cur = write_null(cur);
+ cur++;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_RAW) {
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len + 2);
+ cur = write_raw(cur, str_ptr, str_len);
+ *cur++ = ',';
+ goto val_end;
+ }
+ goto fail_type;
+
+val_end:
+ val++;
+ ctn_len--;
+ if (unlikely(ctn_len == 0)) goto ctn_end;
+ goto val_begin;
+
+ctn_end:
+ cur--;
+ *cur++ = (u8)(']' | ((u8)ctn_obj << 5));
+ *cur++ = ',';
+ if (unlikely((u8 *)ctx >= end)) goto doc_end;
+ yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj);
+ ctn_len--;
+ if (likely(ctn_len > 0)) {
+ goto val_begin;
+ } else {
+ goto ctn_end;
+ }
+
+doc_end:
+ if (newline) {
+ incr_len(2);
+ *(cur - 1) = '\n';
+ cur++;
+ }
+ *--cur = '\0';
+ *dat_len = (usize)(cur - hdr);
+ memset(err, 0, sizeof(yyjson_write_err));
+ return hdr;
+
+fail_alloc:
+ return_err(MEMORY_ALLOCATION, "memory allocation failed");
+fail_type:
+ return_err(INVALID_VALUE_TYPE, "invalid JSON value type");
+fail_num:
+ return_err(NAN_OR_INF, "nan or inf number is not allowed");
+fail_str:
+ return_err(INVALID_STRING, "invalid utf-8 encoding in string");
+
+#undef return_err
+#undef incr_len
+#undef check_str_len
+}
+
+/** Write JSON document pretty.
+ The root of this document should be a non-empty container. */
+static_inline u8 *yyjson_write_pretty(const yyjson_val *root,
+ const yyjson_write_flag flg,
+ const yyjson_alc alc,
+ usize *dat_len,
+ yyjson_write_err *err) {
+
+#define return_err(_code, _msg) do { \
+ *dat_len = 0; \
+ err->code = YYJSON_WRITE_ERROR_##_code; \
+ err->msg = _msg; \
+ if (hdr) alc.free(alc.ctx, hdr); \
+ return NULL; \
+} while (false)
+
+#define incr_len(_len) do { \
+ ext_len = (usize)(_len); \
+ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \
+ alc_inc = yyjson_max(alc_len / 2, ext_len); \
+ alc_inc = size_align_up(alc_inc, sizeof(yyjson_write_ctx)); \
+ if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \
+ goto fail_alloc; \
+ alc_len += alc_inc; \
+ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \
+ if (unlikely(!tmp)) goto fail_alloc; \
+ ctx_len = (usize)(end - (u8 *)ctx); \
+ ctx_tmp = (yyjson_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \
+ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \
+ ctx = ctx_tmp; \
+ cur = tmp + (cur - hdr); \
+ end = tmp + alc_len; \
+ hdr = tmp; \
+ } \
+} while (false)
+
+#define check_str_len(_len) do { \
+ if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \
+ goto fail_alloc; \
+} while (false)
+
+ yyjson_val *val;
+ yyjson_type val_type;
+ usize ctn_len, ctn_len_tmp;
+ bool ctn_obj, ctn_obj_tmp, is_key, no_indent;
+ u8 *hdr, *cur, *end, *tmp;
+ yyjson_write_ctx *ctx, *ctx_tmp;
+ usize alc_len, alc_inc, ctx_len, ext_len, str_len, level;
+ const u8 *str_ptr;
+ const char_enc_type *enc_table = get_enc_table_with_flag(flg);
+ bool cpy = (enc_table == enc_table_cpy);
+ bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
+ bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
+ usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4;
+ bool newline = has_write_flag(NEWLINE_AT_END) != 0;
+
+ alc_len = root->uni.ofs / sizeof(yyjson_val);
+ alc_len = alc_len * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64;
+ alc_len = size_align_up(alc_len, sizeof(yyjson_write_ctx));
+ hdr = (u8 *)alc.malloc(alc.ctx, alc_len);
+ if (!hdr) goto fail_alloc;
+ cur = hdr;
+ end = hdr + alc_len;
+ ctx = (yyjson_write_ctx *)(void *)end;
+
+doc_begin:
+ val = constcast(yyjson_val *)root;
+ val_type = unsafe_yyjson_get_type(val);
+ ctn_obj = (val_type == YYJSON_TYPE_OBJ);
+ ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ *cur++ = '\n';
+ val++;
+ level = 1;
+
+val_begin:
+ val_type = unsafe_yyjson_get_type(val);
+ if (val_type == YYJSON_TYPE_STR) {
+ is_key = (bool)((u8)ctn_obj & (u8)~ctn_len);
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
+ cur = write_string_noesc(cur, str_ptr, str_len);
+ } else {
+ cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table);
+ if (unlikely(!cur)) goto fail_str;
+ }
+ *cur++ = is_key ? ':' : ',';
+ *cur++ = is_key ? ' ' : '\n';
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NUM) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ incr_len(32 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ cur = write_number(cur, val, flg);
+ if (unlikely(!cur)) goto fail_num;
+ *cur++ = ',';
+ *cur++ = '\n';
+ goto val_end;
+ }
+ if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) ==
+ (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ ctn_len_tmp = unsafe_yyjson_get_len(val);
+ ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ);
+ if (unlikely(ctn_len_tmp == 0)) {
+ /* write empty container */
+ incr_len(16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = ',';
+ *cur++ = '\n';
+ goto val_end;
+ } else {
+ /* push context, setup new container */
+ incr_len(32 + (no_indent ? 0 : level * 4));
+ yyjson_write_ctx_set(--ctx, ctn_len, ctn_obj);
+ ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp;
+ ctn_obj = ctn_obj_tmp;
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ level++;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ *cur++ = '\n';
+ val++;
+ goto val_begin;
+ }
+ }
+ if (val_type == YYJSON_TYPE_BOOL) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ incr_len(16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ cur = write_bool(cur, unsafe_yyjson_get_bool(val));
+ cur += 2;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NULL) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ incr_len(16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ cur = write_null(cur);
+ cur += 2;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_RAW) {
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len + 3);
+ cur = write_raw(cur, str_ptr, str_len);
+ *cur++ = ',';
+ *cur++ = '\n';
+ goto val_end;
+ }
+ goto fail_type;
+
+val_end:
+ val++;
+ ctn_len--;
+ if (unlikely(ctn_len == 0)) goto ctn_end;
+ goto val_begin;
+
+ctn_end:
+ cur -= 2;
+ *cur++ = '\n';
+ incr_len(level * 4);
+ cur = write_indent(cur, --level, spaces);
+ *cur++ = (u8)(']' | ((u8)ctn_obj << 5));
+ if (unlikely((u8 *)ctx >= end)) goto doc_end;
+ yyjson_write_ctx_get(ctx++, &ctn_len, &ctn_obj);
+ ctn_len--;
+ *cur++ = ',';
+ *cur++ = '\n';
+ if (likely(ctn_len > 0)) {
+ goto val_begin;
+ } else {
+ goto ctn_end;
+ }
+
+doc_end:
+ if (newline) {
+ incr_len(2);
+ *cur++ = '\n';
+ }
+ *cur = '\0';
+ *dat_len = (usize)(cur - hdr);
+ memset(err, 0, sizeof(yyjson_write_err));
+ return hdr;
+
+fail_alloc:
+ return_err(MEMORY_ALLOCATION, "memory allocation failed");
+fail_type:
+ return_err(INVALID_VALUE_TYPE, "invalid JSON value type");
+fail_num:
+ return_err(NAN_OR_INF, "nan or inf number is not allowed");
+fail_str:
+ return_err(INVALID_STRING, "invalid utf-8 encoding in string");
+
+#undef return_err
+#undef incr_len
+#undef check_str_len
+}
+
+char *yyjson_val_write_opts(const yyjson_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ usize *dat_len,
+ yyjson_write_err *err) {
+ yyjson_write_err dummy_err;
+ usize dummy_dat_len;
+ yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC;
+ yyjson_val *root = constcast(yyjson_val *)val;
+
+ err = err ? err : &dummy_err;
+ dat_len = dat_len ? dat_len : &dummy_dat_len;
+
+ if (unlikely(!root)) {
+ *dat_len = 0;
+ err->msg = "input JSON is NULL";
+ err->code = YYJSON_READ_ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) {
+ return (char *)yyjson_write_single(root, flg, alc, dat_len, err);
+ } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) {
+ return (char *)yyjson_write_pretty(root, flg, alc, dat_len, err);
+ } else {
+ return (char *)yyjson_write_minify(root, flg, alc, dat_len, err);
+ }
+}
+
+char *yyjson_write_opts(const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ usize *dat_len,
+ yyjson_write_err *err) {
+ yyjson_val *root = doc ? doc->root : NULL;
+ return yyjson_val_write_opts(root, flg, alc_ptr, dat_len, err);
+}
+
+bool yyjson_val_write_file(const char *path,
+ const yyjson_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_write_err dummy_err;
+ u8 *dat;
+ usize dat_len = 0;
+ yyjson_val *root = constcast(yyjson_val *)val;
+ bool suc;
+
+ alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC;
+ err = err ? err : &dummy_err;
+ if (unlikely(!path || !*path)) {
+ err->msg = "input path is invalid";
+ err->code = YYJSON_READ_ERROR_INVALID_PARAMETER;
+ return false;
+ }
+
+ dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err);
+ if (unlikely(!dat)) return false;
+ suc = write_dat_to_file(path, dat, dat_len, err);
+ alc_ptr->free(alc_ptr->ctx, dat);
+ return suc;
+}
+
+bool yyjson_val_write_fp(FILE *fp,
+ const yyjson_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_write_err dummy_err;
+ u8 *dat;
+ usize dat_len = 0;
+ yyjson_val *root = constcast(yyjson_val *)val;
+ bool suc;
+
+ alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC;
+ err = err ? err : &dummy_err;
+ if (unlikely(!fp)) {
+ err->msg = "input fp is invalid";
+ err->code = YYJSON_READ_ERROR_INVALID_PARAMETER;
+ return false;
+ }
+
+ dat = (u8 *)yyjson_val_write_opts(root, flg, alc_ptr, &dat_len, err);
+ if (unlikely(!dat)) return false;
+ suc = write_dat_to_fp(fp, dat, dat_len, err);
+ alc_ptr->free(alc_ptr->ctx, dat);
+ return suc;
+}
+
+bool yyjson_write_file(const char *path,
+ const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_val *root = doc ? doc->root : NULL;
+ return yyjson_val_write_file(path, root, flg, alc_ptr, err);
+}
+
+bool yyjson_write_fp(FILE *fp,
+ const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_val *root = doc ? doc->root : NULL;
+ return yyjson_val_write_fp(fp, root, flg, alc_ptr, err);
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Writer Implementation
+ *============================================================================*/
+
+typedef struct yyjson_mut_write_ctx {
+ usize tag;
+ yyjson_mut_val *ctn;
+} yyjson_mut_write_ctx;
+
+static_inline void yyjson_mut_write_ctx_set(yyjson_mut_write_ctx *ctx,
+ yyjson_mut_val *ctn,
+ usize size, bool is_obj) {
+ ctx->tag = (size << 1) | (usize)is_obj;
+ ctx->ctn = ctn;
+}
+
+static_inline void yyjson_mut_write_ctx_get(yyjson_mut_write_ctx *ctx,
+ yyjson_mut_val **ctn,
+ usize *size, bool *is_obj) {
+ usize tag = ctx->tag;
+ *size = tag >> 1;
+ *is_obj = (bool)(tag & 1);
+ *ctn = ctx->ctn;
+}
+
+/** Get the estimated number of values for the mutable JSON document. */
+static_inline usize yyjson_mut_doc_estimated_val_num(
+ const yyjson_mut_doc *doc) {
+ usize sum = 0;
+ yyjson_val_chunk *chunk = doc->val_pool.chunks;
+ while (chunk) {
+ sum += chunk->chunk_size / sizeof(yyjson_mut_val) - 1;
+ if (chunk == doc->val_pool.chunks) {
+ sum -= (usize)(doc->val_pool.end - doc->val_pool.cur);
+ }
+ chunk = chunk->next;
+ }
+ return sum;
+}
+
+/** Write single JSON value. */
+static_inline u8 *yyjson_mut_write_single(yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ yyjson_alc alc,
+ usize *dat_len,
+ yyjson_write_err *err) {
+ return yyjson_write_single((yyjson_val *)val, flg, alc, dat_len, err);
+}
+
+/** Write JSON document minify.
+ The root of this document should be a non-empty container. */
+static_inline u8 *yyjson_mut_write_minify(const yyjson_mut_val *root,
+ usize estimated_val_num,
+ yyjson_write_flag flg,
+ yyjson_alc alc,
+ usize *dat_len,
+ yyjson_write_err *err) {
+
+#define return_err(_code, _msg) do { \
+ *dat_len = 0; \
+ err->code = YYJSON_WRITE_ERROR_##_code; \
+ err->msg = _msg; \
+ if (hdr) alc.free(alc.ctx, hdr); \
+ return NULL; \
+} while (false)
+
+#define incr_len(_len) do { \
+ ext_len = (usize)(_len); \
+ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \
+ alc_inc = yyjson_max(alc_len / 2, ext_len); \
+ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \
+ if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \
+ goto fail_alloc; \
+ alc_len += alc_inc; \
+ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \
+ if (unlikely(!tmp)) goto fail_alloc; \
+ ctx_len = (usize)(end - (u8 *)ctx); \
+ ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \
+ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \
+ ctx = ctx_tmp; \
+ cur = tmp + (cur - hdr); \
+ end = tmp + alc_len; \
+ hdr = tmp; \
+ } \
+} while (false)
+
+#define check_str_len(_len) do { \
+ if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \
+ goto fail_alloc; \
+} while (false)
+
+ yyjson_mut_val *val, *ctn;
+ yyjson_type val_type;
+ usize ctn_len, ctn_len_tmp;
+ bool ctn_obj, ctn_obj_tmp, is_key;
+ u8 *hdr, *cur, *end, *tmp;
+ yyjson_mut_write_ctx *ctx, *ctx_tmp;
+ usize alc_len, alc_inc, ctx_len, ext_len, str_len;
+ const u8 *str_ptr;
+ const char_enc_type *enc_table = get_enc_table_with_flag(flg);
+ bool cpy = (enc_table == enc_table_cpy);
+ bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
+ bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
+ bool newline = has_write_flag(NEWLINE_AT_END) != 0;
+
+ alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_MINIFY_RATIO + 64;
+ alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx));
+ hdr = (u8 *)alc.malloc(alc.ctx, alc_len);
+ if (!hdr) goto fail_alloc;
+ cur = hdr;
+ end = hdr + alc_len;
+ ctx = (yyjson_mut_write_ctx *)(void *)end;
+
+doc_begin:
+ val = constcast(yyjson_mut_val *)root;
+ val_type = unsafe_yyjson_get_type(val);
+ ctn_obj = (val_type == YYJSON_TYPE_OBJ);
+ ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ ctn = val;
+ val = (yyjson_mut_val *)val->uni.ptr; /* tail */
+ val = ctn_obj ? val->next->next : val->next;
+
+val_begin:
+ val_type = unsafe_yyjson_get_type(val);
+ if (val_type == YYJSON_TYPE_STR) {
+ is_key = ((u8)ctn_obj & (u8)~ctn_len);
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len * 6 + 16);
+ if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
+ cur = write_string_noesc(cur, str_ptr, str_len);
+ } else {
+ cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table);
+ if (unlikely(!cur)) goto fail_str;
+ }
+ *cur++ = is_key ? ':' : ',';
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NUM) {
+ incr_len(32);
+ cur = write_number(cur, (yyjson_val *)val, flg);
+ if (unlikely(!cur)) goto fail_num;
+ *cur++ = ',';
+ goto val_end;
+ }
+ if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) ==
+ (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) {
+ ctn_len_tmp = unsafe_yyjson_get_len(val);
+ ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ);
+ incr_len(16);
+ if (unlikely(ctn_len_tmp == 0)) {
+ /* write empty container */
+ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = ',';
+ goto val_end;
+ } else {
+ /* push context, setup new container */
+ yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj);
+ ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp;
+ ctn_obj = ctn_obj_tmp;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ ctn = val;
+ val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */
+ val = ctn_obj ? val->next->next : val->next;
+ goto val_begin;
+ }
+ }
+ if (val_type == YYJSON_TYPE_BOOL) {
+ incr_len(16);
+ cur = write_bool(cur, unsafe_yyjson_get_bool(val));
+ cur++;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NULL) {
+ incr_len(16);
+ cur = write_null(cur);
+ cur++;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_RAW) {
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len + 2);
+ cur = write_raw(cur, str_ptr, str_len);
+ *cur++ = ',';
+ goto val_end;
+ }
+ goto fail_type;
+
+val_end:
+ ctn_len--;
+ if (unlikely(ctn_len == 0)) goto ctn_end;
+ val = val->next;
+ goto val_begin;
+
+ctn_end:
+ cur--;
+ *cur++ = (u8)(']' | ((u8)ctn_obj << 5));
+ *cur++ = ',';
+ if (unlikely((u8 *)ctx >= end)) goto doc_end;
+ val = ctn->next;
+ yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj);
+ ctn_len--;
+ if (likely(ctn_len > 0)) {
+ goto val_begin;
+ } else {
+ goto ctn_end;
+ }
+
+doc_end:
+ if (newline) {
+ incr_len(2);
+ *(cur - 1) = '\n';
+ cur++;
+ }
+ *--cur = '\0';
+ *dat_len = (usize)(cur - hdr);
+ err->code = YYJSON_WRITE_SUCCESS;
+ err->msg = "success";
+ return hdr;
+
+fail_alloc:
+ return_err(MEMORY_ALLOCATION, "memory allocation failed");
+fail_type:
+ return_err(INVALID_VALUE_TYPE, "invalid JSON value type");
+fail_num:
+ return_err(NAN_OR_INF, "nan or inf number is not allowed");
+fail_str:
+ return_err(INVALID_STRING, "invalid utf-8 encoding in string");
+
+#undef return_err
+#undef incr_len
+#undef check_str_len
+}
+
+/** Write JSON document pretty.
+ The root of this document should be a non-empty container. */
+static_inline u8 *yyjson_mut_write_pretty(const yyjson_mut_val *root,
+ usize estimated_val_num,
+ yyjson_write_flag flg,
+ yyjson_alc alc,
+ usize *dat_len,
+ yyjson_write_err *err) {
+
+#define return_err(_code, _msg) do { \
+ *dat_len = 0; \
+ err->code = YYJSON_WRITE_ERROR_##_code; \
+ err->msg = _msg; \
+ if (hdr) alc.free(alc.ctx, hdr); \
+ return NULL; \
+} while (false)
+
+#define incr_len(_len) do { \
+ ext_len = (usize)(_len); \
+ if (unlikely((u8 *)(cur + ext_len) >= (u8 *)ctx)) { \
+ alc_inc = yyjson_max(alc_len / 2, ext_len); \
+ alc_inc = size_align_up(alc_inc, sizeof(yyjson_mut_write_ctx)); \
+ if ((sizeof(usize) < 8) && size_add_is_overflow(alc_len, alc_inc)) \
+ goto fail_alloc; \
+ alc_len += alc_inc; \
+ tmp = (u8 *)alc.realloc(alc.ctx, hdr, alc_len - alc_inc, alc_len); \
+ if (unlikely(!tmp)) goto fail_alloc; \
+ ctx_len = (usize)(end - (u8 *)ctx); \
+ ctx_tmp = (yyjson_mut_write_ctx *)(void *)(tmp + (alc_len - ctx_len)); \
+ memmove((void *)ctx_tmp, (void *)(tmp + ((u8 *)ctx - hdr)), ctx_len); \
+ ctx = ctx_tmp; \
+ cur = tmp + (cur - hdr); \
+ end = tmp + alc_len; \
+ hdr = tmp; \
+ } \
+} while (false)
+
+#define check_str_len(_len) do { \
+ if ((sizeof(usize) < 8) && (_len >= (USIZE_MAX - 16) / 6)) \
+ goto fail_alloc; \
+} while (false)
+
+ yyjson_mut_val *val, *ctn;
+ yyjson_type val_type;
+ usize ctn_len, ctn_len_tmp;
+ bool ctn_obj, ctn_obj_tmp, is_key, no_indent;
+ u8 *hdr, *cur, *end, *tmp;
+ yyjson_mut_write_ctx *ctx, *ctx_tmp;
+ usize alc_len, alc_inc, ctx_len, ext_len, str_len, level;
+ const u8 *str_ptr;
+ const char_enc_type *enc_table = get_enc_table_with_flag(flg);
+ bool cpy = (enc_table == enc_table_cpy);
+ bool esc = has_write_flag(ESCAPE_UNICODE) != 0;
+ bool inv = has_write_flag(ALLOW_INVALID_UNICODE) != 0;
+ usize spaces = has_write_flag(PRETTY_TWO_SPACES) ? 2 : 4;
+ bool newline = has_write_flag(NEWLINE_AT_END) != 0;
+
+ alc_len = estimated_val_num * YYJSON_WRITER_ESTIMATED_PRETTY_RATIO + 64;
+ alc_len = size_align_up(alc_len, sizeof(yyjson_mut_write_ctx));
+ hdr = (u8 *)alc.malloc(alc.ctx, alc_len);
+ if (!hdr) goto fail_alloc;
+ cur = hdr;
+ end = hdr + alc_len;
+ ctx = (yyjson_mut_write_ctx *)(void *)end;
+
+doc_begin:
+ val = constcast(yyjson_mut_val *)root;
+ val_type = unsafe_yyjson_get_type(val);
+ ctn_obj = (val_type == YYJSON_TYPE_OBJ);
+ ctn_len = unsafe_yyjson_get_len(val) << (u8)ctn_obj;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ *cur++ = '\n';
+ ctn = val;
+ val = (yyjson_mut_val *)val->uni.ptr; /* tail */
+ val = ctn_obj ? val->next->next : val->next;
+ level = 1;
+
+val_begin:
+ val_type = unsafe_yyjson_get_type(val);
+ if (val_type == YYJSON_TYPE_STR) {
+ is_key = (bool)((u8)ctn_obj & (u8)~ctn_len);
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len * 6 + 16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ if (likely(cpy) && unsafe_yyjson_get_subtype(val)) {
+ cur = write_string_noesc(cur, str_ptr, str_len);
+ } else {
+ cur = write_string(cur, esc, inv, str_ptr, str_len, enc_table);
+ if (unlikely(!cur)) goto fail_str;
+ }
+ *cur++ = is_key ? ':' : ',';
+ *cur++ = is_key ? ' ' : '\n';
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NUM) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ incr_len(32 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ cur = write_number(cur, (yyjson_val *)val, flg);
+ if (unlikely(!cur)) goto fail_num;
+ *cur++ = ',';
+ *cur++ = '\n';
+ goto val_end;
+ }
+ if ((val_type & (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) ==
+ (YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ)) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ ctn_len_tmp = unsafe_yyjson_get_len(val);
+ ctn_obj_tmp = (val_type == YYJSON_TYPE_OBJ);
+ if (unlikely(ctn_len_tmp == 0)) {
+ /* write empty container */
+ incr_len(16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ *cur++ = (u8)('[' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = (u8)(']' | ((u8)ctn_obj_tmp << 5));
+ *cur++ = ',';
+ *cur++ = '\n';
+ goto val_end;
+ } else {
+ /* push context, setup new container */
+ incr_len(32 + (no_indent ? 0 : level * 4));
+ yyjson_mut_write_ctx_set(--ctx, ctn, ctn_len, ctn_obj);
+ ctn_len = ctn_len_tmp << (u8)ctn_obj_tmp;
+ ctn_obj = ctn_obj_tmp;
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ level++;
+ *cur++ = (u8)('[' | ((u8)ctn_obj << 5));
+ *cur++ = '\n';
+ ctn = val;
+ val = (yyjson_mut_val *)ctn->uni.ptr; /* tail */
+ val = ctn_obj ? val->next->next : val->next;
+ goto val_begin;
+ }
+ }
+ if (val_type == YYJSON_TYPE_BOOL) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ incr_len(16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ cur = write_bool(cur, unsafe_yyjson_get_bool(val));
+ cur += 2;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_NULL) {
+ no_indent = (bool)((u8)ctn_obj & (u8)ctn_len);
+ incr_len(16 + (no_indent ? 0 : level * 4));
+ cur = write_indent(cur, no_indent ? 0 : level, spaces);
+ cur = write_null(cur);
+ cur += 2;
+ goto val_end;
+ }
+ if (val_type == YYJSON_TYPE_RAW) {
+ str_len = unsafe_yyjson_get_len(val);
+ str_ptr = (const u8 *)unsafe_yyjson_get_str(val);
+ check_str_len(str_len);
+ incr_len(str_len + 3);
+ cur = write_raw(cur, str_ptr, str_len);
+ *cur++ = ',';
+ *cur++ = '\n';
+ goto val_end;
+ }
+ goto fail_type;
+
+val_end:
+ ctn_len--;
+ if (unlikely(ctn_len == 0)) goto ctn_end;
+ val = val->next;
+ goto val_begin;
+
+ctn_end:
+ cur -= 2;
+ *cur++ = '\n';
+ incr_len(level * 4);
+ cur = write_indent(cur, --level, spaces);
+ *cur++ = (u8)(']' | ((u8)ctn_obj << 5));
+ if (unlikely((u8 *)ctx >= end)) goto doc_end;
+ val = ctn->next;
+ yyjson_mut_write_ctx_get(ctx++, &ctn, &ctn_len, &ctn_obj);
+ ctn_len--;
+ *cur++ = ',';
+ *cur++ = '\n';
+ if (likely(ctn_len > 0)) {
+ goto val_begin;
+ } else {
+ goto ctn_end;
+ }
+
+doc_end:
+ if (newline) {
+ incr_len(2);
+ *cur++ = '\n';
+ }
+ *cur = '\0';
+ *dat_len = (usize)(cur - hdr);
+ err->code = YYJSON_WRITE_SUCCESS;
+ err->msg = "success";
+ return hdr;
+
+fail_alloc:
+ return_err(MEMORY_ALLOCATION, "memory allocation failed");
+fail_type:
+ return_err(INVALID_VALUE_TYPE, "invalid JSON value type");
+fail_num:
+ return_err(NAN_OR_INF, "nan or inf number is not allowed");
+fail_str:
+ return_err(INVALID_STRING, "invalid utf-8 encoding in string");
+
+#undef return_err
+#undef incr_len
+#undef check_str_len
+}
+
+static char *yyjson_mut_write_opts_impl(const yyjson_mut_val *val,
+ usize estimated_val_num,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ usize *dat_len,
+ yyjson_write_err *err) {
+ yyjson_write_err dummy_err;
+ usize dummy_dat_len;
+ yyjson_alc alc = alc_ptr ? *alc_ptr : YYJSON_DEFAULT_ALC;
+ yyjson_mut_val *root = constcast(yyjson_mut_val *)val;
+
+ err = err ? err : &dummy_err;
+ dat_len = dat_len ? dat_len : &dummy_dat_len;
+
+ if (unlikely(!root)) {
+ *dat_len = 0;
+ err->msg = "input JSON is NULL";
+ err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ if (!unsafe_yyjson_is_ctn(root) || unsafe_yyjson_get_len(root) == 0) {
+ return (char *)yyjson_mut_write_single(root, flg, alc, dat_len, err);
+ } else if (flg & (YYJSON_WRITE_PRETTY | YYJSON_WRITE_PRETTY_TWO_SPACES)) {
+ return (char *)yyjson_mut_write_pretty(root, estimated_val_num,
+ flg, alc, dat_len, err);
+ } else {
+ return (char *)yyjson_mut_write_minify(root, estimated_val_num,
+ flg, alc, dat_len, err);
+ }
+}
+
+char *yyjson_mut_val_write_opts(const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ usize *dat_len,
+ yyjson_write_err *err) {
+ return yyjson_mut_write_opts_impl(val, 0, flg, alc_ptr, dat_len, err);
+}
+
+char *yyjson_mut_write_opts(const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ usize *dat_len,
+ yyjson_write_err *err) {
+ yyjson_mut_val *root;
+ usize estimated_val_num;
+ if (likely(doc)) {
+ root = doc->root;
+ estimated_val_num = yyjson_mut_doc_estimated_val_num(doc);
+ } else {
+ root = NULL;
+ estimated_val_num = 0;
+ }
+ return yyjson_mut_write_opts_impl(root, estimated_val_num,
+ flg, alc_ptr, dat_len, err);
+}
+
+bool yyjson_mut_val_write_file(const char *path,
+ const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_write_err dummy_err;
+ u8 *dat;
+ usize dat_len = 0;
+ yyjson_mut_val *root = constcast(yyjson_mut_val *)val;
+ bool suc;
+
+ alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC;
+ err = err ? err : &dummy_err;
+ if (unlikely(!path || !*path)) {
+ err->msg = "input path is invalid";
+ err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER;
+ return false;
+ }
+
+ dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err);
+ if (unlikely(!dat)) return false;
+ suc = write_dat_to_file(path, dat, dat_len, err);
+ alc_ptr->free(alc_ptr->ctx, dat);
+ return suc;
+}
+
+bool yyjson_mut_val_write_fp(FILE *fp,
+ const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_write_err dummy_err;
+ u8 *dat;
+ usize dat_len = 0;
+ yyjson_mut_val *root = constcast(yyjson_mut_val *)val;
+ bool suc;
+
+ alc_ptr = alc_ptr ? alc_ptr : &YYJSON_DEFAULT_ALC;
+ err = err ? err : &dummy_err;
+ if (unlikely(!fp)) {
+ err->msg = "input fp is invalid";
+ err->code = YYJSON_WRITE_ERROR_INVALID_PARAMETER;
+ return false;
+ }
+
+ dat = (u8 *)yyjson_mut_val_write_opts(root, flg, alc_ptr, &dat_len, err);
+ if (unlikely(!dat)) return false;
+ suc = write_dat_to_fp(fp, dat, dat_len, err);
+ alc_ptr->free(alc_ptr->ctx, dat);
+ return suc;
+}
+
+bool yyjson_mut_write_file(const char *path,
+ const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_mut_val *root = doc ? doc->root : NULL;
+ return yyjson_mut_val_write_file(path, root, flg, alc_ptr, err);
+}
+
+bool yyjson_mut_write_fp(FILE *fp,
+ const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc_ptr,
+ yyjson_write_err *err) {
+ yyjson_mut_val *root = doc ? doc->root : NULL;
+ return yyjson_mut_val_write_fp(fp, root, flg, alc_ptr, err);
+}
+
+#endif /* YYJSON_DISABLE_WRITER */
diff --git a/vendor/yyjson/yyjson.h b/vendor/yyjson/yyjson.h
new file mode 100644
index 000000000..88cec2b09
--- /dev/null
+++ b/vendor/yyjson/yyjson.h
@@ -0,0 +1,7942 @@
+/*==============================================================================
+ Copyright (c) 2020 YaoYuan <ibireme@gmail.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ *============================================================================*/
+
+/**
+ @file yyjson.h
+ @date 2019-03-09
+ @author YaoYuan
+ */
+
+#ifndef YYJSON_H
+#define YYJSON_H
+
+
+
+/*==============================================================================
+ * Header Files
+ *============================================================================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <float.h>
+
+
+
+/*==============================================================================
+ * Compile-time Options
+ *============================================================================*/
+
+/*
+ Define as 1 to disable JSON reader if JSON parsing is not required.
+
+ This will disable these functions at compile-time:
+ - yyjson_read()
+ - yyjson_read_opts()
+ - yyjson_read_file()
+ - yyjson_read_number()
+ - yyjson_mut_read_number()
+
+ This will reduce the binary size by about 60%.
+ */
+#ifndef YYJSON_DISABLE_READER
+#endif
+
+/*
+ Define as 1 to disable JSON writer if JSON serialization is not required.
+
+ This will disable these functions at compile-time:
+ - yyjson_write()
+ - yyjson_write_file()
+ - yyjson_write_opts()
+ - yyjson_val_write()
+ - yyjson_val_write_file()
+ - yyjson_val_write_opts()
+ - yyjson_mut_write()
+ - yyjson_mut_write_file()
+ - yyjson_mut_write_opts()
+ - yyjson_mut_val_write()
+ - yyjson_mut_val_write_file()
+ - yyjson_mut_val_write_opts()
+
+ This will reduce the binary size by about 30%.
+ */
+#ifndef YYJSON_DISABLE_WRITER
+#endif
+
+/*
+ Define as 1 to disable JSON Pointer, JSON Patch and JSON Merge Patch supports.
+
+ This will disable these functions at compile-time:
+ - yyjson_ptr_xxx()
+ - yyjson_mut_ptr_xxx()
+ - yyjson_doc_ptr_xxx()
+ - yyjson_mut_doc_ptr_xxx()
+ - yyjson_patch()
+ - yyjson_mut_patch()
+ - yyjson_merge_patch()
+ - yyjson_mut_merge_patch()
+ */
+#ifndef YYJSON_DISABLE_UTILS
+#endif
+
+/*
+ Define as 1 to disable the fast floating-point number conversion in yyjson,
+ and use libc's `strtod/snprintf` instead.
+
+ This will reduce the binary size by about 30%, but significantly slow down the
+ floating-point read/write speed.
+ */
+#ifndef YYJSON_DISABLE_FAST_FP_CONV
+#endif
+
+/*
+ Define as 1 to disable non-standard JSON support at compile-time:
+ - Reading and writing inf/nan literal, such as `NaN`, `-Infinity`.
+ - Single line and multiple line comments.
+ - Single trailing comma at the end of an object or array.
+ - Invalid unicode in string value.
+
+ This will also invalidate these run-time options:
+ - YYJSON_READ_ALLOW_INF_AND_NAN
+ - YYJSON_READ_ALLOW_COMMENTS
+ - YYJSON_READ_ALLOW_TRAILING_COMMAS
+ - YYJSON_READ_ALLOW_INVALID_UNICODE
+ - YYJSON_WRITE_ALLOW_INF_AND_NAN
+ - YYJSON_WRITE_ALLOW_INVALID_UNICODE
+
+ This will reduce the binary size by about 10%, and speed up the reading and
+ writing speed by about 2% to 6%.
+ */
+#ifndef YYJSON_DISABLE_NON_STANDARD
+#endif
+
+/*
+ Define as 1 to disable UTF-8 validation at compile time.
+
+ If all input strings are guaranteed to be valid UTF-8 encoding (for example,
+ some language's String object has already validated the encoding), using this
+ flag can avoid redundant UTF-8 validation in yyjson.
+
+ This flag can speed up the reading and writing speed of non-ASCII encoded
+ strings by about 3% to 7%.
+
+ Note: If this flag is used while passing in illegal UTF-8 strings, the
+ following errors may occur:
+ - Escaped characters may be ignored when parsing JSON strings.
+ - Ending quotes may be ignored when parsing JSON strings, causing the string
+ to be concatenated to the next value.
+ - When accessing `yyjson_mut_val` for serialization, the string ending may be
+ accessed out of bounds, causing a segmentation fault.
+ */
+#ifndef YYJSON_DISABLE_UTF8_VALIDATION
+#endif
+
+/*
+ Define as 1 to indicate that the target architecture does not support unaligned
+ memory access. Please refer to the comments in the C file for details.
+ */
+#ifndef YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS
+#endif
+
+/* Define as 1 to export symbols when building this library as Windows DLL. */
+#ifndef YYJSON_EXPORTS
+#endif
+
+/* Define as 1 to import symbols when using this library as Windows DLL. */
+#ifndef YYJSON_IMPORTS
+#endif
+
+/* Define as 1 to include <stdint.h> for compiler which doesn't support C99. */
+#ifndef YYJSON_HAS_STDINT_H
+#endif
+
+/* Define as 1 to include <stdbool.h> for compiler which doesn't support C99. */
+#ifndef YYJSON_HAS_STDBOOL_H
+#endif
+
+
+
+/*==============================================================================
+ * Compiler Macros
+ *============================================================================*/
+
+/** compiler version (MSVC) */
+#ifdef _MSC_VER
+# define YYJSON_MSC_VER _MSC_VER
+#else
+# define YYJSON_MSC_VER 0
+#endif
+
+/** compiler version (GCC) */
+#ifdef __GNUC__
+# define YYJSON_GCC_VER __GNUC__
+# if defined(__GNUC_PATCHLEVEL__)
+# define yyjson_gcc_available(major, minor, patch) \
+ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \
+ >= (major * 10000 + minor * 100 + patch))
+# else
+# define yyjson_gcc_available(major, minor, patch) \
+ ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100) \
+ >= (major * 10000 + minor * 100 + patch))
+# endif
+#else
+# define YYJSON_GCC_VER 0
+# define yyjson_gcc_available(major, minor, patch) 0
+#endif
+
+/** real gcc check */
+#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__ICC) && \
+ defined(__GNUC__)
+# define YYJSON_IS_REAL_GCC 1
+#else
+# define YYJSON_IS_REAL_GCC 0
+#endif
+
+/** C version (STDC) */
+#if defined(__STDC__) && (__STDC__ >= 1) && defined(__STDC_VERSION__)
+# define YYJSON_STDC_VER __STDC_VERSION__
+#else
+# define YYJSON_STDC_VER 0
+#endif
+
+/** C++ version */
+#if defined(__cplusplus)
+# define YYJSON_CPP_VER __cplusplus
+#else
+# define YYJSON_CPP_VER 0
+#endif
+
+/** compiler builtin check (since gcc 10.0, clang 2.6, icc 2021) */
+#ifndef yyjson_has_builtin
+# ifdef __has_builtin
+# define yyjson_has_builtin(x) __has_builtin(x)
+# else
+# define yyjson_has_builtin(x) 0
+# endif
+#endif
+
+/** compiler attribute check (since gcc 5.0, clang 2.9, icc 17) */
+#ifndef yyjson_has_attribute
+# ifdef __has_attribute
+# define yyjson_has_attribute(x) __has_attribute(x)
+# else
+# define yyjson_has_attribute(x) 0
+# endif
+#endif
+
+/** compiler feature check (since clang 2.6, icc 17) */
+#ifndef yyjson_has_feature
+# ifdef __has_feature
+# define yyjson_has_feature(x) __has_feature(x)
+# else
+# define yyjson_has_feature(x) 0
+# endif
+#endif
+
+/** include check (since gcc 5.0, clang 2.7, icc 16, msvc 2017 15.3) */
+#ifndef yyjson_has_include
+# ifdef __has_include
+# define yyjson_has_include(x) __has_include(x)
+# else
+# define yyjson_has_include(x) 0
+# endif
+#endif
+
+/** inline for compiler */
+#ifndef yyjson_inline
+# if YYJSON_MSC_VER >= 1200
+# define yyjson_inline __forceinline
+# elif defined(_MSC_VER)
+# define yyjson_inline __inline
+# elif yyjson_has_attribute(always_inline) || YYJSON_GCC_VER >= 4
+# define yyjson_inline __inline__ __attribute__((always_inline))
+# elif defined(__clang__) || defined(__GNUC__)
+# define yyjson_inline __inline__
+# elif defined(__cplusplus) || YYJSON_STDC_VER >= 199901L
+# define yyjson_inline inline
+# else
+# define yyjson_inline
+# endif
+#endif
+
+/** noinline for compiler */
+#ifndef yyjson_noinline
+# if YYJSON_MSC_VER >= 1400
+# define yyjson_noinline __declspec(noinline)
+# elif yyjson_has_attribute(noinline) || YYJSON_GCC_VER >= 4
+# define yyjson_noinline __attribute__((noinline))
+# else
+# define yyjson_noinline
+# endif
+#endif
+
+/** align for compiler */
+#ifndef yyjson_align
+# if YYJSON_MSC_VER >= 1300
+# define yyjson_align(x) __declspec(align(x))
+# elif yyjson_has_attribute(aligned) || defined(__GNUC__)
+# define yyjson_align(x) __attribute__((aligned(x)))
+# elif YYJSON_CPP_VER >= 201103L
+# define yyjson_align(x) alignas(x)
+# else
+# define yyjson_align(x)
+# endif
+#endif
+
+/** likely for compiler */
+#ifndef yyjson_likely
+# if yyjson_has_builtin(__builtin_expect) || \
+ (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5)
+# define yyjson_likely(expr) __builtin_expect(!!(expr), 1)
+# else
+# define yyjson_likely(expr) (expr)
+# endif
+#endif
+
+/** unlikely for compiler */
+#ifndef yyjson_unlikely
+# if yyjson_has_builtin(__builtin_expect) || \
+ (YYJSON_GCC_VER >= 4 && YYJSON_GCC_VER != 5)
+# define yyjson_unlikely(expr) __builtin_expect(!!(expr), 0)
+# else
+# define yyjson_unlikely(expr) (expr)
+# endif
+#endif
+
+/** compile-time constant check for compiler */
+#ifndef yyjson_constant_p
+# if yyjson_has_builtin(__builtin_constant_p) || (YYJSON_GCC_VER >= 3)
+# define YYJSON_HAS_CONSTANT_P 1
+# define yyjson_constant_p(value) __builtin_constant_p(value)
+# else
+# define YYJSON_HAS_CONSTANT_P 0
+# define yyjson_constant_p(value) 0
+# endif
+#endif
+
+/** deprecate warning */
+#ifndef yyjson_deprecated
+# if YYJSON_MSC_VER >= 1400
+# define yyjson_deprecated(msg) __declspec(deprecated(msg))
+# elif yyjson_has_feature(attribute_deprecated_with_message) || \
+ (YYJSON_GCC_VER > 4 || (YYJSON_GCC_VER == 4 && __GNUC_MINOR__ >= 5))
+# define yyjson_deprecated(msg) __attribute__((deprecated(msg)))
+# elif YYJSON_GCC_VER >= 3
+# define yyjson_deprecated(msg) __attribute__((deprecated))
+# else
+# define yyjson_deprecated(msg)
+# endif
+#endif
+
+/** function export */
+#ifndef yyjson_api
+# if defined(_WIN32)
+# if defined(YYJSON_EXPORTS) && YYJSON_EXPORTS
+# define yyjson_api __declspec(dllexport)
+# elif defined(YYJSON_IMPORTS) && YYJSON_IMPORTS
+# define yyjson_api __declspec(dllimport)
+# else
+# define yyjson_api
+# endif
+# elif yyjson_has_attribute(visibility) || YYJSON_GCC_VER >= 4
+# define yyjson_api __attribute__((visibility("default")))
+# else
+# define yyjson_api
+# endif
+#endif
+
+/** inline function export */
+#ifndef yyjson_api_inline
+# define yyjson_api_inline static yyjson_inline
+#endif
+
+/** stdint (C89 compatible) */
+#if (defined(YYJSON_HAS_STDINT_H) && YYJSON_HAS_STDINT_H) || \
+ YYJSON_MSC_VER >= 1600 || YYJSON_STDC_VER >= 199901L || \
+ defined(_STDINT_H) || defined(_STDINT_H_) || \
+ defined(__CLANG_STDINT_H) || defined(_STDINT_H_INCLUDED) || \
+ yyjson_has_include(<stdint.h>)
+# include <stdint.h>
+#elif defined(_MSC_VER)
+# if _MSC_VER < 1300
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+ typedef signed __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# else
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef signed __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# endif
+#else
+# if UCHAR_MAX == 0xFFU
+ typedef signed char int8_t;
+ typedef unsigned char uint8_t;
+# else
+# error cannot find 8-bit integer type
+# endif
+# if USHRT_MAX == 0xFFFFU
+ typedef unsigned short uint16_t;
+ typedef signed short int16_t;
+# elif UINT_MAX == 0xFFFFU
+ typedef unsigned int uint16_t;
+ typedef signed int int16_t;
+# else
+# error cannot find 16-bit integer type
+# endif
+# if UINT_MAX == 0xFFFFFFFFUL
+ typedef unsigned int uint32_t;
+ typedef signed int int32_t;
+# elif ULONG_MAX == 0xFFFFFFFFUL
+ typedef unsigned long uint32_t;
+ typedef signed long int32_t;
+# elif USHRT_MAX == 0xFFFFFFFFUL
+ typedef unsigned short uint32_t;
+ typedef signed short int32_t;
+# else
+# error cannot find 32-bit integer type
+# endif
+# if defined(__INT64_TYPE__) && defined(__UINT64_TYPE__)
+ typedef __INT64_TYPE__ int64_t;
+ typedef __UINT64_TYPE__ uint64_t;
+# elif defined(__GNUC__) || defined(__clang__)
+# if !defined(_SYS_TYPES_H) && !defined(__int8_t_defined)
+ __extension__ typedef long long int64_t;
+# endif
+ __extension__ typedef unsigned long long uint64_t;
+# elif defined(_LONG_LONG) || defined(__MWERKS__) || defined(_CRAYC) || \
+ defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ typedef long long int64_t;
+ typedef unsigned long long uint64_t;
+# elif (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || \
+ defined(__WATCOM_INT64__) || defined (__alpha) || defined (__DECC)
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# else
+# error cannot find 64-bit integer type
+# endif
+#endif
+
+/** stdbool (C89 compatible) */
+#if (defined(YYJSON_HAS_STDBOOL_H) && YYJSON_HAS_STDBOOL_H) || \
+ (yyjson_has_include(<stdbool.h>) && !defined(__STRICT_ANSI__)) || \
+ YYJSON_MSC_VER >= 1800 || YYJSON_STDC_VER >= 199901L
+# include <stdbool.h>
+#elif !defined(__bool_true_false_are_defined)
+# define __bool_true_false_are_defined 1
+# if defined(__cplusplus)
+# if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+# define _Bool bool
+# if __cplusplus < 201103L
+# define bool bool
+# define false false
+# define true true
+# endif
+# endif
+# else
+# define bool unsigned char
+# define true 1
+# define false 0
+# endif
+#endif
+
+/** char bit check */
+#if defined(CHAR_BIT)
+# if CHAR_BIT != 8
+# error non 8-bit char is not supported
+# endif
+#endif
+
+/**
+ Microsoft Visual C++ 6.0 doesn't support converting number from u64 to f64:
+ error C2520: conversion from unsigned __int64 to double not implemented.
+ */
+#ifndef YYJSON_U64_TO_F64_NO_IMPL
+# if (0 < YYJSON_MSC_VER) && (YYJSON_MSC_VER <= 1200)
+# define YYJSON_U64_TO_F64_NO_IMPL 1
+# else
+# define YYJSON_U64_TO_F64_NO_IMPL 0
+# endif
+#endif
+
+
+
+/*==============================================================================
+ * Compile Hint Begin
+ *============================================================================*/
+
+/* extern "C" begin */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* warning suppress begin */
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunused-function"
+# pragma clang diagnostic ignored "-Wunused-parameter"
+#elif defined(__GNUC__)
+# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+# pragma GCC diagnostic push
+# endif
+# pragma GCC diagnostic ignored "-Wunused-function"
+# pragma GCC diagnostic ignored "-Wunused-parameter"
+#elif defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable:4800) /* 'int': forcing value to 'true' or 'false' */
+#endif
+
+
+
+/*==============================================================================
+ * Version
+ *============================================================================*/
+
+/** The major version of yyjson. */
+#define YYJSON_VERSION_MAJOR 0
+
+/** The minor version of yyjson. */
+#define YYJSON_VERSION_MINOR 10
+
+/** The patch version of yyjson. */
+#define YYJSON_VERSION_PATCH 0
+
+/** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */
+#define YYJSON_VERSION_HEX 0x000A00
+
+/** The version string of yyjson. */
+#define YYJSON_VERSION_STRING "0.10.0"
+
+/** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */
+yyjson_api uint32_t yyjson_version(void);
+
+
+
+/*==============================================================================
+ * JSON Types
+ *============================================================================*/
+
+/** Type of a JSON value (3 bit). */
+typedef uint8_t yyjson_type;
+/** No type, invalid. */
+#define YYJSON_TYPE_NONE ((uint8_t)0) /* _____000 */
+/** Raw string type, no subtype. */
+#define YYJSON_TYPE_RAW ((uint8_t)1) /* _____001 */
+/** Null type: `null` literal, no subtype. */
+#define YYJSON_TYPE_NULL ((uint8_t)2) /* _____010 */
+/** Boolean type, subtype: TRUE, FALSE. */
+#define YYJSON_TYPE_BOOL ((uint8_t)3) /* _____011 */
+/** Number type, subtype: UINT, SINT, REAL. */
+#define YYJSON_TYPE_NUM ((uint8_t)4) /* _____100 */
+/** String type, subtype: NONE, NOESC. */
+#define YYJSON_TYPE_STR ((uint8_t)5) /* _____101 */
+/** Array type, no subtype. */
+#define YYJSON_TYPE_ARR ((uint8_t)6) /* _____110 */
+/** Object type, no subtype. */
+#define YYJSON_TYPE_OBJ ((uint8_t)7) /* _____111 */
+
+/** Subtype of a JSON value (2 bit). */
+typedef uint8_t yyjson_subtype;
+/** No subtype. */
+#define YYJSON_SUBTYPE_NONE ((uint8_t)(0 << 3)) /* ___00___ */
+/** False subtype: `false` literal. */
+#define YYJSON_SUBTYPE_FALSE ((uint8_t)(0 << 3)) /* ___00___ */
+/** True subtype: `true` literal. */
+#define YYJSON_SUBTYPE_TRUE ((uint8_t)(1 << 3)) /* ___01___ */
+/** Unsigned integer subtype: `uint64_t`. */
+#define YYJSON_SUBTYPE_UINT ((uint8_t)(0 << 3)) /* ___00___ */
+/** Signed integer subtype: `int64_t`. */
+#define YYJSON_SUBTYPE_SINT ((uint8_t)(1 << 3)) /* ___01___ */
+/** Real number subtype: `double`. */
+#define YYJSON_SUBTYPE_REAL ((uint8_t)(2 << 3)) /* ___10___ */
+/** String that do not need to be escaped for writing (internal use). */
+#define YYJSON_SUBTYPE_NOESC ((uint8_t)(1 << 3)) /* ___01___ */
+
+/** The mask used to extract the type of a JSON value. */
+#define YYJSON_TYPE_MASK ((uint8_t)0x07) /* _____111 */
+/** The number of bits used by the type. */
+#define YYJSON_TYPE_BIT ((uint8_t)3)
+/** The mask used to extract the subtype of a JSON value. */
+#define YYJSON_SUBTYPE_MASK ((uint8_t)0x18) /* ___11___ */
+/** The number of bits used by the subtype. */
+#define YYJSON_SUBTYPE_BIT ((uint8_t)2)
+/** The mask used to extract the reserved bits of a JSON value. */
+#define YYJSON_RESERVED_MASK ((uint8_t)0xE0) /* 111_____ */
+/** The number of reserved bits. */
+#define YYJSON_RESERVED_BIT ((uint8_t)3)
+/** The mask used to extract the tag of a JSON value. */
+#define YYJSON_TAG_MASK ((uint8_t)0xFF) /* 11111111 */
+/** The number of bits used by the tag. */
+#define YYJSON_TAG_BIT ((uint8_t)8)
+
+/** Padding size for JSON reader. */
+#define YYJSON_PADDING_SIZE 4
+
+
+
+/*==============================================================================
+ * Allocator
+ *============================================================================*/
+
+/**
+ A memory allocator.
+
+ Typically you don't need to use it, unless you want to customize your own
+ memory allocator.
+ */
+typedef struct yyjson_alc {
+ /** Same as libc's malloc(size), should not be NULL. */
+ void *(*malloc)(void *ctx, size_t size);
+ /** Same as libc's realloc(ptr, size), should not be NULL. */
+ void *(*realloc)(void *ctx, void *ptr, size_t old_size, size_t size);
+ /** Same as libc's free(ptr), should not be NULL. */
+ void (*free)(void *ctx, void *ptr);
+ /** A context for malloc/realloc/free, can be NULL. */
+ void *ctx;
+} yyjson_alc;
+
+/**
+ A pool allocator uses fixed length pre-allocated memory.
+
+ This allocator may be used to avoid malloc/realloc calls. The pre-allocated
+ memory should be held by the caller. The maximum amount of memory required to
+ read a JSON can be calculated using the `yyjson_read_max_memory_usage()`
+ function, but the amount of memory required to write a JSON cannot be directly
+ calculated.
+
+ This is not a general-purpose allocator. It is designed to handle a single JSON
+ data at a time. If it is used for overly complex memory tasks, such as parsing
+ multiple JSON documents using the same allocator but releasing only a few of
+ them, it may cause memory fragmentation, resulting in performance degradation
+ and memory waste.
+
+ @param alc The allocator to be initialized.
+ If this parameter is NULL, the function will fail and return false.
+ If `buf` or `size` is invalid, this will be set to an empty allocator.
+ @param buf The buffer memory for this allocator.
+ If this parameter is NULL, the function will fail and return false.
+ @param size The size of `buf`, in bytes.
+ If this parameter is less than 8 words (32/64 bytes on 32/64-bit OS), the
+ function will fail and return false.
+ @return true if the `alc` has been successfully initialized.
+
+ @par Example
+ @code
+ // parse JSON with stack memory
+ char buf[1024];
+ yyjson_alc alc;
+ yyjson_alc_pool_init(&alc, buf, 1024);
+
+ const char *json = "{\"name\":\"Helvetica\",\"size\":16}"
+ yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL);
+ // the memory of `doc` is on the stack
+ @endcode
+
+ @warning This Allocator is not thread-safe.
+ */
+yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size);
+
+/**
+ A dynamic allocator.
+
+ This allocator has a similar usage to the pool allocator above. However, when
+ there is not enough memory, this allocator will dynamically request more memory
+ using libc's `malloc` function, and frees it all at once when it is destroyed.
+
+ @return A new dynamic allocator, or NULL if memory allocation failed.
+ @note The returned value should be freed with `yyjson_alc_dyn_free()`.
+
+ @warning This Allocator is not thread-safe.
+ */
+yyjson_api yyjson_alc *yyjson_alc_dyn_new(void);
+
+/**
+ Free a dynamic allocator which is created by `yyjson_alc_dyn_new()`.
+ @param alc The dynamic allocator to be destroyed.
+ */
+yyjson_api void yyjson_alc_dyn_free(yyjson_alc *alc);
+
+
+
+/*==============================================================================
+ * JSON Structure
+ *============================================================================*/
+
+/**
+ An immutable document for reading JSON.
+ This document holds memory for all its JSON values and strings. When it is no
+ longer used, the user should call `yyjson_doc_free()` to free its memory.
+ */
+typedef struct yyjson_doc yyjson_doc;
+
+/**
+ An immutable value for reading JSON.
+ A JSON Value has the same lifetime as its document. The memory is held by its
+ document and and cannot be freed alone.
+ */
+typedef struct yyjson_val yyjson_val;
+
+/**
+ A mutable document for building JSON.
+ This document holds memory for all its JSON values and strings. When it is no
+ longer used, the user should call `yyjson_mut_doc_free()` to free its memory.
+ */
+typedef struct yyjson_mut_doc yyjson_mut_doc;
+
+/**
+ A mutable value for building JSON.
+ A JSON Value has the same lifetime as its document. The memory is held by its
+ document and and cannot be freed alone.
+ */
+typedef struct yyjson_mut_val yyjson_mut_val;
+
+
+
+/*==============================================================================
+ * JSON Reader API
+ *============================================================================*/
+
+/** Run-time options for JSON reader. */
+typedef uint32_t yyjson_read_flag;
+
+/** Default option (RFC 8259 compliant):
+ - Read positive integer as uint64_t.
+ - Read negative integer as int64_t.
+ - Read floating-point number as double with round-to-nearest mode.
+ - Read integer which cannot fit in uint64_t or int64_t as double.
+ - Report error if double number is infinity.
+ - Report error if string contains invalid UTF-8 character or BOM.
+ - Report error on trailing commas, comments, inf and nan literals. */
+static const yyjson_read_flag YYJSON_READ_NOFLAG = 0;
+
+/** Read the input data in-situ.
+ This option allows the reader to modify and use input data to store string
+ values, which can increase reading speed slightly.
+ The caller should hold the input data before free the document.
+ The input data must be padded by at least `YYJSON_PADDING_SIZE` bytes.
+ For example: `[1,2]` should be `[1,2]\0\0\0\0`, input length should be 5. */
+static const yyjson_read_flag YYJSON_READ_INSITU = 1 << 0;
+
+/** Stop when done instead of issuing an error if there's additional content
+ after a JSON document. This option may be used to parse small pieces of JSON
+ in larger data, such as `NDJSON`. */
+static const yyjson_read_flag YYJSON_READ_STOP_WHEN_DONE = 1 << 1;
+
+/** Allow single trailing comma at the end of an object or array,
+ such as `[1,2,3,]`, `{"a":1,"b":2,}` (non-standard). */
+static const yyjson_read_flag YYJSON_READ_ALLOW_TRAILING_COMMAS = 1 << 2;
+
+/** Allow C-style single line and multiple line comments (non-standard). */
+static const yyjson_read_flag YYJSON_READ_ALLOW_COMMENTS = 1 << 3;
+
+/** Allow inf/nan number and literal, case-insensitive,
+ such as 1e999, NaN, inf, -Infinity (non-standard). */
+static const yyjson_read_flag YYJSON_READ_ALLOW_INF_AND_NAN = 1 << 4;
+
+/** Read all numbers as raw strings (value with `YYJSON_TYPE_RAW` type),
+ inf/nan literal is also read as raw with `ALLOW_INF_AND_NAN` flag. */
+static const yyjson_read_flag YYJSON_READ_NUMBER_AS_RAW = 1 << 5;
+
+/** Allow reading invalid unicode when parsing string values (non-standard).
+ Invalid characters will be allowed to appear in the string values, but
+ invalid escape sequences will still be reported as errors.
+ This flag does not affect the performance of correctly encoded strings.
+
+ @warning Strings in JSON values may contain incorrect encoding when this
+ option is used, you need to handle these strings carefully to avoid security
+ risks. */
+static const yyjson_read_flag YYJSON_READ_ALLOW_INVALID_UNICODE = 1 << 6;
+
+/** Read big numbers as raw strings. These big numbers include integers that
+ cannot be represented by `int64_t` and `uint64_t`, and floating-point
+ numbers that cannot be represented by finite `double`.
+ The flag will be overridden by `YYJSON_READ_NUMBER_AS_RAW` flag. */
+static const yyjson_read_flag YYJSON_READ_BIGNUM_AS_RAW = 1 << 7;
+
+
+
+/** Result code for JSON reader. */
+typedef uint32_t yyjson_read_code;
+
+/** Success, no error. */
+static const yyjson_read_code YYJSON_READ_SUCCESS = 0;
+
+/** Invalid parameter, such as NULL input string or 0 input length. */
+static const yyjson_read_code YYJSON_READ_ERROR_INVALID_PARAMETER = 1;
+
+/** Memory allocation failure occurs. */
+static const yyjson_read_code YYJSON_READ_ERROR_MEMORY_ALLOCATION = 2;
+
+/** Input JSON string is empty. */
+static const yyjson_read_code YYJSON_READ_ERROR_EMPTY_CONTENT = 3;
+
+/** Unexpected content after document, such as `[123]abc`. */
+static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CONTENT = 4;
+
+/** Unexpected ending, such as `[123`. */
+static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_END = 5;
+
+/** Unexpected character inside the document, such as `[abc]`. */
+static const yyjson_read_code YYJSON_READ_ERROR_UNEXPECTED_CHARACTER = 6;
+
+/** Invalid JSON structure, such as `[1,]`. */
+static const yyjson_read_code YYJSON_READ_ERROR_JSON_STRUCTURE = 7;
+
+/** Invalid comment, such as unclosed multi-line comment. */
+static const yyjson_read_code YYJSON_READ_ERROR_INVALID_COMMENT = 8;
+
+/** Invalid number, such as `123.e12`, `000`. */
+static const yyjson_read_code YYJSON_READ_ERROR_INVALID_NUMBER = 9;
+
+/** Invalid string, such as invalid escaped character inside a string. */
+static const yyjson_read_code YYJSON_READ_ERROR_INVALID_STRING = 10;
+
+/** Invalid JSON literal, such as `truu`. */
+static const yyjson_read_code YYJSON_READ_ERROR_LITERAL = 11;
+
+/** Failed to open a file. */
+static const yyjson_read_code YYJSON_READ_ERROR_FILE_OPEN = 12;
+
+/** Failed to read a file. */
+static const yyjson_read_code YYJSON_READ_ERROR_FILE_READ = 13;
+
+/** Error information for JSON reader. */
+typedef struct yyjson_read_err {
+ /** Error code, see `yyjson_read_code` for all possible values. */
+ yyjson_read_code code;
+ /** Error message, constant, no need to free (NULL if success). */
+ const char *msg;
+ /** Error byte position for input data (0 if success). */
+ size_t pos;
+} yyjson_read_err;
+
+/**
+ Locate the line and column number for a byte position in a string.
+ This can be used to get better description for error position.
+
+ @param str The input string.
+ @param len The byte length of the input string.
+ @param pos The byte position within the input string.
+ @param line A pointer to receive the line number, starting from 1.
+ @param col A pointer to receive the column number, starting from 1.
+ @param chr A pointer to receive the character index, starting from 0.
+ @return true on success, false if `str` is NULL or `pos` is out of bounds.
+ @note Line/column/character are calculated based on Unicode characters for
+ compatibility with text editors. For multi-byte UTF-8 characters,
+ the returned value may not directly correspond to the byte position.
+ */
+yyjson_api bool yyjson_locate_pos(const char *str, size_t len, size_t pos,
+ size_t *line, size_t *col, size_t *chr);
+
+
+
+/**
+ Read JSON with options.
+
+ This function is thread-safe when:
+ 1. The `dat` is not modified by other threads.
+ 2. The `alc` is thread-safe or NULL.
+
+ @param dat The JSON data (UTF-8 without BOM), null-terminator is not required.
+ If this parameter is NULL, the function will fail and return NULL.
+ The `dat` will not be modified without the flag `YYJSON_READ_INSITU`, so you
+ can pass a `const char *` string and case it to `char *` if you don't use
+ the `YYJSON_READ_INSITU` flag.
+ @param len The length of JSON data in bytes.
+ If this parameter is 0, the function will fail and return NULL.
+ @param flg The JSON read options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON reader.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON document, or NULL if an error occurs.
+ When it's no longer needed, it should be freed with `yyjson_doc_free()`.
+ */
+yyjson_api yyjson_doc *yyjson_read_opts(char *dat,
+ size_t len,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc,
+ yyjson_read_err *err);
+
+/**
+ Read a JSON file.
+
+ This function is thread-safe when:
+ 1. The file is not modified by other threads.
+ 2. The `alc` is thread-safe or NULL.
+
+ @param path The JSON file's path.
+ If this path is NULL or invalid, the function will fail and return NULL.
+ @param flg The JSON read options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON reader.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON document, or NULL if an error occurs.
+ When it's no longer needed, it should be freed with `yyjson_doc_free()`.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to read.
+ */
+yyjson_api yyjson_doc *yyjson_read_file(const char *path,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc,
+ yyjson_read_err *err);
+
+/**
+ Read JSON from a file pointer.
+
+ @param fp The file pointer.
+ The data will be read from the current position of the FILE to the end.
+ If this fp is NULL or invalid, the function will fail and return NULL.
+ @param flg The JSON read options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON reader.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON document, or NULL if an error occurs.
+ When it's no longer needed, it should be freed with `yyjson_doc_free()`.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to read.
+ */
+yyjson_api yyjson_doc *yyjson_read_fp(FILE *fp,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc,
+ yyjson_read_err *err);
+
+/**
+ Read a JSON string.
+
+ This function is thread-safe.
+
+ @param dat The JSON data (UTF-8 without BOM), null-terminator is not required.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param len The length of JSON data in bytes.
+ If this parameter is 0, the function will fail and return NULL.
+ @param flg The JSON read options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @return A new JSON document, or NULL if an error occurs.
+ When it's no longer needed, it should be freed with `yyjson_doc_free()`.
+ */
+yyjson_api_inline yyjson_doc *yyjson_read(const char *dat,
+ size_t len,
+ yyjson_read_flag flg) {
+ flg &= ~YYJSON_READ_INSITU; /* const string cannot be modified */
+ return yyjson_read_opts((char *)(void *)(size_t)(const void *)dat,
+ len, flg, NULL, NULL);
+}
+
+/**
+ Returns the size of maximum memory usage to read a JSON data.
+
+ You may use this value to avoid malloc() or calloc() call inside the reader
+ to get better performance, or read multiple JSON with one piece of memory.
+
+ @param len The length of JSON data in bytes.
+ @param flg The JSON read options.
+ @return The maximum memory size to read this JSON, or 0 if overflow.
+
+ @par Example
+ @code
+ // read multiple JSON with same pre-allocated memory
+
+ char *dat1, *dat2, *dat3; // JSON data
+ size_t len1, len2, len3; // JSON length
+ size_t max_len = MAX(len1, MAX(len2, len3));
+ yyjson_doc *doc;
+
+ // use one allocator for multiple JSON
+ size_t size = yyjson_read_max_memory_usage(max_len, 0);
+ void *buf = malloc(size);
+ yyjson_alc alc;
+ yyjson_alc_pool_init(&alc, buf, size);
+
+ // no more alloc() or realloc() call during reading
+ doc = yyjson_read_opts(dat1, len1, 0, &alc, NULL);
+ yyjson_doc_free(doc);
+ doc = yyjson_read_opts(dat2, len2, 0, &alc, NULL);
+ yyjson_doc_free(doc);
+ doc = yyjson_read_opts(dat3, len3, 0, &alc, NULL);
+ yyjson_doc_free(doc);
+
+ free(buf);
+ @endcode
+ @see yyjson_alc_pool_init()
+ */
+yyjson_api_inline size_t yyjson_read_max_memory_usage(size_t len,
+ yyjson_read_flag flg) {
+ /*
+ 1. The max value count is (json_size / 2 + 1),
+ for example: "[1,2,3,4]" size is 9, value count is 5.
+ 2. Some broken JSON may cost more memory during reading, but fail at end,
+ for example: "[[[[[[[[".
+ 3. yyjson use 16 bytes per value, see struct yyjson_val.
+ 4. yyjson use dynamic memory with a growth factor of 1.5.
+
+ The max memory size is (json_size / 2 * 16 * 1.5 + padding).
+ */
+ size_t mul = (size_t)12 + !(flg & YYJSON_READ_INSITU);
+ size_t pad = 256;
+ size_t max = (size_t)(~(size_t)0);
+ if (flg & YYJSON_READ_STOP_WHEN_DONE) len = len < 256 ? 256 : len;
+ if (len >= (max - pad - mul) / mul) return 0;
+ return len * mul + pad;
+}
+
+/**
+ Read a JSON number.
+
+ This function is thread-safe when data is not modified by other threads.
+
+ @param dat The JSON data (UTF-8 without BOM), null-terminator is required.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param val The output value where result is stored.
+ If this parameter is NULL, the function will fail and return NULL.
+ The value will hold either UINT or SINT or REAL number;
+ @param flg The JSON read options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`.
+ @param alc The memory allocator used for long number.
+ It is only used when the built-in floating point reader is disabled.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return If successful, a pointer to the character after the last character
+ used in the conversion, NULL if an error occurs.
+ */
+yyjson_api const char *yyjson_read_number(const char *dat,
+ yyjson_val *val,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc,
+ yyjson_read_err *err);
+
+/**
+ Read a JSON number.
+
+ This function is thread-safe when data is not modified by other threads.
+
+ @param dat The JSON data (UTF-8 without BOM), null-terminator is required.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param val The output value where result is stored.
+ If this parameter is NULL, the function will fail and return NULL.
+ The value will hold either UINT or SINT or REAL number;
+ @param flg The JSON read options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ Supports `YYJSON_READ_NUMBER_AS_RAW` and `YYJSON_READ_ALLOW_INF_AND_NAN`.
+ @param alc The memory allocator used for long number.
+ It is only used when the built-in floating point reader is disabled.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return If successful, a pointer to the character after the last character
+ used in the conversion, NULL if an error occurs.
+ */
+yyjson_api_inline const char *yyjson_mut_read_number(const char *dat,
+ yyjson_mut_val *val,
+ yyjson_read_flag flg,
+ const yyjson_alc *alc,
+ yyjson_read_err *err) {
+ return yyjson_read_number(dat, (yyjson_val *)val, flg, alc, err);
+}
+
+
+/*==============================================================================
+ * JSON Writer API
+ *============================================================================*/
+
+/** Run-time options for JSON writer. */
+typedef uint32_t yyjson_write_flag;
+
+/** Default option:
+ - Write JSON minify.
+ - Report error on inf or nan number.
+ - Report error on invalid UTF-8 string.
+ - Do not escape unicode or slash. */
+static const yyjson_write_flag YYJSON_WRITE_NOFLAG = 0;
+
+/** Write JSON pretty with 4 space indent. */
+static const yyjson_write_flag YYJSON_WRITE_PRETTY = 1 << 0;
+
+/** Escape unicode as `uXXXX`, make the output ASCII only. */
+static const yyjson_write_flag YYJSON_WRITE_ESCAPE_UNICODE = 1 << 1;
+
+/** Escape '/' as '\/'. */
+static const yyjson_write_flag YYJSON_WRITE_ESCAPE_SLASHES = 1 << 2;
+
+/** Write inf and nan number as 'Infinity' and 'NaN' literal (non-standard). */
+static const yyjson_write_flag YYJSON_WRITE_ALLOW_INF_AND_NAN = 1 << 3;
+
+/** Write inf and nan number as null literal.
+ This flag will override `YYJSON_WRITE_ALLOW_INF_AND_NAN` flag. */
+static const yyjson_write_flag YYJSON_WRITE_INF_AND_NAN_AS_NULL = 1 << 4;
+
+/** Allow invalid unicode when encoding string values (non-standard).
+ Invalid characters in string value will be copied byte by byte.
+ If `YYJSON_WRITE_ESCAPE_UNICODE` flag is also set, invalid character will be
+ escaped as `U+FFFD` (replacement character).
+ This flag does not affect the performance of correctly encoded strings. */
+static const yyjson_write_flag YYJSON_WRITE_ALLOW_INVALID_UNICODE = 1 << 5;
+
+/** Write JSON pretty with 2 space indent.
+ This flag will override `YYJSON_WRITE_PRETTY` flag. */
+static const yyjson_write_flag YYJSON_WRITE_PRETTY_TWO_SPACES = 1 << 6;
+
+/** Adds a newline character `\n` at the end of the JSON.
+ This can be helpful for text editors or NDJSON. */
+static const yyjson_write_flag YYJSON_WRITE_NEWLINE_AT_END = 1 << 7;
+
+
+
+/** Result code for JSON writer */
+typedef uint32_t yyjson_write_code;
+
+/** Success, no error. */
+static const yyjson_write_code YYJSON_WRITE_SUCCESS = 0;
+
+/** Invalid parameter, such as NULL document. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_PARAMETER = 1;
+
+/** Memory allocation failure occurs. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_MEMORY_ALLOCATION = 2;
+
+/** Invalid value type in JSON document. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_VALUE_TYPE = 3;
+
+/** NaN or Infinity number occurs. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_NAN_OR_INF = 4;
+
+/** Failed to open a file. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_OPEN = 5;
+
+/** Failed to write a file. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_FILE_WRITE = 6;
+
+/** Invalid unicode in string. */
+static const yyjson_write_code YYJSON_WRITE_ERROR_INVALID_STRING = 7;
+
+/** Error information for JSON writer. */
+typedef struct yyjson_write_err {
+ /** Error code, see `yyjson_write_code` for all possible values. */
+ yyjson_write_code code;
+ /** Error message, constant, no need to free (NULL if success). */
+ const char *msg;
+} yyjson_write_err;
+
+
+
+/*==============================================================================
+ * JSON Document Writer API
+ *============================================================================*/
+
+/**
+ Write a document to JSON string with options.
+
+ This function is thread-safe when:
+ The `alc` is thread-safe or NULL.
+
+ @param doc The JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free() or alc->free().
+ */
+yyjson_api char *yyjson_write_opts(const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ size_t *len,
+ yyjson_write_err *err);
+
+/**
+ Write a document to JSON file with options.
+
+ This function is thread-safe when:
+ 1. The file is not accessed by other threads.
+ 2. The `alc` is thread-safe or NULL.
+
+ @param path The JSON file's path.
+ If this path is NULL or invalid, the function will fail and return false.
+ If this file is not empty, the content will be discarded.
+ @param doc The JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_write_file(const char *path,
+ const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a document to file pointer with options.
+
+ @param fp The file pointer.
+ The data will be written to the current position of the file.
+ If this fp is NULL or invalid, the function will fail and return false.
+ @param doc The JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_write_fp(FILE *fp,
+ const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a document to JSON string.
+
+ This function is thread-safe.
+
+ @param doc The JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free().
+ */
+yyjson_api_inline char *yyjson_write(const yyjson_doc *doc,
+ yyjson_write_flag flg,
+ size_t *len) {
+ return yyjson_write_opts(doc, flg, NULL, len, NULL);
+}
+
+
+
+/**
+ Write a document to JSON string with options.
+
+ This function is thread-safe when:
+ 1. The `doc` is not modified by other threads.
+ 2. The `alc` is thread-safe or NULL.
+
+ @param doc The mutable JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free() or alc->free().
+ */
+yyjson_api char *yyjson_mut_write_opts(const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ size_t *len,
+ yyjson_write_err *err);
+
+/**
+ Write a document to JSON file with options.
+
+ This function is thread-safe when:
+ 1. The file is not accessed by other threads.
+ 2. The `doc` is not modified by other threads.
+ 3. The `alc` is thread-safe or NULL.
+
+ @param path The JSON file's path.
+ If this path is NULL or invalid, the function will fail and return false.
+ If this file is not empty, the content will be discarded.
+ @param doc The mutable JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_mut_write_file(const char *path,
+ const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a document to file pointer with options.
+
+ @param fp The file pointer.
+ The data will be written to the current position of the file.
+ If this fp is NULL or invalid, the function will fail and return false.
+ @param doc The mutable JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_mut_write_fp(FILE *fp,
+ const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a document to JSON string.
+
+ This function is thread-safe when:
+ The `doc` is not modified by other threads.
+
+ @param doc The JSON document.
+ If this doc is NULL or has no root, the function will fail and return false.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free().
+ */
+yyjson_api_inline char *yyjson_mut_write(const yyjson_mut_doc *doc,
+ yyjson_write_flag flg,
+ size_t *len) {
+ return yyjson_mut_write_opts(doc, flg, NULL, len, NULL);
+}
+
+
+
+/*==============================================================================
+ * JSON Value Writer API
+ *============================================================================*/
+
+/**
+ Write a value to JSON string with options.
+
+ This function is thread-safe when:
+ The `alc` is thread-safe or NULL.
+
+ @param val The JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free() or alc->free().
+ */
+yyjson_api char *yyjson_val_write_opts(const yyjson_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ size_t *len,
+ yyjson_write_err *err);
+
+/**
+ Write a value to JSON file with options.
+
+ This function is thread-safe when:
+ 1. The file is not accessed by other threads.
+ 2. The `alc` is thread-safe or NULL.
+
+ @param path The JSON file's path.
+ If this path is NULL or invalid, the function will fail and return false.
+ If this file is not empty, the content will be discarded.
+ @param val The JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_val_write_file(const char *path,
+ const yyjson_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a value to file pointer with options.
+
+ @param fp The file pointer.
+ The data will be written to the current position of the file.
+ If this path is NULL or invalid, the function will fail and return false.
+ @param val The JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_val_write_fp(FILE *fp,
+ const yyjson_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a value to JSON string.
+
+ This function is thread-safe.
+
+ @param val The JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free().
+ */
+yyjson_api_inline char *yyjson_val_write(const yyjson_val *val,
+ yyjson_write_flag flg,
+ size_t *len) {
+ return yyjson_val_write_opts(val, flg, NULL, len, NULL);
+}
+
+/**
+ Write a value to JSON string with options.
+
+ This function is thread-safe when:
+ 1. The `val` is not modified by other threads.
+ 2. The `alc` is thread-safe or NULL.
+
+ @param val The mutable JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free() or alc->free().
+ */
+yyjson_api char *yyjson_mut_val_write_opts(const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ size_t *len,
+ yyjson_write_err *err);
+
+/**
+ Write a value to JSON file with options.
+
+ This function is thread-safe when:
+ 1. The file is not accessed by other threads.
+ 2. The `val` is not modified by other threads.
+ 3. The `alc` is thread-safe or NULL.
+
+ @param path The JSON file's path.
+ If this path is NULL or invalid, the function will fail and return false.
+ If this file is not empty, the content will be discarded.
+ @param val The mutable JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_mut_val_write_file(const char *path,
+ const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a value to JSON file with options.
+
+ @param fp The file pointer.
+ The data will be written to the current position of the file.
+ If this path is NULL or invalid, the function will fail and return false.
+ @param val The mutable JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param alc The memory allocator used by JSON writer.
+ Pass NULL to use the libc's default allocator.
+ @param err A pointer to receive error information.
+ Pass NULL if you don't need error information.
+ @return true if successful, false if an error occurs.
+
+ @warning On 32-bit operating system, files larger than 2GB may fail to write.
+ */
+yyjson_api bool yyjson_mut_val_write_fp(FILE *fp,
+ const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ const yyjson_alc *alc,
+ yyjson_write_err *err);
+
+/**
+ Write a value to JSON string.
+
+ This function is thread-safe when:
+ The `val` is not modified by other threads.
+
+ @param val The JSON root value.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param flg The JSON write options.
+ Multiple options can be combined with `|` operator. 0 means no options.
+ @param len A pointer to receive output length in bytes (not including the
+ null-terminator). Pass NULL if you don't need length information.
+ @return A new JSON string, or NULL if an error occurs.
+ This string is encoded as UTF-8 with a null-terminator.
+ When it's no longer needed, it should be freed with free().
+ */
+yyjson_api_inline char *yyjson_mut_val_write(const yyjson_mut_val *val,
+ yyjson_write_flag flg,
+ size_t *len) {
+ return yyjson_mut_val_write_opts(val, flg, NULL, len, NULL);
+}
+
+
+
+/*==============================================================================
+ * JSON Document API
+ *============================================================================*/
+
+/** Returns the root value of this JSON document.
+ Returns NULL if `doc` is NULL. */
+yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc);
+
+/** Returns read size of input JSON data.
+ Returns 0 if `doc` is NULL.
+ For example: the read size of `[1,2,3]` is 7 bytes. */
+yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc);
+
+/** Returns total value count in this JSON document.
+ Returns 0 if `doc` is NULL.
+ For example: the value count of `[1,2,3]` is 4. */
+yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc);
+
+/** Release the JSON document and free the memory.
+ After calling this function, the `doc` and all values from the `doc` are no
+ longer available. This function will do nothing if the `doc` is NULL. */
+yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc);
+
+
+
+/*==============================================================================
+ * JSON Value Type API
+ *============================================================================*/
+
+/** Returns whether the JSON value is raw.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_raw(yyjson_val *val);
+
+/** Returns whether the JSON value is `null`.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_null(yyjson_val *val);
+
+/** Returns whether the JSON value is `true`.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_true(yyjson_val *val);
+
+/** Returns whether the JSON value is `false`.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_false(yyjson_val *val);
+
+/** Returns whether the JSON value is bool (true/false).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_bool(yyjson_val *val);
+
+/** Returns whether the JSON value is unsigned integer (uint64_t).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_uint(yyjson_val *val);
+
+/** Returns whether the JSON value is signed integer (int64_t).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_sint(yyjson_val *val);
+
+/** Returns whether the JSON value is integer (uint64_t/int64_t).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_int(yyjson_val *val);
+
+/** Returns whether the JSON value is real number (double).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_real(yyjson_val *val);
+
+/** Returns whether the JSON value is number (uint64_t/int64_t/double).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_num(yyjson_val *val);
+
+/** Returns whether the JSON value is string.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_str(yyjson_val *val);
+
+/** Returns whether the JSON value is array.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_arr(yyjson_val *val);
+
+/** Returns whether the JSON value is object.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_obj(yyjson_val *val);
+
+/** Returns whether the JSON value is container (array/object).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val);
+
+
+
+/*==============================================================================
+ * JSON Value Content API
+ *============================================================================*/
+
+/** Returns the JSON value's type.
+ Returns YYJSON_TYPE_NONE if `val` is NULL. */
+yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val);
+
+/** Returns the JSON value's subtype.
+ Returns YYJSON_SUBTYPE_NONE if `val` is NULL. */
+yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val);
+
+/** Returns the JSON value's tag.
+ Returns 0 if `val` is NULL. */
+yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val);
+
+/** Returns the JSON value's type description.
+ The return value should be one of these strings: "raw", "null", "string",
+ "array", "object", "true", "false", "uint", "sint", "real", "unknown". */
+yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val);
+
+/** Returns the content if the value is raw.
+ Returns NULL if `val` is NULL or type is not raw. */
+yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val);
+
+/** Returns the content if the value is bool.
+ Returns NULL if `val` is NULL or type is not bool. */
+yyjson_api_inline bool yyjson_get_bool(yyjson_val *val);
+
+/** Returns the content and cast to uint64_t.
+ Returns 0 if `val` is NULL or type is not integer(sint/uint). */
+yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val);
+
+/** Returns the content and cast to int64_t.
+ Returns 0 if `val` is NULL or type is not integer(sint/uint). */
+yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val);
+
+/** Returns the content and cast to int.
+ Returns 0 if `val` is NULL or type is not integer(sint/uint). */
+yyjson_api_inline int yyjson_get_int(yyjson_val *val);
+
+/** Returns the content if the value is real number, or 0.0 on error.
+ Returns 0.0 if `val` is NULL or type is not real(double). */
+yyjson_api_inline double yyjson_get_real(yyjson_val *val);
+
+/** Returns the content and typecast to `double` if the value is number.
+ Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */
+yyjson_api_inline double yyjson_get_num(yyjson_val *val);
+
+/** Returns the content if the value is string.
+ Returns NULL if `val` is NULL or type is not string. */
+yyjson_api_inline const char *yyjson_get_str(yyjson_val *val);
+
+/** Returns the content length (string length, array size, object size.
+ Returns 0 if `val` is NULL or type is not string/array/object. */
+yyjson_api_inline size_t yyjson_get_len(yyjson_val *val);
+
+/** Returns whether the JSON value is equals to a string.
+ Returns false if input is NULL or type is not string. */
+yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str);
+
+/** Returns whether the JSON value is equals to a string.
+ The `str` should be a UTF-8 string, null-terminator is not required.
+ Returns false if input is NULL or type is not string. */
+yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str,
+ size_t len);
+
+/** Returns whether two JSON values are equal (deep compare).
+ Returns false if input is NULL.
+ @note the result may be inaccurate if object has duplicate keys.
+ @warning This function is recursive and may cause a stack overflow
+ if the object level is too deep. */
+yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs);
+
+/** Set the value to raw.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_raw(yyjson_val *val,
+ const char *raw, size_t len);
+
+/** Set the value to null.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_null(yyjson_val *val);
+
+/** Set the value to bool.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num);
+
+/** Set the value to uint.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num);
+
+/** Set the value to sint.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num);
+
+/** Set the value to int.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num);
+
+/** Set the value to real.
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num);
+
+/** Set the value to string (null-terminated).
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str);
+
+/** Set the value to string (with length).
+ Returns false if input is NULL or `val` is object or array.
+ @warning This will modify the `immutable` value, use with caution. */
+yyjson_api_inline bool yyjson_set_strn(yyjson_val *val,
+ const char *str, size_t len);
+
+
+
+/*==============================================================================
+ * JSON Array API
+ *============================================================================*/
+
+/** Returns the number of elements in this array.
+ Returns 0 if `arr` is NULL or type is not array. */
+yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr);
+
+/** Returns the element at the specified position in this array.
+ Returns NULL if array is NULL/empty or the index is out of bounds.
+ @warning This function takes a linear search time if array is not flat.
+ For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat. */
+yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx);
+
+/** Returns the first element of this array.
+ Returns NULL if `arr` is NULL/empty or type is not array. */
+yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr);
+
+/** Returns the last element of this array.
+ Returns NULL if `arr` is NULL/empty or type is not array.
+ @warning This function takes a linear search time if array is not flat.
+ For example: `[1,{},3]` is flat, `[1,[2],3]` is not flat.*/
+yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr);
+
+
+
+/*==============================================================================
+ * JSON Array Iterator API
+ *============================================================================*/
+
+/**
+ A JSON array iterator.
+
+ @par Example
+ @code
+ yyjson_val *val;
+ yyjson_arr_iter iter = yyjson_arr_iter_with(arr);
+ while ((val = yyjson_arr_iter_next(&iter))) {
+ your_func(val);
+ }
+ @endcode
+ */
+typedef struct yyjson_arr_iter {
+ size_t idx; /**< next value's index */
+ size_t max; /**< maximum index (arr.size) */
+ yyjson_val *cur; /**< next value */
+} yyjson_arr_iter;
+
+/**
+ Initialize an iterator for this array.
+
+ @param arr The array to be iterated over.
+ If this parameter is NULL or not an array, `iter` will be set to empty.
+ @param iter The iterator to be initialized.
+ If this parameter is NULL, the function will fail and return false.
+ @return true if the `iter` has been successfully initialized.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr,
+ yyjson_arr_iter *iter);
+
+/**
+ Create an iterator with an array , same as `yyjson_arr_iter_init()`.
+
+ @param arr The array to be iterated over.
+ If this parameter is NULL or not an array, an empty iterator will returned.
+ @return A new iterator for the array.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr);
+
+/**
+ Returns whether the iteration has more elements.
+ If `iter` is NULL, this function will return false.
+ */
+yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter);
+
+/**
+ Returns the next element in the iteration, or NULL on end.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter);
+
+/**
+ Macro for iterating over an array.
+ It works like iterator, but with a more intuitive API.
+
+ @par Example
+ @code
+ size_t idx, max;
+ yyjson_val *val;
+ yyjson_arr_foreach(arr, idx, max, val) {
+ your_func(idx, val);
+ }
+ @endcode
+ */
+#define yyjson_arr_foreach(arr, idx, max, val) \
+ for ((idx) = 0, \
+ (max) = yyjson_arr_size(arr), \
+ (val) = yyjson_arr_get_first(arr); \
+ (idx) < (max); \
+ (idx)++, \
+ (val) = unsafe_yyjson_get_next(val))
+
+
+
+/*==============================================================================
+ * JSON Object API
+ *============================================================================*/
+
+/** Returns the number of key-value pairs in this object.
+ Returns 0 if `obj` is NULL or type is not object. */
+yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj);
+
+/** Returns the value to which the specified key is mapped.
+ Returns NULL if this object contains no mapping for the key.
+ Returns NULL if `obj/key` is NULL, or type is not object.
+
+ The `key` should be a null-terminated UTF-8 string.
+
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj, const char *key);
+
+/** Returns the value to which the specified key is mapped.
+ Returns NULL if this object contains no mapping for the key.
+ Returns NULL if `obj/key` is NULL, or type is not object.
+
+ The `key` should be a UTF-8 string, null-terminator is not required.
+ The `key_len` should be the length of the key, in bytes.
+
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj, const char *key,
+ size_t key_len);
+
+
+
+/*==============================================================================
+ * JSON Object Iterator API
+ *============================================================================*/
+
+/**
+ A JSON object iterator.
+
+ @par Example
+ @code
+ yyjson_val *key, *val;
+ yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
+ while ((key = yyjson_obj_iter_next(&iter))) {
+ val = yyjson_obj_iter_get_val(key);
+ your_func(key, val);
+ }
+ @endcode
+
+ If the ordering of the keys is known at compile-time, you can use this method
+ to speed up value lookups:
+ @code
+ // {"k1":1, "k2": 3, "k3": 3}
+ yyjson_val *key, *val;
+ yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
+ yyjson_val *v1 = yyjson_obj_iter_get(&iter, "k1");
+ yyjson_val *v3 = yyjson_obj_iter_get(&iter, "k3");
+ @endcode
+ @see yyjson_obj_iter_get() and yyjson_obj_iter_getn()
+ */
+typedef struct yyjson_obj_iter {
+ size_t idx; /**< next key's index */
+ size_t max; /**< maximum key index (obj.size) */
+ yyjson_val *cur; /**< next key */
+ yyjson_val *obj; /**< the object being iterated */
+} yyjson_obj_iter;
+
+/**
+ Initialize an iterator for this object.
+
+ @param obj The object to be iterated over.
+ If this parameter is NULL or not an object, `iter` will be set to empty.
+ @param iter The iterator to be initialized.
+ If this parameter is NULL, the function will fail and return false.
+ @return true if the `iter` has been successfully initialized.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj,
+ yyjson_obj_iter *iter);
+
+/**
+ Create an iterator with an object, same as `yyjson_obj_iter_init()`.
+
+ @param obj The object to be iterated over.
+ If this parameter is NULL or not an object, an empty iterator will returned.
+ @return A new iterator for the object.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj);
+
+/**
+ Returns whether the iteration has more elements.
+ If `iter` is NULL, this function will return false.
+ */
+yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter);
+
+/**
+ Returns the next key in the iteration, or NULL on end.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter);
+
+/**
+ Returns the value for key inside the iteration.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key);
+
+/**
+ Iterates to a specified key and returns the value.
+
+ This function does the same thing as `yyjson_obj_get()`, but is much faster
+ if the ordering of the keys is known at compile-time and you are using the same
+ order to look up the values. If the key exists in this object, then the
+ iterator will stop at the next key, otherwise the iterator will not change and
+ NULL is returned.
+
+ @param iter The object iterator, should not be NULL.
+ @param key The key, should be a UTF-8 string with null-terminator.
+ @return The value to which the specified key is mapped.
+ NULL if this object contains no mapping for the key or input is invalid.
+
+ @warning This function takes a linear search time if the key is not nearby.
+ */
+yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter,
+ const char *key);
+
+/**
+ Iterates to a specified key and returns the value.
+
+ This function does the same thing as `yyjson_obj_getn()`, but is much faster
+ if the ordering of the keys is known at compile-time and you are using the same
+ order to look up the values. If the key exists in this object, then the
+ iterator will stop at the next key, otherwise the iterator will not change and
+ NULL is returned.
+
+ @param iter The object iterator, should not be NULL.
+ @param key The key, should be a UTF-8 string, null-terminator is not required.
+ @param key_len The the length of `key`, in bytes.
+ @return The value to which the specified key is mapped.
+ NULL if this object contains no mapping for the key or input is invalid.
+
+ @warning This function takes a linear search time if the key is not nearby.
+ */
+yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter,
+ const char *key,
+ size_t key_len);
+
+/**
+ Macro for iterating over an object.
+ It works like iterator, but with a more intuitive API.
+
+ @par Example
+ @code
+ size_t idx, max;
+ yyjson_val *key, *val;
+ yyjson_obj_foreach(obj, idx, max, key, val) {
+ your_func(key, val);
+ }
+ @endcode
+ */
+#define yyjson_obj_foreach(obj, idx, max, key, val) \
+ for ((idx) = 0, \
+ (max) = yyjson_obj_size(obj), \
+ (key) = (obj) ? unsafe_yyjson_get_first(obj) : NULL, \
+ (val) = (key) + 1; \
+ (idx) < (max); \
+ (idx)++, \
+ (key) = unsafe_yyjson_get_next(val), \
+ (val) = (key) + 1)
+
+
+
+/*==============================================================================
+ * Mutable JSON Document API
+ *============================================================================*/
+
+/** Returns the root value of this JSON document.
+ Returns NULL if `doc` is NULL. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc);
+
+/** Sets the root value of this JSON document.
+ Pass NULL to clear root value of the document. */
+yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc,
+ yyjson_mut_val *root);
+
+/**
+ Set the string pool size for a mutable document.
+ This function does not allocate memory immediately, but uses the size when
+ the next memory allocation is needed.
+
+ If the caller knows the approximate bytes of strings that the document needs to
+ store (e.g. copy string with `yyjson_mut_strcpy` function), setting a larger
+ size can avoid multiple memory allocations and improve performance.
+
+ @param doc The mutable document.
+ @param len The desired string pool size in bytes (total string length).
+ @return true if successful, false if size is 0 or overflow.
+ */
+yyjson_api bool yyjson_mut_doc_set_str_pool_size(yyjson_mut_doc *doc,
+ size_t len);
+
+/**
+ Set the value pool size for a mutable document.
+ This function does not allocate memory immediately, but uses the size when
+ the next memory allocation is needed.
+
+ If the caller knows the approximate number of values that the document needs to
+ store (e.g. create new value with `yyjson_mut_xxx` functions), setting a larger
+ size can avoid multiple memory allocations and improve performance.
+
+ @param doc The mutable document.
+ @param count The desired value pool size (number of `yyjson_mut_val`).
+ @return true if successful, false if size is 0 or overflow.
+ */
+yyjson_api bool yyjson_mut_doc_set_val_pool_size(yyjson_mut_doc *doc,
+ size_t count);
+
+/** Release the JSON document and free the memory.
+ After calling this function, the `doc` and all values from the `doc` are no
+ longer available. This function will do nothing if the `doc` is NULL. */
+yyjson_api void yyjson_mut_doc_free(yyjson_mut_doc *doc);
+
+/** Creates and returns a new mutable JSON document, returns NULL on error.
+ If allocator is NULL, the default allocator will be used. */
+yyjson_api yyjson_mut_doc *yyjson_mut_doc_new(const yyjson_alc *alc);
+
+/** Copies and returns a new mutable document from input, returns NULL on error.
+ This makes a `deep-copy` on the immutable document.
+ If allocator is NULL, the default allocator will be used.
+ @note `imut_doc` -> `mut_doc`. */
+yyjson_api yyjson_mut_doc *yyjson_doc_mut_copy(yyjson_doc *doc,
+ const yyjson_alc *alc);
+
+/** Copies and returns a new mutable document from input, returns NULL on error.
+ This makes a `deep-copy` on the mutable document.
+ If allocator is NULL, the default allocator will be used.
+ @note `mut_doc` -> `mut_doc`. */
+yyjson_api yyjson_mut_doc *yyjson_mut_doc_mut_copy(yyjson_mut_doc *doc,
+ const yyjson_alc *alc);
+
+/** Copies and returns a new mutable value from input, returns NULL on error.
+ This makes a `deep-copy` on the immutable value.
+ The memory was managed by mutable document.
+ @note `imut_val` -> `mut_val`. */
+yyjson_api yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *doc,
+ yyjson_val *val);
+
+/** Copies and returns a new mutable value from input, returns NULL on error.
+ This makes a `deep-copy` on the mutable value.
+ The memory was managed by mutable document.
+ @note `mut_val` -> `mut_val`.
+ @warning This function is recursive and may cause a stack overflow
+ if the object level is too deep. */
+yyjson_api yyjson_mut_val *yyjson_mut_val_mut_copy(yyjson_mut_doc *doc,
+ yyjson_mut_val *val);
+
+/** Copies and returns a new immutable document from input,
+ returns NULL on error. This makes a `deep-copy` on the mutable document.
+ The returned document should be freed with `yyjson_doc_free()`.
+ @note `mut_doc` -> `imut_doc`.
+ @warning This function is recursive and may cause a stack overflow
+ if the object level is too deep. */
+yyjson_api yyjson_doc *yyjson_mut_doc_imut_copy(yyjson_mut_doc *doc,
+ const yyjson_alc *alc);
+
+/** Copies and returns a new immutable document from input,
+ returns NULL on error. This makes a `deep-copy` on the mutable value.
+ The returned document should be freed with `yyjson_doc_free()`.
+ @note `mut_val` -> `imut_doc`.
+ @warning This function is recursive and may cause a stack overflow
+ if the object level is too deep. */
+yyjson_api yyjson_doc *yyjson_mut_val_imut_copy(yyjson_mut_val *val,
+ const yyjson_alc *alc);
+
+
+
+/*==============================================================================
+ * Mutable JSON Value Type API
+ *============================================================================*/
+
+/** Returns whether the JSON value is raw.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is `null`.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is `true`.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is `false`.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is bool (true/false).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is unsigned integer (uint64_t).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is signed integer (int64_t).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is integer (uint64_t/int64_t).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is real number (double).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is number (uint/sint/real).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is string.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is array.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is object.
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is container (array/object).
+ Returns false if `val` is NULL. */
+yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val);
+
+
+
+/*==============================================================================
+ * Mutable JSON Value Content API
+ *============================================================================*/
+
+/** Returns the JSON value's type.
+ Returns `YYJSON_TYPE_NONE` if `val` is NULL. */
+yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val);
+
+/** Returns the JSON value's subtype.
+ Returns `YYJSON_SUBTYPE_NONE` if `val` is NULL. */
+yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val);
+
+/** Returns the JSON value's tag.
+ Returns 0 if `val` is NULL. */
+yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val);
+
+/** Returns the JSON value's type description.
+ The return value should be one of these strings: "raw", "null", "string",
+ "array", "object", "true", "false", "uint", "sint", "real", "unknown". */
+yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val);
+
+/** Returns the content if the value is raw.
+ Returns NULL if `val` is NULL or type is not raw. */
+yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val);
+
+/** Returns the content if the value is bool.
+ Returns NULL if `val` is NULL or type is not bool. */
+yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val);
+
+/** Returns the content and cast to uint64_t.
+ Returns 0 if `val` is NULL or type is not integer(sint/uint). */
+yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val);
+
+/** Returns the content and cast to int64_t.
+ Returns 0 if `val` is NULL or type is not integer(sint/uint). */
+yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val);
+
+/** Returns the content and cast to int.
+ Returns 0 if `val` is NULL or type is not integer(sint/uint). */
+yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val);
+
+/** Returns the content if the value is real number.
+ Returns 0.0 if `val` is NULL or type is not real(double). */
+yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val);
+
+/** Returns the content and typecast to `double` if the value is number.
+ Returns 0.0 if `val` is NULL or type is not number(uint/sint/real). */
+yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val);
+
+/** Returns the content if the value is string.
+ Returns NULL if `val` is NULL or type is not string. */
+yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val);
+
+/** Returns the content length (string length, array size, object size.
+ Returns 0 if `val` is NULL or type is not string/array/object. */
+yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val);
+
+/** Returns whether the JSON value is equals to a string.
+ The `str` should be a null-terminated UTF-8 string.
+ Returns false if input is NULL or type is not string. */
+yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val,
+ const char *str);
+
+/** Returns whether the JSON value is equals to a string.
+ The `str` should be a UTF-8 string, null-terminator is not required.
+ Returns false if input is NULL or type is not string. */
+yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val,
+ const char *str, size_t len);
+
+/** Returns whether two JSON values are equal (deep compare).
+ Returns false if input is NULL.
+ @note the result may be inaccurate if object has duplicate keys.
+ @warning This function is recursive and may cause a stack overflow
+ if the object level is too deep. */
+yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs,
+ yyjson_mut_val *rhs);
+
+/** Set the value to raw.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val,
+ const char *raw, size_t len);
+
+/** Set the value to null.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val);
+
+/** Set the value to bool.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num);
+
+/** Set the value to uint.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num);
+
+/** Set the value to sint.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num);
+
+/** Set the value to int.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num);
+
+/** Set the value to real.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num);
+
+/** Set the value to string (null-terminated).
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val, const char *str);
+
+/** Set the value to string (with length).
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val,
+ const char *str, size_t len);
+
+/** Set the value to array.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val);
+
+/** Set the value to array.
+ Returns false if input is NULL.
+ @warning This function should not be used on an existing object or array. */
+yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val);
+
+
+
+/*==============================================================================
+ * Mutable JSON Value Creation API
+ *============================================================================*/
+
+/** Creates and returns a raw value, returns NULL on error.
+ The `str` should be a null-terminated UTF-8 string.
+
+ @warning The input string is not copied, you should keep this string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc,
+ const char *str);
+
+/** Creates and returns a raw value, returns NULL on error.
+ The `str` should be a UTF-8 string, null-terminator is not required.
+
+ @warning The input string is not copied, you should keep this string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len);
+
+/** Creates and returns a raw value, returns NULL on error.
+ The `str` should be a null-terminated UTF-8 string.
+ The input string is copied and held by the document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc,
+ const char *str);
+
+/** Creates and returns a raw value, returns NULL on error.
+ The `str` should be a UTF-8 string, null-terminator is not required.
+ The input string is copied and held by the document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len);
+
+/** Creates and returns a null value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc);
+
+/** Creates and returns a true value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc);
+
+/** Creates and returns a false value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc);
+
+/** Creates and returns a bool value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
+ bool val);
+
+/** Creates and returns an unsigned integer value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc,
+ uint64_t num);
+
+/** Creates and returns a signed integer value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc,
+ int64_t num);
+
+/** Creates and returns a signed integer value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc,
+ int64_t num);
+
+/** Creates and returns an real number value, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc,
+ double num);
+
+/** Creates and returns a string value, returns NULL on error.
+ The `str` should be a null-terminated UTF-8 string.
+ @warning The input string is not copied, you should keep this string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc,
+ const char *str);
+
+/** Creates and returns a string value, returns NULL on error.
+ The `str` should be a UTF-8 string, null-terminator is not required.
+ @warning The input string is not copied, you should keep this string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len);
+
+/** Creates and returns a string value, returns NULL on error.
+ The `str` should be a null-terminated UTF-8 string.
+ The input string is copied and held by the document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc,
+ const char *str);
+
+/** Creates and returns a string value, returns NULL on error.
+ The `str` should be a UTF-8 string, null-terminator is not required.
+ The input string is copied and held by the document. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len);
+
+
+
+/*==============================================================================
+ * Mutable JSON Array API
+ *============================================================================*/
+
+/** Returns the number of elements in this array.
+ Returns 0 if `arr` is NULL or type is not array. */
+yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr);
+
+/** Returns the element at the specified position in this array.
+ Returns NULL if array is NULL/empty or the index is out of bounds.
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr,
+ size_t idx);
+
+/** Returns the first element of this array.
+ Returns NULL if `arr` is NULL/empty or type is not array. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(yyjson_mut_val *arr);
+
+/** Returns the last element of this array.
+ Returns NULL if `arr` is NULL/empty or type is not array. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(yyjson_mut_val *arr);
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Iterator API
+ *============================================================================*/
+
+/**
+ A mutable JSON array iterator.
+
+ @warning You should not modify the array while iterating over it, but you can
+ use `yyjson_mut_arr_iter_remove()` to remove current value.
+
+ @par Example
+ @code
+ yyjson_mut_val *val;
+ yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(arr);
+ while ((val = yyjson_mut_arr_iter_next(&iter))) {
+ your_func(val);
+ if (your_val_is_unused(val)) {
+ yyjson_mut_arr_iter_remove(&iter);
+ }
+ }
+ @endcode
+ */
+typedef struct yyjson_mut_arr_iter {
+ size_t idx; /**< next value's index */
+ size_t max; /**< maximum index (arr.size) */
+ yyjson_mut_val *cur; /**< current value */
+ yyjson_mut_val *pre; /**< previous value */
+ yyjson_mut_val *arr; /**< the array being iterated */
+} yyjson_mut_arr_iter;
+
+/**
+ Initialize an iterator for this array.
+
+ @param arr The array to be iterated over.
+ If this parameter is NULL or not an array, `iter` will be set to empty.
+ @param iter The iterator to be initialized.
+ If this parameter is NULL, the function will fail and return false.
+ @return true if the `iter` has been successfully initialized.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr,
+ yyjson_mut_arr_iter *iter);
+
+/**
+ Create an iterator with an array , same as `yyjson_mut_arr_iter_init()`.
+
+ @param arr The array to be iterated over.
+ If this parameter is NULL or not an array, an empty iterator will returned.
+ @return A new iterator for the array.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with(
+ yyjson_mut_val *arr);
+
+/**
+ Returns whether the iteration has more elements.
+ If `iter` is NULL, this function will return false.
+ */
+yyjson_api_inline bool yyjson_mut_arr_iter_has_next(
+ yyjson_mut_arr_iter *iter);
+
+/**
+ Returns the next element in the iteration, or NULL on end.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next(
+ yyjson_mut_arr_iter *iter);
+
+/**
+ Removes and returns current element in the iteration.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove(
+ yyjson_mut_arr_iter *iter);
+
+/**
+ Macro for iterating over an array.
+ It works like iterator, but with a more intuitive API.
+
+ @warning You should not modify the array while iterating over it.
+
+ @par Example
+ @code
+ size_t idx, max;
+ yyjson_mut_val *val;
+ yyjson_mut_arr_foreach(arr, idx, max, val) {
+ your_func(idx, val);
+ }
+ @endcode
+ */
+#define yyjson_mut_arr_foreach(arr, idx, max, val) \
+ for ((idx) = 0, \
+ (max) = yyjson_mut_arr_size(arr), \
+ (val) = yyjson_mut_arr_get_first(arr); \
+ (idx) < (max); \
+ (idx)++, \
+ (val) = (val)->next)
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Creation API
+ *============================================================================*/
+
+/**
+ Creates and returns an empty mutable array.
+ @param doc A mutable document, used for memory allocation only.
+ @return The new array. NULL if input is NULL or memory allocation failed.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc);
+
+/**
+ Creates and returns a new mutable array with the given boolean values.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of boolean values.
+ @param count The value count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const bool vals[3] = { true, false, true };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_bool(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
+ yyjson_mut_doc *doc, const bool *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given sint numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of sint numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const int64_t vals[3] = { -1, 0, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint(
+ yyjson_mut_doc *doc, const int64_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given uint numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of uint numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const uint64_t vals[3] = { 0, 1, 0 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_uint(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint(
+ yyjson_mut_doc *doc, const uint64_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given real numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of real numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const double vals[3] = { 0.1, 0.2, 0.3 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_real(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real(
+ yyjson_mut_doc *doc, const double *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given int8 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of int8 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const int8_t vals[3] = { -1, 0, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_sint8(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8(
+ yyjson_mut_doc *doc, const int8_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given int16 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of int16 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const int16_t vals[3] = { -1, 0, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_sint16(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16(
+ yyjson_mut_doc *doc, const int16_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given int32 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of int32 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const int32_t vals[3] = { -1, 0, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_sint32(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32(
+ yyjson_mut_doc *doc, const int32_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given int64 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of int64 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const int64_t vals[3] = { -1, 0, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_sint64(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64(
+ yyjson_mut_doc *doc, const int64_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given uint8 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of uint8 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const uint8_t vals[3] = { 0, 1, 0 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_uint8(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8(
+ yyjson_mut_doc *doc, const uint8_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given uint16 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of uint16 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const uint16_t vals[3] = { 0, 1, 0 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_uint16(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16(
+ yyjson_mut_doc *doc, const uint16_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given uint32 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of uint32 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const uint32_t vals[3] = { 0, 1, 0 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_uint32(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32(
+ yyjson_mut_doc *doc, const uint32_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given uint64 numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of uint64 numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const uint64_t vals[3] = { 0, 1, 0 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_uint64(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64(
+ yyjson_mut_doc *doc, const uint64_t *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given float numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of float numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const float vals[3] = { -1.0f, 0.0f, 1.0f };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_float(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float(
+ yyjson_mut_doc *doc, const float *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given double numbers.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of double numbers.
+ @param count The number count. If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const double vals[3] = { -1.0, 0.0, 1.0 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_double(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double(
+ yyjson_mut_doc *doc, const double *vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given strings, these strings
+ will not be copied.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of UTF-8 null-terminator strings.
+ If this array contains NULL, the function will fail and return NULL.
+ @param count The number of values in `vals`.
+ If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @warning The input strings are not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document. If these strings will be
+ modified, you should use `yyjson_mut_arr_with_strcpy()` instead.
+
+ @par Example
+ @code
+ const char *vals[3] = { "a", "b", "c" };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_str(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str(
+ yyjson_mut_doc *doc, const char **vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given strings and string
+ lengths, these strings will not be copied.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of UTF-8 strings, null-terminator is not required.
+ If this array contains NULL, the function will fail and return NULL.
+ @param lens A C array of string lengths, in bytes.
+ @param count The number of strings in `vals`.
+ If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @warning The input strings are not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document. If these strings will be
+ modified, you should use `yyjson_mut_arr_with_strncpy()` instead.
+
+ @par Example
+ @code
+ const char *vals[3] = { "a", "bb", "c" };
+ const size_t lens[3] = { 1, 2, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn(
+ yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given strings, these strings
+ will be copied.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of UTF-8 null-terminator strings.
+ If this array contains NULL, the function will fail and return NULL.
+ @param count The number of values in `vals`.
+ If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const char *vals[3] = { "a", "b", "c" };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_strcpy(doc, vals, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy(
+ yyjson_mut_doc *doc, const char **vals, size_t count);
+
+/**
+ Creates and returns a new mutable array with the given strings and string
+ lengths, these strings will be copied.
+
+ @param doc A mutable document, used for memory allocation only.
+ If this parameter is NULL, the function will fail and return NULL.
+ @param vals A C array of UTF-8 strings, null-terminator is not required.
+ If this array contains NULL, the function will fail and return NULL.
+ @param lens A C array of string lengths, in bytes.
+ @param count The number of strings in `vals`.
+ If this value is 0, an empty array will return.
+ @return The new array. NULL if input is invalid or memory allocation failed.
+
+ @par Example
+ @code
+ const char *vals[3] = { "a", "bb", "c" };
+ const size_t lens[3] = { 1, 2, 1 };
+ yyjson_mut_val *arr = yyjson_mut_arr_with_strn(doc, vals, lens, 3);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy(
+ yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count);
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Modification API
+ *============================================================================*/
+
+/**
+ Inserts a value into an array at a given index.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param val The value to be inserted. Returns false if it is NULL.
+ @param idx The index to which to insert the new value.
+ Returns false if the index is out of range.
+ @return Whether successful.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr,
+ yyjson_mut_val *val, size_t idx);
+
+/**
+ Inserts a value at the end of the array.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param val The value to be inserted. Returns false if it is NULL.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr,
+ yyjson_mut_val *val);
+
+/**
+ Inserts a value at the head of the array.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param val The value to be inserted. Returns false if it is NULL.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr,
+ yyjson_mut_val *val);
+
+/**
+ Replaces a value at index and returns old value.
+ @param arr The array to which the value is to be replaced.
+ Returns false if it is NULL or not an array.
+ @param idx The index to which to replace the value.
+ Returns false if the index is out of range.
+ @param val The new value to replace. Returns false if it is NULL.
+ @return Old value, or NULL on error.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr,
+ size_t idx,
+ yyjson_mut_val *val);
+
+/**
+ Removes and returns a value at index.
+ @param arr The array from which the value is to be removed.
+ Returns false if it is NULL or not an array.
+ @param idx The index from which to remove the value.
+ Returns false if the index is out of range.
+ @return Old value, or NULL on error.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr,
+ size_t idx);
+
+/**
+ Removes and returns the first value in this array.
+ @param arr The array from which the value is to be removed.
+ Returns false if it is NULL or not an array.
+ @return The first value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first(
+ yyjson_mut_val *arr);
+
+/**
+ Removes and returns the last value in this array.
+ @param arr The array from which the value is to be removed.
+ Returns false if it is NULL or not an array.
+ @return The last value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last(
+ yyjson_mut_val *arr);
+
+/**
+ Removes all values within a specified range in the array.
+ @param arr The array from which the value is to be removed.
+ Returns false if it is NULL or not an array.
+ @param idx The start index of the range (0 is the first).
+ @param len The number of items in the range (can be 0).
+ @return Whether successful.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr,
+ size_t idx, size_t len);
+
+/**
+ Removes all values in this array.
+ @param arr The array from which all of the values are to be removed.
+ Returns false if it is NULL or not an array.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr);
+
+/**
+ Rotates values in this array for the given number of times.
+ For example: `[1,2,3,4,5]` rotate 2 is `[3,4,5,1,2]`.
+ @param arr The array to be rotated.
+ @param idx Index (or times) to rotate.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr,
+ size_t idx);
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Modification Convenience API
+ *============================================================================*/
+
+/**
+ Adds a value at the end of the array.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param val The value to be inserted. Returns false if it is NULL.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr,
+ yyjson_mut_val *val);
+
+/**
+ Adds a `null` value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr);
+
+/**
+ Adds a `true` value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr);
+
+/**
+ Adds a `false` value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr);
+
+/**
+ Adds a bool value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param val The bool value to be added.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ bool val);
+
+/**
+ Adds an unsigned integer value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param num The number to be added.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ uint64_t num);
+
+/**
+ Adds a signed integer value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param num The number to be added.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ int64_t num);
+
+/**
+ Adds a integer value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param num The number to be added.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ int64_t num);
+
+/**
+ Adds a double value at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param num The number to be added.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ double num);
+
+/**
+ Adds a string value at the end of the array (no copy).
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param str A null-terminated UTF-8 string.
+ @return Whether successful.
+ @warning The input string is not copied, you should keep this string unmodified
+ for the lifetime of this JSON document.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str);
+
+/**
+ Adds a string value at the end of the array (no copy).
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param str A UTF-8 string, null-terminator is not required.
+ @param len The length of the string, in bytes.
+ @return Whether successful.
+ @warning The input string is not copied, you should keep this string unmodified
+ for the lifetime of this JSON document.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str,
+ size_t len);
+
+/**
+ Adds a string value at the end of the array (copied).
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param str A null-terminated UTF-8 string.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str);
+
+/**
+ Adds a string value at the end of the array (copied).
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @param str A UTF-8 string, null-terminator is not required.
+ @param len The length of the string, in bytes.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str,
+ size_t len);
+
+/**
+ Creates and adds a new array at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @return The new array, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr);
+
+/**
+ Creates and adds a new object at the end of the array.
+ @param doc The `doc` is only used for memory allocation.
+ @param arr The array to which the value is to be inserted.
+ Returns false if it is NULL or not an array.
+ @return The new object, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr);
+
+
+
+/*==============================================================================
+ * Mutable JSON Object API
+ *============================================================================*/
+
+/** Returns the number of key-value pairs in this object.
+ Returns 0 if `obj` is NULL or type is not object. */
+yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj);
+
+/** Returns the value to which the specified key is mapped.
+ Returns NULL if this object contains no mapping for the key.
+ Returns NULL if `obj/key` is NULL, or type is not object.
+
+ The `key` should be a null-terminated UTF-8 string.
+
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj,
+ const char *key);
+
+/** Returns the value to which the specified key is mapped.
+ Returns NULL if this object contains no mapping for the key.
+ Returns NULL if `obj/key` is NULL, or type is not object.
+
+ The `key` should be a UTF-8 string, null-terminator is not required.
+ The `key_len` should be the length of the key, in bytes.
+
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj,
+ const char *key,
+ size_t key_len);
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Iterator API
+ *============================================================================*/
+
+/**
+ A mutable JSON object iterator.
+
+ @warning You should not modify the object while iterating over it, but you can
+ use `yyjson_mut_obj_iter_remove()` to remove current value.
+
+ @par Example
+ @code
+ yyjson_mut_val *key, *val;
+ yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj);
+ while ((key = yyjson_mut_obj_iter_next(&iter))) {
+ val = yyjson_mut_obj_iter_get_val(key);
+ your_func(key, val);
+ if (your_val_is_unused(key, val)) {
+ yyjson_mut_obj_iter_remove(&iter);
+ }
+ }
+ @endcode
+
+ If the ordering of the keys is known at compile-time, you can use this method
+ to speed up value lookups:
+ @code
+ // {"k1":1, "k2": 3, "k3": 3}
+ yyjson_mut_val *key, *val;
+ yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(obj);
+ yyjson_mut_val *v1 = yyjson_mut_obj_iter_get(&iter, "k1");
+ yyjson_mut_val *v3 = yyjson_mut_obj_iter_get(&iter, "k3");
+ @endcode
+ @see `yyjson_mut_obj_iter_get()` and `yyjson_mut_obj_iter_getn()`
+ */
+typedef struct yyjson_mut_obj_iter {
+ size_t idx; /**< next key's index */
+ size_t max; /**< maximum key index (obj.size) */
+ yyjson_mut_val *cur; /**< current key */
+ yyjson_mut_val *pre; /**< previous key */
+ yyjson_mut_val *obj; /**< the object being iterated */
+} yyjson_mut_obj_iter;
+
+/**
+ Initialize an iterator for this object.
+
+ @param obj The object to be iterated over.
+ If this parameter is NULL or not an array, `iter` will be set to empty.
+ @param iter The iterator to be initialized.
+ If this parameter is NULL, the function will fail and return false.
+ @return true if the `iter` has been successfully initialized.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj,
+ yyjson_mut_obj_iter *iter);
+
+/**
+ Create an iterator with an object, same as `yyjson_obj_iter_init()`.
+
+ @param obj The object to be iterated over.
+ If this parameter is NULL or not an object, an empty iterator will returned.
+ @return A new iterator for the object.
+
+ @note The iterator does not need to be destroyed.
+ */
+yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with(
+ yyjson_mut_val *obj);
+
+/**
+ Returns whether the iteration has more elements.
+ If `iter` is NULL, this function will return false.
+ */
+yyjson_api_inline bool yyjson_mut_obj_iter_has_next(
+ yyjson_mut_obj_iter *iter);
+
+/**
+ Returns the next key in the iteration, or NULL on end.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next(
+ yyjson_mut_obj_iter *iter);
+
+/**
+ Returns the value for key inside the iteration.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val(
+ yyjson_mut_val *key);
+
+/**
+ Removes current key-value pair in the iteration, returns the removed value.
+ If `iter` is NULL, this function will return NULL.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove(
+ yyjson_mut_obj_iter *iter);
+
+/**
+ Iterates to a specified key and returns the value.
+
+ This function does the same thing as `yyjson_mut_obj_get()`, but is much faster
+ if the ordering of the keys is known at compile-time and you are using the same
+ order to look up the values. If the key exists in this object, then the
+ iterator will stop at the next key, otherwise the iterator will not change and
+ NULL is returned.
+
+ @param iter The object iterator, should not be NULL.
+ @param key The key, should be a UTF-8 string with null-terminator.
+ @return The value to which the specified key is mapped.
+ NULL if this object contains no mapping for the key or input is invalid.
+
+ @warning This function takes a linear search time if the key is not nearby.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get(
+ yyjson_mut_obj_iter *iter, const char *key);
+
+/**
+ Iterates to a specified key and returns the value.
+
+ This function does the same thing as `yyjson_mut_obj_getn()` but is much faster
+ if the ordering of the keys is known at compile-time and you are using the same
+ order to look up the values. If the key exists in this object, then the
+ iterator will stop at the next key, otherwise the iterator will not change and
+ NULL is returned.
+
+ @param iter The object iterator, should not be NULL.
+ @param key The key, should be a UTF-8 string, null-terminator is not required.
+ @param key_len The the length of `key`, in bytes.
+ @return The value to which the specified key is mapped.
+ NULL if this object contains no mapping for the key or input is invalid.
+
+ @warning This function takes a linear search time if the key is not nearby.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn(
+ yyjson_mut_obj_iter *iter, const char *key, size_t key_len);
+
+/**
+ Macro for iterating over an object.
+ It works like iterator, but with a more intuitive API.
+
+ @warning You should not modify the object while iterating over it.
+
+ @par Example
+ @code
+ size_t idx, max;
+ yyjson_val *key, *val;
+ yyjson_obj_foreach(obj, idx, max, key, val) {
+ your_func(key, val);
+ }
+ @endcode
+ */
+#define yyjson_mut_obj_foreach(obj, idx, max, key, val) \
+ for ((idx) = 0, \
+ (max) = yyjson_mut_obj_size(obj), \
+ (key) = (max) ? ((yyjson_mut_val *)(obj)->uni.ptr)->next->next : NULL, \
+ (val) = (key) ? (key)->next : NULL; \
+ (idx) < (max); \
+ (idx)++, \
+ (key) = (val)->next, \
+ (val) = (key)->next)
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Creation API
+ *============================================================================*/
+
+/** Creates and returns a mutable object, returns NULL on error. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc);
+
+/**
+ Creates and returns a mutable object with keys and values, returns NULL on
+ error. The keys and values are not copied. The strings should be a
+ null-terminated UTF-8 string.
+
+ @warning The input string is not copied, you should keep this string
+ unmodified for the lifetime of this JSON document.
+
+ @par Example
+ @code
+ const char *keys[2] = { "id", "name" };
+ const char *vals[2] = { "01", "Harry" };
+ yyjson_mut_val *obj = yyjson_mut_obj_with_str(doc, keys, vals, 2);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc,
+ const char **keys,
+ const char **vals,
+ size_t count);
+
+/**
+ Creates and returns a mutable object with key-value pairs and pair count,
+ returns NULL on error. The keys and values are not copied. The strings should
+ be a null-terminated UTF-8 string.
+
+ @warning The input string is not copied, you should keep this string
+ unmodified for the lifetime of this JSON document.
+
+ @par Example
+ @code
+ const char *kv_pairs[4] = { "id", "01", "name", "Harry" };
+ yyjson_mut_val *obj = yyjson_mut_obj_with_kv(doc, kv_pairs, 2);
+ @endcode
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc,
+ const char **kv_pairs,
+ size_t pair_count);
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Modification API
+ *============================================================================*/
+
+/**
+ Adds a key-value pair at the end of the object.
+ This function allows duplicated key in one object.
+ @param obj The object to which the new key-value pair is to be added.
+ @param key The key, should be a string which is created by `yyjson_mut_str()`,
+ `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
+ @param val The value to add to the object.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val);
+/**
+ Sets a key-value pair at the end of the object.
+ This function may remove all key-value pairs for the given key before add.
+ @param obj The object to which the new key-value pair is to be added.
+ @param key The key, should be a string which is created by `yyjson_mut_str()`,
+ `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
+ @param val The value to add to the object. If this value is null, the behavior
+ is same as `yyjson_mut_obj_remove()`.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val);
+
+/**
+ Inserts a key-value pair to the object at the given position.
+ This function allows duplicated key in one object.
+ @param obj The object to which the new key-value pair is to be added.
+ @param key The key, should be a string which is created by `yyjson_mut_str()`,
+ `yyjson_mut_strn()`, `yyjson_mut_strcpy()` or `yyjson_mut_strncpy()`.
+ @param val The value to add to the object.
+ @param idx The index to which to insert the new pair.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val,
+ size_t idx);
+
+/**
+ Removes all key-value pair from the object with given key.
+ @param obj The object from which the key-value pair is to be removed.
+ @param key The key, should be a string value.
+ @return The first matched value, or NULL if no matched value.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj,
+ yyjson_mut_val *key);
+
+/**
+ Removes all key-value pair from the object with given key.
+ @param obj The object from which the key-value pair is to be removed.
+ @param key The key, should be a UTF-8 string with null-terminator.
+ @return The first matched value, or NULL if no matched value.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key(
+ yyjson_mut_val *obj, const char *key);
+
+/**
+ Removes all key-value pair from the object with given key.
+ @param obj The object from which the key-value pair is to be removed.
+ @param key The key, should be a UTF-8 string, null-terminator is not required.
+ @param key_len The length of the key.
+ @return The first matched value, or NULL if no matched value.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn(
+ yyjson_mut_val *obj, const char *key, size_t key_len);
+
+/**
+ Removes all key-value pairs in this object.
+ @param obj The object from which all of the values are to be removed.
+ @return Whether successful.
+ */
+yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj);
+
+/**
+ Replaces value from the object with given key.
+ If the key is not exist, or the value is NULL, it will fail.
+ @param obj The object to which the value is to be replaced.
+ @param key The key, should be a string value.
+ @param val The value to replace into the object.
+ @return Whether successful.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val);
+
+/**
+ Rotates key-value pairs in the object for the given number of times.
+ For example: `{"a":1,"b":2,"c":3,"d":4}` rotate 1 is
+ `{"b":2,"c":3,"d":4,"a":1}`.
+ @param obj The object to be rotated.
+ @param idx Index (or times) to rotate.
+ @return Whether successful.
+ @warning This function takes a linear search time.
+ */
+yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
+ size_t idx);
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Modification Convenience API
+ *============================================================================*/
+
+/** Adds a `null` value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key);
+
+/** Adds a `true` value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key);
+
+/** Adds a `false` value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key);
+
+/** Adds a bool value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key, bool val);
+
+/** Adds an unsigned integer value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key, uint64_t val);
+
+/** Adds a signed integer value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key, int64_t val);
+
+/** Adds an int value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key, int64_t val);
+
+/** Adds a double value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key, double val);
+
+/** Adds a string value at the end of the object.
+ The `key` and `val` should be null-terminated UTF-8 strings.
+ This function allows duplicated key in one object.
+
+ @warning The key/value strings are not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key, const char *val);
+
+/** Adds a string value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ The `val` should be a UTF-8 string, null-terminator is not required.
+ The `len` should be the length of the `val`, in bytes.
+ This function allows duplicated key in one object.
+
+ @warning The key/value strings are not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ const char *val, size_t len);
+
+/** Adds a string value at the end of the object.
+ The `key` and `val` should be null-terminated UTF-8 strings.
+ The value string is copied.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ const char *val);
+
+/** Adds a string value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ The `val` should be a UTF-8 string, null-terminator is not required.
+ The `len` should be the length of the `val`, in bytes.
+ This function allows duplicated key in one object.
+
+ @warning The key strings are not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ const char *val, size_t len);
+
+/**
+ Creates and adds a new array to the target object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document.
+ @return The new array, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key);
+
+/**
+ Creates and adds a new object to the target object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep these strings
+ unmodified for the lifetime of this JSON document.
+ @return The new object, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key);
+
+/** Adds a JSON value at the end of the object.
+ The `key` should be a null-terminated UTF-8 string.
+ This function allows duplicated key in one object.
+
+ @warning The key string is not copied, you should keep the string
+ unmodified for the lifetime of this JSON document. */
+yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ yyjson_mut_val *val);
+
+/** Removes all key-value pairs for the given key.
+ Returns the first value to which the specified key is mapped or NULL if this
+ object contains no mapping for the key.
+ The `key` should be a null-terminated UTF-8 string.
+
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(
+ yyjson_mut_val *obj, const char *key);
+
+/** Removes all key-value pairs for the given key.
+ Returns the first value to which the specified key is mapped or NULL if this
+ object contains no mapping for the key.
+ The `key` should be a UTF-8 string, null-terminator is not required.
+ The `len` should be the length of the key, in bytes.
+
+ @warning This function takes a linear search time. */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn(
+ yyjson_mut_val *obj, const char *key, size_t len);
+
+/** Replaces all matching keys with the new key.
+ Returns true if at least one key was renamed.
+ The `key` and `new_key` should be a null-terminated UTF-8 string.
+ The `new_key` is copied and held by doc.
+
+ @warning This function takes a linear search time.
+ If `new_key` already exists, it will cause duplicate keys.
+ */
+yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ const char *new_key);
+
+/** Replaces all matching keys with the new key.
+ Returns true if at least one key was renamed.
+ The `key` and `new_key` should be a UTF-8 string,
+ null-terminator is not required. The `new_key` is copied and held by doc.
+
+ @warning This function takes a linear search time.
+ If `new_key` already exists, it will cause duplicate keys.
+ */
+yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ size_t len,
+ const char *new_key,
+ size_t new_len);
+
+
+
+/*==============================================================================
+ * JSON Pointer API (RFC 6901)
+ * https://tools.ietf.org/html/rfc6901
+ *============================================================================*/
+
+/** JSON Pointer error code. */
+typedef uint32_t yyjson_ptr_code;
+
+/** No JSON pointer error. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_NONE = 0;
+
+/** Invalid input parameter, such as NULL input. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_PARAMETER = 1;
+
+/** JSON pointer syntax error, such as invalid escape, token no prefix. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_SYNTAX = 2;
+
+/** JSON pointer resolve failed, such as index out of range, key not found. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_RESOLVE = 3;
+
+/** Document's root is NULL, but it is required for the function call. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_NULL_ROOT = 4;
+
+/** Cannot set root as the target is not a document. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_SET_ROOT = 5;
+
+/** The memory allocation failed and a new value could not be created. */
+static const yyjson_ptr_code YYJSON_PTR_ERR_MEMORY_ALLOCATION = 6;
+
+/** Error information for JSON pointer. */
+typedef struct yyjson_ptr_err {
+ /** Error code, see `yyjson_ptr_code` for all possible values. */
+ yyjson_ptr_code code;
+ /** Error message, constant, no need to free (NULL if no error). */
+ const char *msg;
+ /** Error byte position for input JSON pointer (0 if no error). */
+ size_t pos;
+} yyjson_ptr_err;
+
+/**
+ A context for JSON pointer operation.
+
+ This struct stores the context of JSON Pointer operation result. The struct
+ can be used with three helper functions: `ctx_append()`, `ctx_replace()`, and
+ `ctx_remove()`, which perform the corresponding operations on the container
+ without re-parsing the JSON Pointer.
+
+ For example:
+ @code
+ // doc before: {"a":[0,1,null]}
+ // ptr: "/a/2"
+ val = yyjson_mut_doc_ptr_getx(doc, ptr, strlen(ptr), &ctx, &err);
+ if (yyjson_is_null(val)) {
+ yyjson_ptr_ctx_remove(&ctx);
+ }
+ // doc after: {"a":[0,1]}
+ @endcode
+ */
+typedef struct yyjson_ptr_ctx {
+ /**
+ The container (parent) of the target value. It can be either an array or
+ an object. If the target location has no value, but all its parent
+ containers exist, and the target location can be used to insert a new
+ value, then `ctn` is the parent container of the target location.
+ Otherwise, `ctn` is NULL.
+ */
+ yyjson_mut_val *ctn;
+ /**
+ The previous sibling of the target value. It can be either a value in an
+ array or a key in an object. As the container is a `circular linked list`
+ of elements, `pre` is the previous node of the target value. If the
+ operation is `add` or `set`, then `pre` is the previous node of the new
+ value, not the original target value. If the target value does not exist,
+ `pre` is NULL.
+ */
+ yyjson_mut_val *pre;
+ /**
+ The removed value if the operation is `set`, `replace` or `remove`. It can
+ be used to restore the original state of the document if needed.
+ */
+ yyjson_mut_val *old;
+} yyjson_ptr_ctx;
+
+/**
+ Get value by a JSON Pointer.
+ @param doc The JSON document to be queried.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @return The value referenced by the JSON pointer.
+ NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc,
+ const char *ptr);
+
+/**
+ Get value by a JSON Pointer.
+ @param doc The JSON document to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @return The value referenced by the JSON pointer.
+ NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc,
+ const char *ptr, size_t len);
+
+/**
+ Get value by a JSON Pointer.
+ @param doc The JSON document to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The value referenced by the JSON pointer.
+ NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_ptr_err *err);
+
+/**
+ Get value by a JSON Pointer.
+ @param val The JSON value to be queried.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @return The value referenced by the JSON pointer.
+ NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val,
+ const char *ptr);
+
+/**
+ Get value by a JSON Pointer.
+ @param val The JSON value to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @return The value referenced by the JSON pointer.
+ NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val,
+ const char *ptr, size_t len);
+
+/**
+ Get value by a JSON Pointer.
+ @param val The JSON value to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The value referenced by the JSON pointer.
+ NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val,
+ const char *ptr, size_t len,
+ yyjson_ptr_err *err);
+
+/**
+ Get value by a JSON Pointer.
+ @param doc The JSON document to be queried.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @return The value referenced by the JSON pointer.
+ NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc,
+ const char *ptr);
+
+/**
+ Get value by a JSON Pointer.
+ @param doc The JSON document to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @return The value referenced by the JSON pointer.
+ NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc,
+ const char *ptr,
+ size_t len);
+
+/**
+ Get value by a JSON Pointer.
+ @param doc The JSON document to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The value referenced by the JSON pointer.
+ NULL if `doc` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Get value by a JSON Pointer.
+ @param val The JSON value to be queried.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @return The value referenced by the JSON pointer.
+ NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val,
+ const char *ptr);
+
+/**
+ Get value by a JSON Pointer.
+ @param val The JSON value to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @return The value referenced by the JSON pointer.
+ NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len);
+
+/**
+ Get value by a JSON Pointer.
+ @param val The JSON value to be queried.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The value referenced by the JSON pointer.
+ NULL if `val` or `ptr` is NULL, or the JSON pointer cannot be resolved.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Add (insert) value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @param new_val The value to be added.
+ @return true if JSON pointer is valid and new value is added, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ */
+yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc,
+ const char *ptr,
+ yyjson_mut_val *new_val);
+
+/**
+ Add (insert) value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The value to be added.
+ @return true if JSON pointer is valid and new value is added, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ */
+yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val);
+
+/**
+ Add (insert) value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The value to be added.
+ @param create_parent Whether to create parent nodes if not exist.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return true if JSON pointer is valid and new value is added, false otherwise.
+ */
+yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Add (insert) value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @param doc Only used to create new values when needed.
+ @param new_val The value to be added.
+ @return true if JSON pointer is valid and new value is added, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ */
+yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val,
+ const char *ptr,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc);
+
+/**
+ Add (insert) value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param doc Only used to create new values when needed.
+ @param new_val The value to be added.
+ @return true if JSON pointer is valid and new value is added, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ */
+yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc);
+
+/**
+ Add (insert) value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param doc Only used to create new values when needed.
+ @param new_val The value to be added.
+ @param create_parent Whether to create parent nodes if not exist.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return true if JSON pointer is valid and new value is added, false otherwise.
+ */
+yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Set value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @param new_val The value to be set, pass NULL to remove.
+ @return true if JSON pointer is valid and new value is set, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ If the target value already exists, it will be replaced by the new value.
+ */
+yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc,
+ const char *ptr,
+ yyjson_mut_val *new_val);
+
+/**
+ Set value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The value to be set, pass NULL to remove.
+ @return true if JSON pointer is valid and new value is set, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ If the target value already exists, it will be replaced by the new value.
+ */
+yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val);
+
+/**
+ Set value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The value to be set, pass NULL to remove.
+ @param create_parent Whether to create parent nodes if not exist.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return true if JSON pointer is valid and new value is set, false otherwise.
+ @note If the target value already exists, it will be replaced by the new value.
+ */
+yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Set value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @param new_val The value to be set, pass NULL to remove.
+ @param doc Only used to create new values when needed.
+ @return true if JSON pointer is valid and new value is set, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ If the target value already exists, it will be replaced by the new value.
+ */
+yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val,
+ const char *ptr,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc);
+
+/**
+ Set value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The value to be set, pass NULL to remove.
+ @param doc Only used to create new values when needed.
+ @return true if JSON pointer is valid and new value is set, false otherwise.
+ @note The parent nodes will be created if they do not exist.
+ If the target value already exists, it will be replaced by the new value.
+ */
+yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc);
+
+/**
+ Set value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The value to be set, pass NULL to remove.
+ @param doc Only used to create new values when needed.
+ @param create_parent Whether to create parent nodes if not exist.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return true if JSON pointer is valid and new value is set, false otherwise.
+ @note If the target value already exists, it will be replaced by the new value.
+ */
+yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Replace value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @param new_val The new value to replace the old one.
+ @return The old value that was replaced, or NULL if not found.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace(
+ yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val);
+
+/**
+ Replace value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The new value to replace the old one.
+ @return The old value that was replaced, or NULL if not found.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen(
+ yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val);
+
+/**
+ Replace value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The new value to replace the old one.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The old value that was replaced, or NULL if not found.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex(
+ yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
+
+/**
+ Replace value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @param new_val The new value to replace the old one.
+ @return The old value that was replaced, or NULL if not found.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace(
+ yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val);
+
+/**
+ Replace value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The new value to replace the old one.
+ @return The old value that was replaced, or NULL if not found.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen(
+ yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val);
+
+/**
+ Replace value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param new_val The new value to replace the old one.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The old value that was replaced, or NULL if not found.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex(
+ yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
+
+/**
+ Remove value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @return The removed value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove(
+ yyjson_mut_doc *doc, const char *ptr);
+
+/**
+ Remove value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @return The removed value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen(
+ yyjson_mut_doc *doc, const char *ptr, size_t len);
+
+/**
+ Remove value by a JSON pointer.
+ @param doc The target JSON document.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The removed value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex(
+ yyjson_mut_doc *doc, const char *ptr, size_t len,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
+
+/**
+ Remove value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8 with null-terminator).
+ @return The removed value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val,
+ const char *ptr);
+
+/**
+ Remove value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @return The removed value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len);
+
+/**
+ Remove value by a JSON pointer.
+ @param val The target JSON value.
+ @param ptr The JSON pointer string (UTF-8, null-terminator is not required).
+ @param len The length of `ptr` in bytes.
+ @param ctx A pointer to store the result context, or NULL if not needed.
+ @param err A pointer to store the error information, or NULL if not needed.
+ @return The removed value, or NULL on error.
+ */
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/**
+ Append value by JSON pointer context.
+ @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
+ @param key New key if `ctx->ctn` is object, or NULL if `ctx->ctn` is array.
+ @param val New value to be added.
+ @return true on success or false on fail.
+ */
+yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val);
+
+/**
+ Replace value by JSON pointer context.
+ @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
+ @param val New value to be replaced.
+ @return true on success or false on fail.
+ @note If success, the old value will be returned via `ctx->old`.
+ */
+yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx,
+ yyjson_mut_val *val);
+
+/**
+ Remove value by JSON pointer context.
+ @param ctx The context from the `yyjson_mut_ptr_xxx()` calls.
+ @return true on success or false on fail.
+ @note If success, the old value will be returned via `ctx->old`.
+ */
+yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx);
+
+
+
+/*==============================================================================
+ * JSON Patch API (RFC 6902)
+ * https://tools.ietf.org/html/rfc6902
+ *============================================================================*/
+
+/** Result code for JSON patch. */
+typedef uint32_t yyjson_patch_code;
+
+/** Success, no error. */
+static const yyjson_patch_code YYJSON_PATCH_SUCCESS = 0;
+
+/** Invalid parameter, such as NULL input or non-array patch. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_PARAMETER = 1;
+
+/** Memory allocation failure occurs. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_MEMORY_ALLOCATION = 2;
+
+/** JSON patch operation is not object type. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_OPERATION = 3;
+
+/** JSON patch operation is missing a required key. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_MISSING_KEY = 4;
+
+/** JSON patch operation member is invalid. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_INVALID_MEMBER = 5;
+
+/** JSON patch operation `test` not equal. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_EQUAL = 6;
+
+/** JSON patch operation failed on JSON pointer. */
+static const yyjson_patch_code YYJSON_PATCH_ERROR_POINTER = 7;
+
+/** Error information for JSON patch. */
+typedef struct yyjson_patch_err {
+ /** Error code, see `yyjson_patch_code` for all possible values. */
+ yyjson_patch_code code;
+ /** Index of the error operation (0 if no error). */
+ size_t idx;
+ /** Error message, constant, no need to free (NULL if no error). */
+ const char *msg;
+ /** JSON pointer error if `code == YYJSON_PATCH_ERROR_POINTER`. */
+ yyjson_ptr_err ptr;
+} yyjson_patch_err;
+
+/**
+ Creates and returns a patched JSON value (RFC 6902).
+ The memory of the returned value is allocated by the `doc`.
+ The `err` is used to receive error information, pass NULL if not needed.
+ Returns NULL if the patch could not be applied.
+ */
+yyjson_api yyjson_mut_val *yyjson_patch(yyjson_mut_doc *doc,
+ yyjson_val *orig,
+ yyjson_val *patch,
+ yyjson_patch_err *err);
+
+/**
+ Creates and returns a patched JSON value (RFC 6902).
+ The memory of the returned value is allocated by the `doc`.
+ The `err` is used to receive error information, pass NULL if not needed.
+ Returns NULL if the patch could not be applied.
+ */
+yyjson_api yyjson_mut_val *yyjson_mut_patch(yyjson_mut_doc *doc,
+ yyjson_mut_val *orig,
+ yyjson_mut_val *patch,
+ yyjson_patch_err *err);
+
+
+
+/*==============================================================================
+ * JSON Merge-Patch API (RFC 7386)
+ * https://tools.ietf.org/html/rfc7386
+ *============================================================================*/
+
+/**
+ Creates and returns a merge-patched JSON value (RFC 7386).
+ The memory of the returned value is allocated by the `doc`.
+ Returns NULL if the patch could not be applied.
+
+ @warning This function is recursive and may cause a stack overflow if the
+ object level is too deep.
+ */
+yyjson_api yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc,
+ yyjson_val *orig,
+ yyjson_val *patch);
+
+/**
+ Creates and returns a merge-patched JSON value (RFC 7386).
+ The memory of the returned value is allocated by the `doc`.
+ Returns NULL if the patch could not be applied.
+
+ @warning This function is recursive and may cause a stack overflow if the
+ object level is too deep.
+ */
+yyjson_api yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc,
+ yyjson_mut_val *orig,
+ yyjson_mut_val *patch);
+
+
+
+/*==============================================================================
+ * JSON Structure (Implementation)
+ *============================================================================*/
+
+/** Payload of a JSON value (8 bytes). */
+typedef union yyjson_val_uni {
+ uint64_t u64;
+ int64_t i64;
+ double f64;
+ const char *str;
+ void *ptr;
+ size_t ofs;
+} yyjson_val_uni;
+
+/**
+ Immutable JSON value, 16 bytes.
+ */
+struct yyjson_val {
+ uint64_t tag; /**< type, subtype and length */
+ yyjson_val_uni uni; /**< payload */
+};
+
+struct yyjson_doc {
+ /** Root value of the document (nonnull). */
+ yyjson_val *root;
+ /** Allocator used by document (nonnull). */
+ yyjson_alc alc;
+ /** The total number of bytes read when parsing JSON (nonzero). */
+ size_t dat_read;
+ /** The total number of value read when parsing JSON (nonzero). */
+ size_t val_read;
+ /** The string pool used by JSON values (nullable). */
+ char *str_pool;
+};
+
+
+
+/*==============================================================================
+ * Unsafe JSON Value API (Implementation)
+ *============================================================================*/
+
+/*
+ Whether the string does not need to be escaped for serialization.
+ This function is used to optimize the writing speed of small constant strings.
+ This function works only if the compiler can evaluate it at compile time.
+
+ Clang supports it since v8.0,
+ earlier versions do not support constant_p(strlen) and return false.
+ GCC supports it since at least v4.4,
+ earlier versions may compile it as run-time instructions.
+ ICC supports it since at least v16,
+ earlier versions are uncertain.
+
+ @param str The C string.
+ @param len The returnd value from strlen(str).
+ */
+yyjson_api_inline bool unsafe_yyjson_is_str_noesc(const char *str, size_t len) {
+#if YYJSON_HAS_CONSTANT_P && \
+ (!YYJSON_IS_REAL_GCC || yyjson_gcc_available(4, 4, 0))
+ if (yyjson_constant_p(len) && len <= 32) {
+ /*
+ Same as the following loop:
+
+ for (size_t i = 0; i < len; i++) {
+ char c = str[i];
+ if (c < ' ' || c > '~' || c == '"' || c == '\\') return false;
+ }
+
+ GCC evaluates it at compile time only if the string length is within 17
+ and -O3 (which turns on the -fpeel-loops flag) is used.
+ So the loop is unrolled for GCC.
+ */
+# define yyjson_repeat32_incr(x) \
+ x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) \
+ x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) \
+ x(16) x(17) x(18) x(19) x(20) x(21) x(22) x(23) \
+ x(24) x(25) x(26) x(27) x(28) x(29) x(30) x(31)
+# define yyjson_check_char_noesc(i) \
+ if (i < len) { \
+ char c = str[i]; \
+ if (c < ' ' || c > '~' || c == '"' || c == '\\') return false; }
+ yyjson_repeat32_incr(yyjson_check_char_noesc)
+# undef yyjson_repeat32_incr
+# undef yyjson_check_char_noesc
+ return true;
+ }
+#else
+ (void)str;
+ (void)len;
+#endif
+ return false;
+}
+
+yyjson_api_inline yyjson_type unsafe_yyjson_get_type(void *val) {
+ uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
+ return (yyjson_type)(tag & YYJSON_TYPE_MASK);
+}
+
+yyjson_api_inline yyjson_subtype unsafe_yyjson_get_subtype(void *val) {
+ uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
+ return (yyjson_subtype)(tag & YYJSON_SUBTYPE_MASK);
+}
+
+yyjson_api_inline uint8_t unsafe_yyjson_get_tag(void *val) {
+ uint8_t tag = (uint8_t)((yyjson_val *)val)->tag;
+ return (uint8_t)(tag & YYJSON_TAG_MASK);
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_raw(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_RAW;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_null(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NULL;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_bool(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_BOOL;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_num(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_NUM;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_str(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_STR;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_arr(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_ARR;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_obj(void *val) {
+ return unsafe_yyjson_get_type(val) == YYJSON_TYPE_OBJ;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_ctn(void *val) {
+ uint8_t mask = YYJSON_TYPE_ARR & YYJSON_TYPE_OBJ;
+ return (unsafe_yyjson_get_tag(val) & mask) == mask;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_uint(void *val) {
+ const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ return unsafe_yyjson_get_tag(val) == patt;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_sint(void *val) {
+ const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ return unsafe_yyjson_get_tag(val) == patt;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_int(void *val) {
+ const uint8_t mask = YYJSON_TAG_MASK & (~YYJSON_SUBTYPE_SINT);
+ const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ return (unsafe_yyjson_get_tag(val) & mask) == patt;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_real(void *val) {
+ const uint8_t patt = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ return unsafe_yyjson_get_tag(val) == patt;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_true(void *val) {
+ const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
+ return unsafe_yyjson_get_tag(val) == patt;
+}
+
+yyjson_api_inline bool unsafe_yyjson_is_false(void *val) {
+ const uint8_t patt = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
+ return unsafe_yyjson_get_tag(val) == patt;
+}
+
+yyjson_api_inline bool unsafe_yyjson_arr_is_flat(yyjson_val *val) {
+ size_t ofs = val->uni.ofs;
+ size_t len = (size_t)(val->tag >> YYJSON_TAG_BIT);
+ return len * sizeof(yyjson_val) + sizeof(yyjson_val) == ofs;
+}
+
+yyjson_api_inline const char *unsafe_yyjson_get_raw(void *val) {
+ return ((yyjson_val *)val)->uni.str;
+}
+
+yyjson_api_inline bool unsafe_yyjson_get_bool(void *val) {
+ uint8_t tag = unsafe_yyjson_get_tag(val);
+ return (bool)((tag & YYJSON_SUBTYPE_MASK) >> YYJSON_TYPE_BIT);
+}
+
+yyjson_api_inline uint64_t unsafe_yyjson_get_uint(void *val) {
+ return ((yyjson_val *)val)->uni.u64;
+}
+
+yyjson_api_inline int64_t unsafe_yyjson_get_sint(void *val) {
+ return ((yyjson_val *)val)->uni.i64;
+}
+
+yyjson_api_inline int unsafe_yyjson_get_int(void *val) {
+ return (int)((yyjson_val *)val)->uni.i64;
+}
+
+yyjson_api_inline double unsafe_yyjson_get_real(void *val) {
+ return ((yyjson_val *)val)->uni.f64;
+}
+
+yyjson_api_inline double unsafe_yyjson_get_num(void *val) {
+ uint8_t tag = unsafe_yyjson_get_tag(val);
+ if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL)) {
+ return ((yyjson_val *)val)->uni.f64;
+ } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT)) {
+ return (double)((yyjson_val *)val)->uni.i64;
+ } else if (tag == (YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT)) {
+#if YYJSON_U64_TO_F64_NO_IMPL
+ uint64_t msb = ((uint64_t)1) << 63;
+ uint64_t num = ((yyjson_val *)val)->uni.u64;
+ if ((num & msb) == 0) {
+ return (double)(int64_t)num;
+ } else {
+ return ((double)(int64_t)((num >> 1) | (num & 1))) * (double)2.0;
+ }
+#else
+ return (double)((yyjson_val *)val)->uni.u64;
+#endif
+ }
+ return 0.0;
+}
+
+yyjson_api_inline const char *unsafe_yyjson_get_str(void *val) {
+ return ((yyjson_val *)val)->uni.str;
+}
+
+yyjson_api_inline size_t unsafe_yyjson_get_len(void *val) {
+ return (size_t)(((yyjson_val *)val)->tag >> YYJSON_TAG_BIT);
+}
+
+yyjson_api_inline yyjson_val *unsafe_yyjson_get_first(yyjson_val *ctn) {
+ return ctn + 1;
+}
+
+yyjson_api_inline yyjson_val *unsafe_yyjson_get_next(yyjson_val *val) {
+ bool is_ctn = unsafe_yyjson_is_ctn(val);
+ size_t ctn_ofs = val->uni.ofs;
+ size_t ofs = (is_ctn ? ctn_ofs : sizeof(yyjson_val));
+ return (yyjson_val *)(void *)((uint8_t *)val + ofs);
+}
+
+yyjson_api_inline bool unsafe_yyjson_equals_strn(void *val, const char *str,
+ size_t len) {
+ return unsafe_yyjson_get_len(val) == len &&
+ memcmp(((yyjson_val *)val)->uni.str, str, len) == 0;
+}
+
+yyjson_api_inline bool unsafe_yyjson_equals_str(void *val, const char *str) {
+ return unsafe_yyjson_equals_strn(val, str, strlen(str));
+}
+
+yyjson_api_inline void unsafe_yyjson_set_type(void *val, yyjson_type type,
+ yyjson_subtype subtype) {
+ uint8_t tag = (type | subtype);
+ uint64_t new_tag = ((yyjson_val *)val)->tag;
+ new_tag = (new_tag & (~(uint64_t)YYJSON_TAG_MASK)) | (uint64_t)tag;
+ ((yyjson_val *)val)->tag = new_tag;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_len(void *val, size_t len) {
+ uint64_t tag = ((yyjson_val *)val)->tag & YYJSON_TAG_MASK;
+ tag |= (uint64_t)len << YYJSON_TAG_BIT;
+ ((yyjson_val *)val)->tag = tag;
+}
+
+yyjson_api_inline void unsafe_yyjson_inc_len(void *val) {
+ uint64_t tag = ((yyjson_val *)val)->tag;
+ tag += (uint64_t)(1 << YYJSON_TAG_BIT);
+ ((yyjson_val *)val)->tag = tag;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_raw(void *val, const char *raw,
+ size_t len) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_RAW, YYJSON_SUBTYPE_NONE);
+ unsafe_yyjson_set_len(val, len);
+ ((yyjson_val *)val)->uni.str = raw;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_null(void *val) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_NULL, YYJSON_SUBTYPE_NONE);
+ unsafe_yyjson_set_len(val, 0);
+}
+
+yyjson_api_inline void unsafe_yyjson_set_bool(void *val, bool num) {
+ yyjson_subtype subtype = num ? YYJSON_SUBTYPE_TRUE : YYJSON_SUBTYPE_FALSE;
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_BOOL, subtype);
+ unsafe_yyjson_set_len(val, 0);
+}
+
+yyjson_api_inline void unsafe_yyjson_set_uint(void *val, uint64_t num) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_UINT);
+ unsafe_yyjson_set_len(val, 0);
+ ((yyjson_val *)val)->uni.u64 = num;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_sint(void *val, int64_t num) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_SINT);
+ unsafe_yyjson_set_len(val, 0);
+ ((yyjson_val *)val)->uni.i64 = num;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_real(void *val, double num) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_NUM, YYJSON_SUBTYPE_REAL);
+ unsafe_yyjson_set_len(val, 0);
+ ((yyjson_val *)val)->uni.f64 = num;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_str(void *val, const char *str) {
+ size_t len = strlen(str);
+ bool noesc = unsafe_yyjson_is_str_noesc(str, len);
+ yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, sub);
+ unsafe_yyjson_set_len(val, len);
+ ((yyjson_val *)val)->uni.str = str;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_strn(void *val, const char *str,
+ size_t len) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_STR, YYJSON_SUBTYPE_NONE);
+ unsafe_yyjson_set_len(val, len);
+ ((yyjson_val *)val)->uni.str = str;
+}
+
+yyjson_api_inline void unsafe_yyjson_set_arr(void *val, size_t size) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_ARR, YYJSON_SUBTYPE_NONE);
+ unsafe_yyjson_set_len(val, size);
+}
+
+yyjson_api_inline void unsafe_yyjson_set_obj(void *val, size_t size) {
+ unsafe_yyjson_set_type(val, YYJSON_TYPE_OBJ, YYJSON_SUBTYPE_NONE);
+ unsafe_yyjson_set_len(val, size);
+}
+
+
+
+/*==============================================================================
+ * JSON Document API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_val *yyjson_doc_get_root(yyjson_doc *doc) {
+ return doc ? doc->root : NULL;
+}
+
+yyjson_api_inline size_t yyjson_doc_get_read_size(yyjson_doc *doc) {
+ return doc ? doc->dat_read : 0;
+}
+
+yyjson_api_inline size_t yyjson_doc_get_val_count(yyjson_doc *doc) {
+ return doc ? doc->val_read : 0;
+}
+
+yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc) {
+ if (doc) {
+ yyjson_alc alc = doc->alc;
+ memset(&doc->alc, 0, sizeof(alc));
+ if (doc->str_pool) alc.free(alc.ctx, doc->str_pool);
+ alc.free(alc.ctx, doc);
+ }
+}
+
+
+
+/*==============================================================================
+ * JSON Value Type API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_is_raw(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_raw(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_null(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_null(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_true(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_true(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_false(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_false(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_bool(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_bool(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_uint(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_uint(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_sint(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_sint(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_int(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_int(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_real(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_real(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_num(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_num(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_str(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_str(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_arr(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_arr(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_obj(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_obj(val) : false;
+}
+
+yyjson_api_inline bool yyjson_is_ctn(yyjson_val *val) {
+ return val ? unsafe_yyjson_is_ctn(val) : false;
+}
+
+
+
+/*==============================================================================
+ * JSON Value Content API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_type yyjson_get_type(yyjson_val *val) {
+ return val ? unsafe_yyjson_get_type(val) : YYJSON_TYPE_NONE;
+}
+
+yyjson_api_inline yyjson_subtype yyjson_get_subtype(yyjson_val *val) {
+ return val ? unsafe_yyjson_get_subtype(val) : YYJSON_SUBTYPE_NONE;
+}
+
+yyjson_api_inline uint8_t yyjson_get_tag(yyjson_val *val) {
+ return val ? unsafe_yyjson_get_tag(val) : 0;
+}
+
+yyjson_api_inline const char *yyjson_get_type_desc(yyjson_val *val) {
+ switch (yyjson_get_tag(val)) {
+ case YYJSON_TYPE_RAW | YYJSON_SUBTYPE_NONE: return "raw";
+ case YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE: return "null";
+ case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NONE: return "string";
+ case YYJSON_TYPE_STR | YYJSON_SUBTYPE_NOESC: return "string";
+ case YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE: return "array";
+ case YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE: return "object";
+ case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE: return "true";
+ case YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE: return "false";
+ case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT: return "uint";
+ case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT: return "sint";
+ case YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL: return "real";
+ default: return "unknown";
+ }
+}
+
+yyjson_api_inline const char *yyjson_get_raw(yyjson_val *val) {
+ return yyjson_is_raw(val) ? unsafe_yyjson_get_raw(val) : NULL;
+}
+
+yyjson_api_inline bool yyjson_get_bool(yyjson_val *val) {
+ return yyjson_is_bool(val) ? unsafe_yyjson_get_bool(val) : false;
+}
+
+yyjson_api_inline uint64_t yyjson_get_uint(yyjson_val *val) {
+ return yyjson_is_int(val) ? unsafe_yyjson_get_uint(val) : 0;
+}
+
+yyjson_api_inline int64_t yyjson_get_sint(yyjson_val *val) {
+ return yyjson_is_int(val) ? unsafe_yyjson_get_sint(val) : 0;
+}
+
+yyjson_api_inline int yyjson_get_int(yyjson_val *val) {
+ return yyjson_is_int(val) ? unsafe_yyjson_get_int(val) : 0;
+}
+
+yyjson_api_inline double yyjson_get_real(yyjson_val *val) {
+ return yyjson_is_real(val) ? unsafe_yyjson_get_real(val) : 0.0;
+}
+
+yyjson_api_inline double yyjson_get_num(yyjson_val *val) {
+ return val ? unsafe_yyjson_get_num(val) : 0.0;
+}
+
+yyjson_api_inline const char *yyjson_get_str(yyjson_val *val) {
+ return yyjson_is_str(val) ? unsafe_yyjson_get_str(val) : NULL;
+}
+
+yyjson_api_inline size_t yyjson_get_len(yyjson_val *val) {
+ return val ? unsafe_yyjson_get_len(val) : 0;
+}
+
+yyjson_api_inline bool yyjson_equals_str(yyjson_val *val, const char *str) {
+ if (yyjson_likely(val && str)) {
+ return unsafe_yyjson_is_str(val) &&
+ unsafe_yyjson_equals_str(val, str);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_equals_strn(yyjson_val *val, const char *str,
+ size_t len) {
+ if (yyjson_likely(val && str)) {
+ return unsafe_yyjson_is_str(val) &&
+ unsafe_yyjson_equals_strn(val, str, len);
+ }
+ return false;
+}
+
+yyjson_api bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs);
+
+yyjson_api_inline bool yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) {
+ if (yyjson_unlikely(!lhs || !rhs)) return false;
+ return unsafe_yyjson_equals(lhs, rhs);
+}
+
+yyjson_api_inline bool yyjson_set_raw(yyjson_val *val,
+ const char *raw, size_t len) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_raw(val, raw, len);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_null(yyjson_val *val) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_null(val);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_bool(yyjson_val *val, bool num) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_bool(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_uint(yyjson_val *val, uint64_t num) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_uint(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_sint(yyjson_val *val, int64_t num) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_sint(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_int(yyjson_val *val, int num) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_sint(val, (int64_t)num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_real(yyjson_val *val, double num) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ unsafe_yyjson_set_real(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_str(yyjson_val *val, const char *str) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ if (yyjson_unlikely(!str)) return false;
+ unsafe_yyjson_set_str(val, str);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_set_strn(yyjson_val *val,
+ const char *str, size_t len) {
+ if (yyjson_unlikely(!val || unsafe_yyjson_is_ctn(val))) return false;
+ if (yyjson_unlikely(!str)) return false;
+ unsafe_yyjson_set_strn(val, str, len);
+ return true;
+}
+
+
+
+/*==============================================================================
+ * JSON Array API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline size_t yyjson_arr_size(yyjson_val *arr) {
+ return yyjson_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0;
+}
+
+yyjson_api_inline yyjson_val *yyjson_arr_get(yyjson_val *arr, size_t idx) {
+ if (yyjson_likely(yyjson_is_arr(arr))) {
+ if (yyjson_likely(unsafe_yyjson_get_len(arr) > idx)) {
+ yyjson_val *val = unsafe_yyjson_get_first(arr);
+ if (unsafe_yyjson_arr_is_flat(arr)) {
+ return val + idx;
+ } else {
+ while (idx-- > 0) val = unsafe_yyjson_get_next(val);
+ return val;
+ }
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_val *yyjson_arr_get_first(yyjson_val *arr) {
+ if (yyjson_likely(yyjson_is_arr(arr))) {
+ if (yyjson_likely(unsafe_yyjson_get_len(arr) > 0)) {
+ return unsafe_yyjson_get_first(arr);
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_val *yyjson_arr_get_last(yyjson_val *arr) {
+ if (yyjson_likely(yyjson_is_arr(arr))) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (yyjson_likely(len > 0)) {
+ yyjson_val *val = unsafe_yyjson_get_first(arr);
+ if (unsafe_yyjson_arr_is_flat(arr)) {
+ return val + (len - 1);
+ } else {
+ while (len-- > 1) val = unsafe_yyjson_get_next(val);
+ return val;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * JSON Array Iterator API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_arr_iter_init(yyjson_val *arr,
+ yyjson_arr_iter *iter) {
+ if (yyjson_likely(yyjson_is_arr(arr) && iter)) {
+ iter->idx = 0;
+ iter->max = unsafe_yyjson_get_len(arr);
+ iter->cur = unsafe_yyjson_get_first(arr);
+ return true;
+ }
+ if (iter) memset(iter, 0, sizeof(yyjson_arr_iter));
+ return false;
+}
+
+yyjson_api_inline yyjson_arr_iter yyjson_arr_iter_with(yyjson_val *arr) {
+ yyjson_arr_iter iter;
+ yyjson_arr_iter_init(arr, &iter);
+ return iter;
+}
+
+yyjson_api_inline bool yyjson_arr_iter_has_next(yyjson_arr_iter *iter) {
+ return iter ? iter->idx < iter->max : false;
+}
+
+yyjson_api_inline yyjson_val *yyjson_arr_iter_next(yyjson_arr_iter *iter) {
+ yyjson_val *val;
+ if (iter && iter->idx < iter->max) {
+ val = iter->cur;
+ iter->cur = unsafe_yyjson_get_next(val);
+ iter->idx++;
+ return val;
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * JSON Object API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline size_t yyjson_obj_size(yyjson_val *obj) {
+ return yyjson_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0;
+}
+
+yyjson_api_inline yyjson_val *yyjson_obj_get(yyjson_val *obj,
+ const char *key) {
+ return yyjson_obj_getn(obj, key, key ? strlen(key) : 0);
+}
+
+yyjson_api_inline yyjson_val *yyjson_obj_getn(yyjson_val *obj,
+ const char *_key,
+ size_t key_len) {
+ if (yyjson_likely(yyjson_is_obj(obj) && _key)) {
+ size_t len = unsafe_yyjson_get_len(obj);
+ yyjson_val *key = unsafe_yyjson_get_first(obj);
+ while (len-- > 0) {
+ if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key + 1;
+ key = unsafe_yyjson_get_next(key + 1);
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * JSON Object Iterator API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_obj_iter_init(yyjson_val *obj,
+ yyjson_obj_iter *iter) {
+ if (yyjson_likely(yyjson_is_obj(obj) && iter)) {
+ iter->idx = 0;
+ iter->max = unsafe_yyjson_get_len(obj);
+ iter->cur = unsafe_yyjson_get_first(obj);
+ iter->obj = obj;
+ return true;
+ }
+ if (iter) memset(iter, 0, sizeof(yyjson_obj_iter));
+ return false;
+}
+
+yyjson_api_inline yyjson_obj_iter yyjson_obj_iter_with(yyjson_val *obj) {
+ yyjson_obj_iter iter;
+ yyjson_obj_iter_init(obj, &iter);
+ return iter;
+}
+
+yyjson_api_inline bool yyjson_obj_iter_has_next(yyjson_obj_iter *iter) {
+ return iter ? iter->idx < iter->max : false;
+}
+
+yyjson_api_inline yyjson_val *yyjson_obj_iter_next(yyjson_obj_iter *iter) {
+ if (iter && iter->idx < iter->max) {
+ yyjson_val *key = iter->cur;
+ iter->idx++;
+ iter->cur = unsafe_yyjson_get_next(key + 1);
+ return key;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_val *yyjson_obj_iter_get_val(yyjson_val *key) {
+ return key ? key + 1 : NULL;
+}
+
+yyjson_api_inline yyjson_val *yyjson_obj_iter_get(yyjson_obj_iter *iter,
+ const char *key) {
+ return yyjson_obj_iter_getn(iter, key, key ? strlen(key) : 0);
+}
+
+yyjson_api_inline yyjson_val *yyjson_obj_iter_getn(yyjson_obj_iter *iter,
+ const char *key,
+ size_t key_len) {
+ if (iter && key) {
+ size_t idx = iter->idx;
+ size_t max = iter->max;
+ yyjson_val *cur = iter->cur;
+ if (yyjson_unlikely(idx == max)) {
+ idx = 0;
+ cur = unsafe_yyjson_get_first(iter->obj);
+ }
+ while (idx++ < max) {
+ yyjson_val *next = unsafe_yyjson_get_next(cur + 1);
+ if (unsafe_yyjson_equals_strn(cur, key, key_len)) {
+ iter->idx = idx;
+ iter->cur = next;
+ return cur + 1;
+ }
+ cur = next;
+ if (idx == iter->max && iter->idx < iter->max) {
+ idx = 0;
+ max = iter->idx;
+ cur = unsafe_yyjson_get_first(iter->obj);
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Structure (Implementation)
+ *============================================================================*/
+
+/**
+ Mutable JSON value, 24 bytes.
+ The 'tag' and 'uni' field is same as immutable value.
+ The 'next' field links all elements inside the container to be a cycle.
+ */
+struct yyjson_mut_val {
+ uint64_t tag; /**< type, subtype and length */
+ yyjson_val_uni uni; /**< payload */
+ yyjson_mut_val *next; /**< the next value in circular linked list */
+};
+
+/**
+ A memory chunk in string memory pool.
+ */
+typedef struct yyjson_str_chunk {
+ struct yyjson_str_chunk *next; /* next chunk linked list */
+ size_t chunk_size; /* chunk size in bytes */
+ /* char str[]; flexible array member */
+} yyjson_str_chunk;
+
+/**
+ A memory pool to hold all strings in a mutable document.
+ */
+typedef struct yyjson_str_pool {
+ char *cur; /* cursor inside current chunk */
+ char *end; /* the end of current chunk */
+ size_t chunk_size; /* chunk size in bytes while creating new chunk */
+ size_t chunk_size_max; /* maximum chunk size in bytes */
+ yyjson_str_chunk *chunks; /* a linked list of chunks, nullable */
+} yyjson_str_pool;
+
+/**
+ A memory chunk in value memory pool.
+ `sizeof(yyjson_val_chunk)` should not larger than `sizeof(yyjson_mut_val)`.
+ */
+typedef struct yyjson_val_chunk {
+ struct yyjson_val_chunk *next; /* next chunk linked list */
+ size_t chunk_size; /* chunk size in bytes */
+ /* char pad[sizeof(yyjson_mut_val) - sizeof(yyjson_val_chunk)]; padding */
+ /* yyjson_mut_val vals[]; flexible array member */
+} yyjson_val_chunk;
+
+/**
+ A memory pool to hold all values in a mutable document.
+ */
+typedef struct yyjson_val_pool {
+ yyjson_mut_val *cur; /* cursor inside current chunk */
+ yyjson_mut_val *end; /* the end of current chunk */
+ size_t chunk_size; /* chunk size in bytes while creating new chunk */
+ size_t chunk_size_max; /* maximum chunk size in bytes */
+ yyjson_val_chunk *chunks; /* a linked list of chunks, nullable */
+} yyjson_val_pool;
+
+struct yyjson_mut_doc {
+ yyjson_mut_val *root; /**< root value of the JSON document, nullable */
+ yyjson_alc alc; /**< a valid allocator, nonnull */
+ yyjson_str_pool str_pool; /**< string memory pool */
+ yyjson_val_pool val_pool; /**< value memory pool */
+};
+
+/* Ensures the capacity to at least equal to the specified byte length. */
+yyjson_api bool unsafe_yyjson_str_pool_grow(yyjson_str_pool *pool,
+ const yyjson_alc *alc,
+ size_t len);
+
+/* Ensures the capacity to at least equal to the specified value count. */
+yyjson_api bool unsafe_yyjson_val_pool_grow(yyjson_val_pool *pool,
+ const yyjson_alc *alc,
+ size_t count);
+
+/* Allocate memory for string. */
+yyjson_api_inline char *unsafe_yyjson_mut_str_alc(yyjson_mut_doc *doc,
+ size_t len) {
+ char *mem;
+ const yyjson_alc *alc = &doc->alc;
+ yyjson_str_pool *pool = &doc->str_pool;
+ if (yyjson_unlikely((size_t)(pool->end - pool->cur) <= len)) {
+ if (yyjson_unlikely(!unsafe_yyjson_str_pool_grow(pool, alc, len + 1))) {
+ return NULL;
+ }
+ }
+ mem = pool->cur;
+ pool->cur = mem + len + 1;
+ return mem;
+}
+
+yyjson_api_inline char *unsafe_yyjson_mut_strncpy(yyjson_mut_doc *doc,
+ const char *str, size_t len) {
+ char *mem = unsafe_yyjson_mut_str_alc(doc, len);
+ if (yyjson_unlikely(!mem)) return NULL;
+ memcpy((void *)mem, (const void *)str, len);
+ mem[len] = '\0';
+ return mem;
+}
+
+yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_val(yyjson_mut_doc *doc,
+ size_t count) {
+ yyjson_mut_val *val;
+ yyjson_alc *alc = &doc->alc;
+ yyjson_val_pool *pool = &doc->val_pool;
+ if (yyjson_unlikely((size_t)(pool->end - pool->cur) < count)) {
+ if (yyjson_unlikely(!unsafe_yyjson_val_pool_grow(pool, alc, count))) {
+ return NULL;
+ }
+ }
+ val = pool->cur;
+ pool->cur += count;
+ return val;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Document API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_root(yyjson_mut_doc *doc) {
+ return doc ? doc->root : NULL;
+}
+
+yyjson_api_inline void yyjson_mut_doc_set_root(yyjson_mut_doc *doc,
+ yyjson_mut_val *root) {
+ if (doc) doc->root = root;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Value Type API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_mut_is_raw(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_raw(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_null(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_null(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_true(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_true(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_false(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_false(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_bool(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_bool(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_uint(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_uint(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_sint(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_sint(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_int(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_int(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_real(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_real(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_num(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_num(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_str(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_str(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_arr(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_arr(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_obj(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_obj(val) : false;
+}
+
+yyjson_api_inline bool yyjson_mut_is_ctn(yyjson_mut_val *val) {
+ return val ? unsafe_yyjson_is_ctn(val) : false;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Value Content API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_type yyjson_mut_get_type(yyjson_mut_val *val) {
+ return yyjson_get_type((yyjson_val *)val);
+}
+
+yyjson_api_inline yyjson_subtype yyjson_mut_get_subtype(yyjson_mut_val *val) {
+ return yyjson_get_subtype((yyjson_val *)val);
+}
+
+yyjson_api_inline uint8_t yyjson_mut_get_tag(yyjson_mut_val *val) {
+ return yyjson_get_tag((yyjson_val *)val);
+}
+
+yyjson_api_inline const char *yyjson_mut_get_type_desc(yyjson_mut_val *val) {
+ return yyjson_get_type_desc((yyjson_val *)val);
+}
+
+yyjson_api_inline const char *yyjson_mut_get_raw(yyjson_mut_val *val) {
+ return yyjson_get_raw((yyjson_val *)val);
+}
+
+yyjson_api_inline bool yyjson_mut_get_bool(yyjson_mut_val *val) {
+ return yyjson_get_bool((yyjson_val *)val);
+}
+
+yyjson_api_inline uint64_t yyjson_mut_get_uint(yyjson_mut_val *val) {
+ return yyjson_get_uint((yyjson_val *)val);
+}
+
+yyjson_api_inline int64_t yyjson_mut_get_sint(yyjson_mut_val *val) {
+ return yyjson_get_sint((yyjson_val *)val);
+}
+
+yyjson_api_inline int yyjson_mut_get_int(yyjson_mut_val *val) {
+ return yyjson_get_int((yyjson_val *)val);
+}
+
+yyjson_api_inline double yyjson_mut_get_real(yyjson_mut_val *val) {
+ return yyjson_get_real((yyjson_val *)val);
+}
+
+yyjson_api_inline double yyjson_mut_get_num(yyjson_mut_val *val) {
+ return yyjson_get_num((yyjson_val *)val);
+}
+
+yyjson_api_inline const char *yyjson_mut_get_str(yyjson_mut_val *val) {
+ return yyjson_get_str((yyjson_val *)val);
+}
+
+yyjson_api_inline size_t yyjson_mut_get_len(yyjson_mut_val *val) {
+ return yyjson_get_len((yyjson_val *)val);
+}
+
+yyjson_api_inline bool yyjson_mut_equals_str(yyjson_mut_val *val,
+ const char *str) {
+ return yyjson_equals_str((yyjson_val *)val, str);
+}
+
+yyjson_api_inline bool yyjson_mut_equals_strn(yyjson_mut_val *val,
+ const char *str, size_t len) {
+ return yyjson_equals_strn((yyjson_val *)val, str, len);
+}
+
+yyjson_api bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs,
+ yyjson_mut_val *rhs);
+
+yyjson_api_inline bool yyjson_mut_equals(yyjson_mut_val *lhs,
+ yyjson_mut_val *rhs) {
+ if (yyjson_unlikely(!lhs || !rhs)) return false;
+ return unsafe_yyjson_mut_equals(lhs, rhs);
+}
+
+yyjson_api_inline bool yyjson_mut_set_raw(yyjson_mut_val *val,
+ const char *raw, size_t len) {
+ if (yyjson_unlikely(!val || !raw)) return false;
+ unsafe_yyjson_set_raw(val, raw, len);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_null(yyjson_mut_val *val) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_null(val);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_bool(yyjson_mut_val *val, bool num) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_bool(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_uint(yyjson_mut_val *val, uint64_t num) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_uint(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_sint(yyjson_mut_val *val, int64_t num) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_sint(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_int(yyjson_mut_val *val, int num) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_sint(val, (int64_t)num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_real(yyjson_mut_val *val, double num) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_real(val, num);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_str(yyjson_mut_val *val,
+ const char *str) {
+ if (yyjson_unlikely(!val || !str)) return false;
+ unsafe_yyjson_set_str(val, str);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_strn(yyjson_mut_val *val,
+ const char *str, size_t len) {
+ if (yyjson_unlikely(!val || !str)) return false;
+ unsafe_yyjson_set_strn(val, str, len);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_arr(yyjson_mut_val *val) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_arr(val, 0);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_set_obj(yyjson_mut_val *val) {
+ if (yyjson_unlikely(!val)) return false;
+ unsafe_yyjson_set_obj(val, 0);
+ return true;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Value Creation API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_raw(yyjson_mut_doc *doc,
+ const char *str) {
+ if (yyjson_likely(str)) return yyjson_mut_rawn(doc, str, strlen(str));
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_rawn(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len) {
+ if (yyjson_likely(doc && str)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW;
+ val->uni.str = str;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_rawcpy(yyjson_mut_doc *doc,
+ const char *str) {
+ if (yyjson_likely(str)) return yyjson_mut_rawncpy(doc, str, strlen(str));
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_rawncpy(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len) {
+ if (yyjson_likely(doc && str)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
+ if (yyjson_likely(val && new_str)) {
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_RAW;
+ val->uni.str = new_str;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_null(yyjson_mut_doc *doc) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_true(yyjson_mut_doc *doc) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_false(yyjson_mut_doc *doc) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_bool(yyjson_mut_doc *doc,
+ bool _val) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ _val = !!_val;
+ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_uint(yyjson_mut_doc *doc,
+ uint64_t num) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ val->uni.u64 = num;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_sint(yyjson_mut_doc *doc,
+ int64_t num) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = num;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_int(yyjson_mut_doc *doc,
+ int64_t num) {
+ return yyjson_mut_sint(doc, num);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_real(yyjson_mut_doc *doc,
+ double num) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ val->uni.f64 = num;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_str(yyjson_mut_doc *doc,
+ const char *str) {
+ if (yyjson_likely(doc && str)) {
+ size_t len = strlen(str);
+ bool noesc = unsafe_yyjson_is_str_noesc(str, len);
+ yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) |
+ (uint64_t)(YYJSON_TYPE_STR | sub);
+ val->uni.str = str;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_strn(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len) {
+ if (yyjson_likely(doc && str)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = str;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_strcpy(yyjson_mut_doc *doc,
+ const char *str) {
+ if (yyjson_likely(doc && str)) {
+ size_t len = strlen(str);
+ bool noesc = unsafe_yyjson_is_str_noesc(str, len);
+ yyjson_subtype sub = noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
+ if (yyjson_likely(val && new_str)) {
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) |
+ (uint64_t)(YYJSON_TYPE_STR | sub);
+ val->uni.str = new_str;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_strncpy(yyjson_mut_doc *doc,
+ const char *str,
+ size_t len) {
+ if (yyjson_likely(doc && str)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ char *new_str = unsafe_yyjson_mut_strncpy(doc, str, len);
+ if (yyjson_likely(val && new_str)) {
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = new_str;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Array API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline size_t yyjson_mut_arr_size(yyjson_mut_val *arr) {
+ return yyjson_mut_is_arr(arr) ? unsafe_yyjson_get_len(arr) : 0;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get(yyjson_mut_val *arr,
+ size_t idx) {
+ if (yyjson_likely(idx < yyjson_mut_arr_size(arr))) {
+ yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr;
+ while (idx-- > 0) val = val->next;
+ return val->next;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_first(
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) {
+ return ((yyjson_mut_val *)arr->uni.ptr)->next;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_get_last(
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(yyjson_mut_arr_size(arr) > 0)) {
+ return ((yyjson_mut_val *)arr->uni.ptr);
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Iterator API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_mut_arr_iter_init(yyjson_mut_val *arr,
+ yyjson_mut_arr_iter *iter) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr) && iter)) {
+ iter->idx = 0;
+ iter->max = unsafe_yyjson_get_len(arr);
+ iter->cur = iter->max ? (yyjson_mut_val *)arr->uni.ptr : NULL;
+ iter->pre = NULL;
+ iter->arr = arr;
+ return true;
+ }
+ if (iter) memset(iter, 0, sizeof(yyjson_mut_arr_iter));
+ return false;
+}
+
+yyjson_api_inline yyjson_mut_arr_iter yyjson_mut_arr_iter_with(
+ yyjson_mut_val *arr) {
+ yyjson_mut_arr_iter iter;
+ yyjson_mut_arr_iter_init(arr, &iter);
+ return iter;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_iter_has_next(yyjson_mut_arr_iter *iter) {
+ return iter ? iter->idx < iter->max : false;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_next(
+ yyjson_mut_arr_iter *iter) {
+ if (iter && iter->idx < iter->max) {
+ yyjson_mut_val *val = iter->cur;
+ iter->pre = val;
+ iter->cur = val->next;
+ iter->idx++;
+ return iter->cur;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_iter_remove(
+ yyjson_mut_arr_iter *iter) {
+ if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) {
+ yyjson_mut_val *prev = iter->pre;
+ yyjson_mut_val *cur = iter->cur;
+ yyjson_mut_val *next = cur->next;
+ if (yyjson_unlikely(iter->idx == iter->max)) iter->arr->uni.ptr = prev;
+ iter->idx--;
+ iter->max--;
+ unsafe_yyjson_set_len(iter->arr, iter->max);
+ prev->next = next;
+ iter->cur = next;
+ return cur;
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Creation API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr(yyjson_mut_doc *doc) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_ARR | YYJSON_SUBTYPE_NONE;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+#define yyjson_mut_arr_with_func(func) \
+ if (yyjson_likely(doc && ((0 < count && count < \
+ (~(size_t)0) / sizeof(yyjson_mut_val) && vals) || count == 0))) { \
+ yyjson_mut_val *arr = unsafe_yyjson_mut_val(doc, 1 + count); \
+ if (yyjson_likely(arr)) { \
+ arr->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_ARR; \
+ if (count > 0) { \
+ size_t i; \
+ for (i = 0; i < count; i++) { \
+ yyjson_mut_val *val = arr + i + 1; \
+ func \
+ val->next = val + 1; \
+ } \
+ arr[count].next = arr + 1; \
+ arr->uni.ptr = arr + count; \
+ } \
+ return arr; \
+ } \
+ } \
+ return NULL
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_bool(
+ yyjson_mut_doc *doc, const bool *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ bool _val = !!vals[i];
+ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)_val << 3);
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint(
+ yyjson_mut_doc *doc, const int64_t *vals, size_t count) {
+ return yyjson_mut_arr_with_sint64(doc, vals, count);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint(
+ yyjson_mut_doc *doc, const uint64_t *vals, size_t count) {
+ return yyjson_mut_arr_with_uint64(doc, vals, count);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_real(
+ yyjson_mut_doc *doc, const double *vals, size_t count) {
+ return yyjson_mut_arr_with_double(doc, vals, count);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint8(
+ yyjson_mut_doc *doc, const int8_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = (int64_t)vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint16(
+ yyjson_mut_doc *doc, const int16_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint32(
+ yyjson_mut_doc *doc, const int32_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_sint64(
+ yyjson_mut_doc *doc, const int64_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint8(
+ yyjson_mut_doc *doc, const uint8_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ val->uni.u64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint16(
+ yyjson_mut_doc *doc, const uint16_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ val->uni.u64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint32(
+ yyjson_mut_doc *doc, const uint32_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ val->uni.u64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_uint64(
+ yyjson_mut_doc *doc, const uint64_t *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ val->uni.u64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_float(
+ yyjson_mut_doc *doc, const float *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ val->uni.f64 = (double)vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_double(
+ yyjson_mut_doc *doc, const double *vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ val->uni.f64 = vals[i];
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_str(
+ yyjson_mut_doc *doc, const char **vals, size_t count) {
+ yyjson_mut_arr_with_func({
+ uint64_t len = (uint64_t)strlen(vals[i]);
+ val->tag = (len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = vals[i];
+ if (yyjson_unlikely(!val->uni.str)) return NULL;
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strn(
+ yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) {
+ if (yyjson_unlikely(count > 0 && !lens)) return NULL;
+ yyjson_mut_arr_with_func({
+ val->tag = ((uint64_t)lens[i] << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = vals[i];
+ if (yyjson_unlikely(!val->uni.str)) return NULL;
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strcpy(
+ yyjson_mut_doc *doc, const char **vals, size_t count) {
+ size_t len;
+ const char *str;
+ yyjson_mut_arr_with_func({
+ str = vals[i];
+ if (!str) return NULL;
+ len = strlen(str);
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len);
+ if (yyjson_unlikely(!val->uni.str)) return NULL;
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_with_strncpy(
+ yyjson_mut_doc *doc, const char **vals, const size_t *lens, size_t count) {
+ size_t len;
+ const char *str;
+ if (yyjson_unlikely(count > 0 && !lens)) return NULL;
+ yyjson_mut_arr_with_func({
+ str = vals[i];
+ len = lens[i];
+ val->tag = ((uint64_t)len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = unsafe_yyjson_mut_strncpy(doc, str, len);
+ if (yyjson_unlikely(!val->uni.str)) return NULL;
+ });
+}
+
+#undef yyjson_mut_arr_with_func
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Modification API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_mut_arr_insert(yyjson_mut_val *arr,
+ yyjson_mut_val *val, size_t idx) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (yyjson_likely(idx <= len)) {
+ unsafe_yyjson_set_len(arr, len + 1);
+ if (len == 0) {
+ val->next = val;
+ arr->uni.ptr = val;
+ } else {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ if (idx == len) {
+ prev->next = val;
+ val->next = next;
+ arr->uni.ptr = val;
+ } else {
+ while (idx-- > 0) {
+ prev = next;
+ next = next->next;
+ }
+ prev->next = val;
+ val->next = next;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_append(yyjson_mut_val *arr,
+ yyjson_mut_val *val) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ unsafe_yyjson_set_len(arr, len + 1);
+ if (len == 0) {
+ val->next = val;
+ } else {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ prev->next = val;
+ val->next = next;
+ }
+ arr->uni.ptr = val;
+ return true;
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_prepend(yyjson_mut_val *arr,
+ yyjson_mut_val *val) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ unsafe_yyjson_set_len(arr, len + 1);
+ if (len == 0) {
+ val->next = val;
+ arr->uni.ptr = val;
+ } else {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ prev->next = val;
+ val->next = next;
+ }
+ return true;
+ }
+ return false;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_replace(yyjson_mut_val *arr,
+ size_t idx,
+ yyjson_mut_val *val) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr) && val)) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (yyjson_likely(idx < len)) {
+ if (yyjson_likely(len > 1)) {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ while (idx-- > 0) {
+ prev = next;
+ next = next->next;
+ }
+ prev->next = val;
+ val->next = next->next;
+ if ((void *)next == arr->uni.ptr) arr->uni.ptr = val;
+ return next;
+ } else {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ val->next = val;
+ arr->uni.ptr = val;
+ return prev;
+ }
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove(yyjson_mut_val *arr,
+ size_t idx) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr))) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (yyjson_likely(idx < len)) {
+ unsafe_yyjson_set_len(arr, len - 1);
+ if (yyjson_likely(len > 1)) {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ while (idx-- > 0) {
+ prev = next;
+ next = next->next;
+ }
+ prev->next = next->next;
+ if ((void *)next == arr->uni.ptr) arr->uni.ptr = prev;
+ return next;
+ } else {
+ return ((yyjson_mut_val *)arr->uni.ptr);
+ }
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_first(
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr))) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (len > 1) {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ prev->next = next->next;
+ unsafe_yyjson_set_len(arr, len - 1);
+ return next;
+ } else if (len == 1) {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ unsafe_yyjson_set_len(arr, 0);
+ return prev;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_remove_last(
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr))) {
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (yyjson_likely(len > 1)) {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ yyjson_mut_val *next = prev->next;
+ unsafe_yyjson_set_len(arr, len - 1);
+ while (--len > 0) prev = prev->next;
+ prev->next = next;
+ next = (yyjson_mut_val *)arr->uni.ptr;
+ arr->uni.ptr = prev;
+ return next;
+ } else if (len == 1) {
+ yyjson_mut_val *prev = ((yyjson_mut_val *)arr->uni.ptr);
+ unsafe_yyjson_set_len(arr, 0);
+ return prev;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_remove_range(yyjson_mut_val *arr,
+ size_t _idx, size_t _len) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *prev, *next;
+ bool tail_removed;
+ size_t len = unsafe_yyjson_get_len(arr);
+ if (yyjson_unlikely(_idx + _len > len)) return false;
+ if (yyjson_unlikely(_len == 0)) return true;
+ unsafe_yyjson_set_len(arr, len - _len);
+ if (yyjson_unlikely(len == _len)) return true;
+ tail_removed = (_idx + _len == len);
+ prev = ((yyjson_mut_val *)arr->uni.ptr);
+ while (_idx-- > 0) prev = prev->next;
+ next = prev->next;
+ while (_len-- > 0) next = next->next;
+ prev->next = next;
+ if (yyjson_unlikely(tail_removed)) arr->uni.ptr = prev;
+ return true;
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_clear(yyjson_mut_val *arr) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr))) {
+ unsafe_yyjson_set_len(arr, 0);
+ return true;
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_rotate(yyjson_mut_val *arr,
+ size_t idx) {
+ if (yyjson_likely(yyjson_mut_is_arr(arr) &&
+ unsafe_yyjson_get_len(arr) > idx)) {
+ yyjson_mut_val *val = (yyjson_mut_val *)arr->uni.ptr;
+ while (idx-- > 0) val = val->next;
+ arr->uni.ptr = (void *)val;
+ return true;
+ }
+ return false;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Array Modification Convenience API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_mut_arr_add_val(yyjson_mut_val *arr,
+ yyjson_mut_val *val) {
+ return yyjson_mut_arr_append(arr, val);
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_null(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_null(doc);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_true(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_true(doc);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_false(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_false(doc);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_bool(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ bool _val) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_bool(doc, _val);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_uint(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ uint64_t num) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_uint(doc, num);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_sint(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ int64_t num) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_sint(doc, num);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_int(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ int64_t num) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_sint(doc, num);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_real(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ double num) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_real(doc, num);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_str(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_str(doc, str);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_strn(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str, size_t len) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_strn(doc, str, len);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_strcpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_strcpy(doc, str);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_arr_add_strncpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr,
+ const char *str, size_t len) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_strncpy(doc, str, len);
+ return yyjson_mut_arr_append(arr, val);
+ }
+ return false;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_arr(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_arr(doc);
+ return yyjson_mut_arr_append(arr, val) ? val : NULL;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_arr_add_obj(yyjson_mut_doc *doc,
+ yyjson_mut_val *arr) {
+ if (yyjson_likely(doc && yyjson_mut_is_arr(arr))) {
+ yyjson_mut_val *val = yyjson_mut_obj(doc);
+ return yyjson_mut_arr_append(arr, val) ? val : NULL;
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Object API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline size_t yyjson_mut_obj_size(yyjson_mut_val *obj) {
+ return yyjson_mut_is_obj(obj) ? unsafe_yyjson_get_len(obj) : 0;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_get(yyjson_mut_val *obj,
+ const char *key) {
+ return yyjson_mut_obj_getn(obj, key, key ? strlen(key) : 0);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_getn(yyjson_mut_val *obj,
+ const char *_key,
+ size_t key_len) {
+ size_t len = yyjson_mut_obj_size(obj);
+ if (yyjson_likely(len && _key)) {
+ yyjson_mut_val *key = ((yyjson_mut_val *)obj->uni.ptr)->next->next;
+ while (len-- > 0) {
+ if (unsafe_yyjson_equals_strn(key, _key, key_len)) return key->next;
+ key = key->next->next;
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Iterator API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline bool yyjson_mut_obj_iter_init(yyjson_mut_val *obj,
+ yyjson_mut_obj_iter *iter) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) && iter)) {
+ iter->idx = 0;
+ iter->max = unsafe_yyjson_get_len(obj);
+ iter->cur = iter->max ? (yyjson_mut_val *)obj->uni.ptr : NULL;
+ iter->pre = NULL;
+ iter->obj = obj;
+ return true;
+ }
+ if (iter) memset(iter, 0, sizeof(yyjson_mut_obj_iter));
+ return false;
+}
+
+yyjson_api_inline yyjson_mut_obj_iter yyjson_mut_obj_iter_with(
+ yyjson_mut_val *obj) {
+ yyjson_mut_obj_iter iter;
+ yyjson_mut_obj_iter_init(obj, &iter);
+ return iter;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_iter_has_next(yyjson_mut_obj_iter *iter) {
+ return iter ? iter->idx < iter->max : false;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_next(
+ yyjson_mut_obj_iter *iter) {
+ if (iter && iter->idx < iter->max) {
+ yyjson_mut_val *key = iter->cur;
+ iter->pre = key;
+ iter->cur = key->next->next;
+ iter->idx++;
+ return iter->cur;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get_val(
+ yyjson_mut_val *key) {
+ return key ? key->next : NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_remove(
+ yyjson_mut_obj_iter *iter) {
+ if (yyjson_likely(iter && 0 < iter->idx && iter->idx <= iter->max)) {
+ yyjson_mut_val *prev = iter->pre;
+ yyjson_mut_val *cur = iter->cur;
+ yyjson_mut_val *next = cur->next->next;
+ if (yyjson_unlikely(iter->idx == iter->max)) iter->obj->uni.ptr = prev;
+ iter->idx--;
+ iter->max--;
+ unsafe_yyjson_set_len(iter->obj, iter->max);
+ prev->next->next = next;
+ iter->cur = prev;
+ return cur->next;
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_get(
+ yyjson_mut_obj_iter *iter, const char *key) {
+ return yyjson_mut_obj_iter_getn(iter, key, key ? strlen(key) : 0);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_iter_getn(
+ yyjson_mut_obj_iter *iter, const char *key, size_t key_len) {
+ if (iter && key) {
+ size_t idx = 0;
+ size_t max = iter->max;
+ yyjson_mut_val *pre, *cur = iter->cur;
+ while (idx++ < max) {
+ pre = cur;
+ cur = cur->next->next;
+ if (unsafe_yyjson_equals_strn(cur, key, key_len)) {
+ iter->idx += idx;
+ if (iter->idx > max) iter->idx -= max + 1;
+ iter->pre = pre;
+ iter->cur = cur;
+ return cur->next;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Creation API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj(yyjson_mut_doc *doc) {
+ if (yyjson_likely(doc)) {
+ yyjson_mut_val *val = unsafe_yyjson_mut_val(doc, 1);
+ if (yyjson_likely(val)) {
+ val->tag = YYJSON_TYPE_OBJ | YYJSON_SUBTYPE_NONE;
+ return val;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_str(yyjson_mut_doc *doc,
+ const char **keys,
+ const char **vals,
+ size_t count) {
+ if (yyjson_likely(doc && ((count > 0 && keys && vals) || (count == 0)))) {
+ yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2);
+ if (yyjson_likely(obj)) {
+ obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ;
+ if (count > 0) {
+ size_t i;
+ for (i = 0; i < count; i++) {
+ yyjson_mut_val *key = obj + (i * 2 + 1);
+ yyjson_mut_val *val = obj + (i * 2 + 2);
+ uint64_t key_len = (uint64_t)strlen(keys[i]);
+ uint64_t val_len = (uint64_t)strlen(vals[i]);
+ key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ key->uni.str = keys[i];
+ val->uni.str = vals[i];
+ key->next = val;
+ val->next = val + 1;
+ }
+ obj[count * 2].next = obj + 1;
+ obj->uni.ptr = obj + (count * 2 - 1);
+ }
+ return obj;
+ }
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_with_kv(yyjson_mut_doc *doc,
+ const char **pairs,
+ size_t count) {
+ if (yyjson_likely(doc && ((count > 0 && pairs) || (count == 0)))) {
+ yyjson_mut_val *obj = unsafe_yyjson_mut_val(doc, 1 + count * 2);
+ if (yyjson_likely(obj)) {
+ obj->tag = ((uint64_t)count << YYJSON_TAG_BIT) | YYJSON_TYPE_OBJ;
+ if (count > 0) {
+ size_t i;
+ for (i = 0; i < count; i++) {
+ yyjson_mut_val *key = obj + (i * 2 + 1);
+ yyjson_mut_val *val = obj + (i * 2 + 2);
+ const char *key_str = pairs[i * 2 + 0];
+ const char *val_str = pairs[i * 2 + 1];
+ uint64_t key_len = (uint64_t)strlen(key_str);
+ uint64_t val_len = (uint64_t)strlen(val_str);
+ key->tag = (key_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->tag = (val_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ key->uni.str = key_str;
+ val->uni.str = val_str;
+ key->next = val;
+ val->next = val + 1;
+ }
+ obj[count * 2].next = obj + 1;
+ obj->uni.ptr = obj + (count * 2 - 1);
+ }
+ return obj;
+ }
+ }
+ return NULL;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Modification API (Implementation)
+ *============================================================================*/
+
+yyjson_api_inline void unsafe_yyjson_mut_obj_add(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val,
+ size_t len) {
+ if (yyjson_likely(len)) {
+ yyjson_mut_val *prev_val = ((yyjson_mut_val *)obj->uni.ptr)->next;
+ yyjson_mut_val *next_key = prev_val->next;
+ prev_val->next = key;
+ val->next = next_key;
+ } else {
+ val->next = key;
+ }
+ key->next = val;
+ obj->uni.ptr = (void *)key;
+ unsafe_yyjson_set_len(obj, len + 1);
+}
+
+yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_obj_remove(
+ yyjson_mut_val *obj, const char *key, size_t key_len) {
+ size_t obj_len = unsafe_yyjson_get_len(obj);
+ if (obj_len) {
+ yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr;
+ yyjson_mut_val *cur_key = pre_key->next->next;
+ yyjson_mut_val *removed_item = NULL;
+ size_t i;
+ for (i = 0; i < obj_len; i++) {
+ if (unsafe_yyjson_equals_strn(cur_key, key, key_len)) {
+ if (!removed_item) removed_item = cur_key->next;
+ cur_key = cur_key->next->next;
+ pre_key->next->next = cur_key;
+ if (i + 1 == obj_len) obj->uni.ptr = pre_key;
+ i--;
+ obj_len--;
+ } else {
+ pre_key = cur_key;
+ cur_key = cur_key->next->next;
+ }
+ }
+ unsafe_yyjson_set_len(obj, obj_len);
+ return removed_item;
+ } else {
+ return NULL;
+ }
+}
+
+yyjson_api_inline bool unsafe_yyjson_mut_obj_replace(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val) {
+ size_t key_len = unsafe_yyjson_get_len(key);
+ size_t obj_len = unsafe_yyjson_get_len(obj);
+ if (obj_len) {
+ yyjson_mut_val *pre_key = (yyjson_mut_val *)obj->uni.ptr;
+ yyjson_mut_val *cur_key = pre_key->next->next;
+ size_t i;
+ for (i = 0; i < obj_len; i++) {
+ if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) {
+ cur_key->next->tag = val->tag;
+ cur_key->next->uni.u64 = val->uni.u64;
+ return true;
+ } else {
+ cur_key = cur_key->next->next;
+ }
+ }
+ }
+ return false;
+}
+
+yyjson_api_inline void unsafe_yyjson_mut_obj_rotate(yyjson_mut_val *obj,
+ size_t idx) {
+ yyjson_mut_val *key = (yyjson_mut_val *)obj->uni.ptr;
+ while (idx-- > 0) key = key->next->next;
+ obj->uni.ptr = (void *)key;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) &&
+ yyjson_mut_is_str(key) && val)) {
+ unsafe_yyjson_mut_obj_add(obj, key, val, unsafe_yyjson_get_len(obj));
+ return true;
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_put(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val) {
+ bool replaced = false;
+ size_t key_len;
+ yyjson_mut_obj_iter iter;
+ yyjson_mut_val *cur_key;
+ if (yyjson_unlikely(!yyjson_mut_is_obj(obj) ||
+ !yyjson_mut_is_str(key))) return false;
+ key_len = unsafe_yyjson_get_len(key);
+ yyjson_mut_obj_iter_init(obj, &iter);
+ while ((cur_key = yyjson_mut_obj_iter_next(&iter)) != 0) {
+ if (unsafe_yyjson_equals_strn(cur_key, key->uni.str, key_len)) {
+ if (!replaced && val) {
+ replaced = true;
+ val->next = cur_key->next->next;
+ cur_key->next = val;
+ } else {
+ yyjson_mut_obj_iter_remove(&iter);
+ }
+ }
+ }
+ if (!replaced && val) unsafe_yyjson_mut_obj_add(obj, key, val, iter.max);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_insert(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val,
+ size_t idx) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) &&
+ yyjson_mut_is_str(key) && val)) {
+ size_t len = unsafe_yyjson_get_len(obj);
+ if (yyjson_likely(len >= idx)) {
+ if (len > idx) {
+ void *ptr = obj->uni.ptr;
+ unsafe_yyjson_mut_obj_rotate(obj, idx);
+ unsafe_yyjson_mut_obj_add(obj, key, val, len);
+ obj->uni.ptr = ptr;
+ } else {
+ unsafe_yyjson_mut_obj_add(obj, key, val, len);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove(yyjson_mut_val *obj,
+ yyjson_mut_val *key) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) && yyjson_mut_is_str(key))) {
+ return unsafe_yyjson_mut_obj_remove(obj, key->uni.str,
+ unsafe_yyjson_get_len(key));
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_key(
+ yyjson_mut_val *obj, const char *key) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) {
+ size_t key_len = strlen(key);
+ return unsafe_yyjson_mut_obj_remove(obj, key, key_len);
+ }
+ return NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_keyn(
+ yyjson_mut_val *obj, const char *key, size_t key_len) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) && key)) {
+ return unsafe_yyjson_mut_obj_remove(obj, key, key_len);
+ }
+ return NULL;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_clear(yyjson_mut_val *obj) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj))) {
+ unsafe_yyjson_set_len(obj, 0);
+ return true;
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_replace(yyjson_mut_val *obj,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) &&
+ yyjson_mut_is_str(key) && val)) {
+ return unsafe_yyjson_mut_obj_replace(obj, key, val);
+ }
+ return false;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj,
+ size_t idx) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) &&
+ unsafe_yyjson_get_len(obj) > idx)) {
+ unsafe_yyjson_mut_obj_rotate(obj, idx);
+ return true;
+ }
+ return false;
+}
+
+
+
+/*==============================================================================
+ * Mutable JSON Object Modification Convenience API (Implementation)
+ *============================================================================*/
+
+#define yyjson_mut_obj_add_func(func) \
+ if (yyjson_likely(doc && yyjson_mut_is_obj(obj) && _key)) { \
+ yyjson_mut_val *key = unsafe_yyjson_mut_val(doc, 2); \
+ if (yyjson_likely(key)) { \
+ size_t len = unsafe_yyjson_get_len(obj); \
+ yyjson_mut_val *val = key + 1; \
+ size_t key_len = strlen(_key); \
+ bool noesc = unsafe_yyjson_is_str_noesc(_key, key_len); \
+ key->tag = YYJSON_TYPE_STR; \
+ key->tag |= noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE; \
+ key->tag |= (uint64_t)strlen(_key) << YYJSON_TAG_BIT; \
+ key->uni.str = _key; \
+ func \
+ unsafe_yyjson_mut_obj_add(obj, key, val, len); \
+ return true; \
+ } \
+ } \
+ return false
+
+yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_NULL | YYJSON_SUBTYPE_NONE;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_TRUE;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_BOOL | YYJSON_SUBTYPE_FALSE;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ bool _val) {
+ yyjson_mut_obj_add_func({
+ _val = !!_val;
+ val->tag = YYJSON_TYPE_BOOL | (uint8_t)((uint8_t)(_val) << 3);
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ uint64_t _val) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_UINT;
+ val->uni.u64 = _val;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ int64_t _val) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = _val;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ int64_t _val) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_SINT;
+ val->uni.i64 = _val;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ double _val) {
+ yyjson_mut_obj_add_func({
+ val->tag = YYJSON_TYPE_NUM | YYJSON_SUBTYPE_REAL;
+ val->uni.f64 = _val;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ const char *_val) {
+ if (yyjson_unlikely(!_val)) return false;
+ yyjson_mut_obj_add_func({
+ size_t val_len = strlen(_val);
+ bool val_noesc = unsafe_yyjson_is_str_noesc(_val, val_len);
+ val->tag = ((uint64_t)strlen(_val) << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->tag |= val_noesc ? YYJSON_SUBTYPE_NOESC : YYJSON_SUBTYPE_NONE;
+ val->uni.str = _val;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ const char *_val,
+ size_t _len) {
+ if (yyjson_unlikely(!_val)) return false;
+ yyjson_mut_obj_add_func({
+ val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ val->uni.str = _val;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ const char *_val) {
+ if (yyjson_unlikely(!_val)) return false;
+ yyjson_mut_obj_add_func({
+ size_t _len = strlen(_val);
+ val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len);
+ if (yyjson_unlikely(!val->uni.str)) return false;
+ val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ });
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ const char *_val,
+ size_t _len) {
+ if (yyjson_unlikely(!_val)) return false;
+ yyjson_mut_obj_add_func({
+ val->uni.str = unsafe_yyjson_mut_strncpy(doc, _val, _len);
+ if (yyjson_unlikely(!val->uni.str)) return false;
+ val->tag = ((uint64_t)_len << YYJSON_TAG_BIT) | YYJSON_TYPE_STR;
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key) {
+ yyjson_mut_val *key = yyjson_mut_str(doc, _key);
+ yyjson_mut_val *val = yyjson_mut_arr(doc);
+ return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key) {
+ yyjson_mut_val *key = yyjson_mut_str(doc, _key);
+ yyjson_mut_val *val = yyjson_mut_obj(doc);
+ return yyjson_mut_obj_add(obj, key, val) ? val : NULL;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *_key,
+ yyjson_mut_val *_val) {
+ if (yyjson_unlikely(!_val)) return false;
+ yyjson_mut_obj_add_func({
+ val = _val;
+ });
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_str(yyjson_mut_val *obj,
+ const char *key) {
+ return yyjson_mut_obj_remove_strn(obj, key, key ? strlen(key) : 0);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_remove_strn(
+ yyjson_mut_val *obj, const char *_key, size_t _len) {
+ if (yyjson_likely(yyjson_mut_is_obj(obj) && _key)) {
+ yyjson_mut_val *key;
+ yyjson_mut_obj_iter iter;
+ yyjson_mut_val *val_removed = NULL;
+ yyjson_mut_obj_iter_init(obj, &iter);
+ while ((key = yyjson_mut_obj_iter_next(&iter)) != NULL) {
+ if (unsafe_yyjson_equals_strn(key, _key, _len)) {
+ if (!val_removed) val_removed = key->next;
+ yyjson_mut_obj_iter_remove(&iter);
+ }
+ }
+ return val_removed;
+ }
+ return NULL;
+}
+
+yyjson_api_inline bool yyjson_mut_obj_rename_key(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ const char *new_key) {
+ if (!key || !new_key) return false;
+ return yyjson_mut_obj_rename_keyn(doc, obj, key, strlen(key),
+ new_key, strlen(new_key));
+}
+
+yyjson_api_inline bool yyjson_mut_obj_rename_keyn(yyjson_mut_doc *doc,
+ yyjson_mut_val *obj,
+ const char *key,
+ size_t len,
+ const char *new_key,
+ size_t new_len) {
+ char *cpy_key = NULL;
+ yyjson_mut_val *old_key;
+ yyjson_mut_obj_iter iter;
+ if (!doc || !obj || !key || !new_key) return false;
+ yyjson_mut_obj_iter_init(obj, &iter);
+ while ((old_key = yyjson_mut_obj_iter_next(&iter))) {
+ if (unsafe_yyjson_equals_strn((void *)old_key, key, len)) {
+ if (!cpy_key) {
+ cpy_key = unsafe_yyjson_mut_strncpy(doc, new_key, new_len);
+ if (!cpy_key) return false;
+ }
+ yyjson_mut_set_strn(old_key, cpy_key, new_len);
+ }
+ }
+ return cpy_key != NULL;
+}
+
+
+
+/*==============================================================================
+ * JSON Pointer API (Implementation)
+ *============================================================================*/
+
+#define yyjson_ptr_set_err(_code, _msg) do { \
+ if (err) { \
+ err->code = YYJSON_PTR_ERR_##_code; \
+ err->msg = _msg; \
+ err->pos = 0; \
+ } \
+} while(false)
+
+/* require: val != NULL, *ptr == '/', len > 0 */
+yyjson_api yyjson_val *unsafe_yyjson_ptr_getx(yyjson_val *val,
+ const char *ptr, size_t len,
+ yyjson_ptr_err *err);
+
+/* require: val != NULL, *ptr == '/', len > 0 */
+yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_getx(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/* require: val/new_val/doc != NULL, *ptr == '/', len > 0 */
+yyjson_api bool unsafe_yyjson_mut_ptr_putx(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc,
+ bool create_parent, bool insert_new,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+/* require: val/err != NULL, *ptr == '/', len > 0 */
+yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_replacex(
+ yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err);
+
+/* require: val/err != NULL, *ptr == '/', len > 0 */
+yyjson_api yyjson_mut_val *unsafe_yyjson_mut_ptr_removex(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err);
+
+yyjson_api_inline yyjson_val *yyjson_doc_ptr_get(yyjson_doc *doc,
+ const char *ptr) {
+ if (yyjson_unlikely(!ptr)) return NULL;
+ return yyjson_doc_ptr_getn(doc, ptr, strlen(ptr));
+}
+
+yyjson_api_inline yyjson_val *yyjson_doc_ptr_getn(yyjson_doc *doc,
+ const char *ptr, size_t len) {
+ return yyjson_doc_ptr_getx(doc, ptr, len, NULL);
+}
+
+yyjson_api_inline yyjson_val *yyjson_doc_ptr_getx(yyjson_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (yyjson_unlikely(!doc || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(!doc->root)) {
+ yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ return doc->root;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_ptr_getx(doc->root, ptr, len, err);
+}
+
+yyjson_api_inline yyjson_val *yyjson_ptr_get(yyjson_val *val,
+ const char *ptr) {
+ if (yyjson_unlikely(!ptr)) return NULL;
+ return yyjson_ptr_getn(val, ptr, strlen(ptr));
+}
+
+yyjson_api_inline yyjson_val *yyjson_ptr_getn(yyjson_val *val,
+ const char *ptr, size_t len) {
+ return yyjson_ptr_getx(val, ptr, len, NULL);
+}
+
+yyjson_api_inline yyjson_val *yyjson_ptr_getx(yyjson_val *val,
+ const char *ptr, size_t len,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (yyjson_unlikely(!val || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ return val;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_ptr_getx(val, ptr, len, err);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_get(yyjson_mut_doc *doc,
+ const char *ptr) {
+ if (!ptr) return NULL;
+ return yyjson_mut_doc_ptr_getn(doc, ptr, strlen(ptr));
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getn(yyjson_mut_doc *doc,
+ const char *ptr,
+ size_t len) {
+ return yyjson_mut_doc_ptr_getx(doc, ptr, len, NULL, NULL);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_getx(yyjson_mut_doc *doc,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!doc || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(!doc->root)) {
+ yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ return doc->root;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_mut_ptr_getx(doc->root, ptr, len, ctx, err);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_get(yyjson_mut_val *val,
+ const char *ptr) {
+ if (!ptr) return NULL;
+ return yyjson_mut_ptr_getn(val, ptr, strlen(ptr));
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getn(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len) {
+ return yyjson_mut_ptr_getx(val, ptr, len, NULL, NULL);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_getx(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!val || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ return val;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_mut_ptr_getx(val, ptr, len, ctx, err);
+}
+
+yyjson_api_inline bool yyjson_mut_doc_ptr_add(yyjson_mut_doc *doc,
+ const char *ptr,
+ yyjson_mut_val *new_val) {
+ if (yyjson_unlikely(!ptr)) return false;
+ return yyjson_mut_doc_ptr_addn(doc, ptr, strlen(ptr), new_val);
+}
+
+yyjson_api_inline bool yyjson_mut_doc_ptr_addn(yyjson_mut_doc *doc,
+ const char *ptr,
+ size_t len,
+ yyjson_mut_val *new_val) {
+ return yyjson_mut_doc_ptr_addx(doc, ptr, len, new_val, true, NULL, NULL);
+}
+
+yyjson_api_inline bool yyjson_mut_doc_ptr_addx(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!doc || !ptr || !new_val)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return false;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ if (doc->root) {
+ yyjson_ptr_set_err(SET_ROOT, "cannot set document's root");
+ return false;
+ } else {
+ doc->root = new_val;
+ return true;
+ }
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return false;
+ }
+ if (yyjson_unlikely(!doc->root && !create_parent)) {
+ yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
+ return false;
+ }
+ if (yyjson_unlikely(!doc->root)) {
+ yyjson_mut_val *root = yyjson_mut_obj(doc);
+ if (yyjson_unlikely(!root)) {
+ yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value");
+ return false;
+ }
+ if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc,
+ create_parent, true, ctx, err)) {
+ doc->root = root;
+ return true;
+ }
+ return false;
+ }
+ return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc,
+ create_parent, true, ctx, err);
+}
+
+yyjson_api_inline bool yyjson_mut_ptr_add(yyjson_mut_val *val,
+ const char *ptr,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc) {
+ if (yyjson_unlikely(!ptr)) return false;
+ return yyjson_mut_ptr_addn(val, ptr, strlen(ptr), new_val, doc);
+}
+
+yyjson_api_inline bool yyjson_mut_ptr_addn(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc) {
+ return yyjson_mut_ptr_addx(val, ptr, len, new_val, doc, true, NULL, NULL);
+}
+
+yyjson_api_inline bool yyjson_mut_ptr_addx(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!val || !ptr || !new_val || !doc)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return false;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ yyjson_ptr_set_err(SET_ROOT, "cannot set root");
+ return false;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return false;
+ }
+ return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val,
+ doc, create_parent, true, ctx, err);
+}
+
+yyjson_api_inline bool yyjson_mut_doc_ptr_set(yyjson_mut_doc *doc,
+ const char *ptr,
+ yyjson_mut_val *new_val) {
+ if (yyjson_unlikely(!ptr)) return false;
+ return yyjson_mut_doc_ptr_setn(doc, ptr, strlen(ptr), new_val);
+}
+
+yyjson_api_inline bool yyjson_mut_doc_ptr_setn(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val) {
+ return yyjson_mut_doc_ptr_setx(doc, ptr, len, new_val, true, NULL, NULL);
+}
+
+yyjson_api_inline bool yyjson_mut_doc_ptr_setx(yyjson_mut_doc *doc,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!doc || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return false;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ if (ctx) ctx->old = doc->root;
+ doc->root = new_val;
+ return true;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return false;
+ }
+ if (!new_val) {
+ if (!doc->root) {
+ yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved");
+ return false;
+ }
+ return !!unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err);
+ }
+ if (yyjson_unlikely(!doc->root && !create_parent)) {
+ yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
+ return false;
+ }
+ if (yyjson_unlikely(!doc->root)) {
+ yyjson_mut_val *root = yyjson_mut_obj(doc);
+ if (yyjson_unlikely(!root)) {
+ yyjson_ptr_set_err(MEMORY_ALLOCATION, "failed to create value");
+ return false;
+ }
+ if (unsafe_yyjson_mut_ptr_putx(root, ptr, len, new_val, doc,
+ create_parent, false, ctx, err)) {
+ doc->root = root;
+ return true;
+ }
+ return false;
+ }
+ return unsafe_yyjson_mut_ptr_putx(doc->root, ptr, len, new_val, doc,
+ create_parent, false, ctx, err);
+}
+
+yyjson_api_inline bool yyjson_mut_ptr_set(yyjson_mut_val *val,
+ const char *ptr,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc) {
+ if (yyjson_unlikely(!ptr)) return false;
+ return yyjson_mut_ptr_setn(val, ptr, strlen(ptr), new_val, doc);
+}
+
+yyjson_api_inline bool yyjson_mut_ptr_setn(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc) {
+ return yyjson_mut_ptr_setx(val, ptr, len, new_val, doc, true, NULL, NULL);
+}
+
+yyjson_api_inline bool yyjson_mut_ptr_setx(yyjson_mut_val *val,
+ const char *ptr, size_t len,
+ yyjson_mut_val *new_val,
+ yyjson_mut_doc *doc,
+ bool create_parent,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!val || !ptr || !doc)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return false;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ yyjson_ptr_set_err(SET_ROOT, "cannot set root");
+ return false;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return false;
+ }
+ if (!new_val) {
+ return !!unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err);
+ }
+ return unsafe_yyjson_mut_ptr_putx(val, ptr, len, new_val, doc,
+ create_parent, false, ctx, err);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replace(
+ yyjson_mut_doc *doc, const char *ptr, yyjson_mut_val *new_val) {
+ if (!ptr) return NULL;
+ return yyjson_mut_doc_ptr_replacen(doc, ptr, strlen(ptr), new_val);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacen(
+ yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val) {
+ return yyjson_mut_doc_ptr_replacex(doc, ptr, len, new_val, NULL, NULL);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_replacex(
+ yyjson_mut_doc *doc, const char *ptr, size_t len, yyjson_mut_val *new_val,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
+
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!doc || !ptr || !new_val)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ yyjson_mut_val *root = doc->root;
+ if (yyjson_unlikely(!root)) {
+ yyjson_ptr_set_err(RESOLVE, "JSON pointer cannot be resolved");
+ return NULL;
+ }
+ if (ctx) ctx->old = root;
+ doc->root = new_val;
+ return root;
+ }
+ if (yyjson_unlikely(!doc->root)) {
+ yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_mut_ptr_replacex(doc->root, ptr, len, new_val,
+ ctx, err);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replace(
+ yyjson_mut_val *val, const char *ptr, yyjson_mut_val *new_val) {
+ if (!ptr) return NULL;
+ return yyjson_mut_ptr_replacen(val, ptr, strlen(ptr), new_val);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacen(
+ yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val) {
+ return yyjson_mut_ptr_replacex(val, ptr, len, new_val, NULL, NULL);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_replacex(
+ yyjson_mut_val *val, const char *ptr, size_t len, yyjson_mut_val *new_val,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
+
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!val || !ptr || !new_val)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ yyjson_ptr_set_err(SET_ROOT, "cannot set root");
+ return NULL;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_mut_ptr_replacex(val, ptr, len, new_val, ctx, err);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_remove(
+ yyjson_mut_doc *doc, const char *ptr) {
+ if (!ptr) return NULL;
+ return yyjson_mut_doc_ptr_removen(doc, ptr, strlen(ptr));
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removen(
+ yyjson_mut_doc *doc, const char *ptr, size_t len) {
+ return yyjson_mut_doc_ptr_removex(doc, ptr, len, NULL, NULL);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_ptr_removex(
+ yyjson_mut_doc *doc, const char *ptr, size_t len,
+ yyjson_ptr_ctx *ctx, yyjson_ptr_err *err) {
+
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!doc || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(!doc->root)) {
+ yyjson_ptr_set_err(NULL_ROOT, "document's root is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ yyjson_mut_val *root = doc->root;
+ if (ctx) ctx->old = root;
+ doc->root = NULL;
+ return root;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_mut_ptr_removex(doc->root, ptr, len, ctx, err);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_remove(yyjson_mut_val *val,
+ const char *ptr) {
+ if (!ptr) return NULL;
+ return yyjson_mut_ptr_removen(val, ptr, strlen(ptr));
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removen(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len) {
+ return yyjson_mut_ptr_removex(val, ptr, len, NULL, NULL);
+}
+
+yyjson_api_inline yyjson_mut_val *yyjson_mut_ptr_removex(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len,
+ yyjson_ptr_ctx *ctx,
+ yyjson_ptr_err *err) {
+ yyjson_ptr_set_err(NONE, NULL);
+ if (ctx) memset(ctx, 0, sizeof(*ctx));
+
+ if (yyjson_unlikely(!val || !ptr)) {
+ yyjson_ptr_set_err(PARAMETER, "input parameter is NULL");
+ return NULL;
+ }
+ if (yyjson_unlikely(len == 0)) {
+ yyjson_ptr_set_err(SET_ROOT, "cannot set root");
+ return NULL;
+ }
+ if (yyjson_unlikely(*ptr != '/')) {
+ yyjson_ptr_set_err(SYNTAX, "no prefix '/'");
+ return NULL;
+ }
+ return unsafe_yyjson_mut_ptr_removex(val, ptr, len, ctx, err);
+}
+
+yyjson_api_inline bool yyjson_ptr_ctx_append(yyjson_ptr_ctx *ctx,
+ yyjson_mut_val *key,
+ yyjson_mut_val *val) {
+ yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val;
+ if (!ctx || !ctx->ctn || !val) return false;
+ ctn = ctx->ctn;
+
+ if (yyjson_mut_is_obj(ctn)) {
+ if (!key) return false;
+ key->next = val;
+ pre_key = ctx->pre;
+ if (unsafe_yyjson_get_len(ctn) == 0) {
+ val->next = key;
+ ctn->uni.ptr = key;
+ ctx->pre = key;
+ } else if (!pre_key) {
+ pre_key = (yyjson_mut_val *)ctn->uni.ptr;
+ pre_val = pre_key->next;
+ val->next = pre_val->next;
+ pre_val->next = key;
+ ctn->uni.ptr = key;
+ ctx->pre = pre_key;
+ } else {
+ cur_key = pre_key->next->next;
+ cur_val = cur_key->next;
+ val->next = cur_val->next;
+ cur_val->next = key;
+ if (ctn->uni.ptr == cur_key) ctn->uni.ptr = key;
+ ctx->pre = cur_key;
+ }
+ } else {
+ pre_val = ctx->pre;
+ if (unsafe_yyjson_get_len(ctn) == 0) {
+ val->next = val;
+ ctn->uni.ptr = val;
+ ctx->pre = val;
+ } else if (!pre_val) {
+ pre_val = (yyjson_mut_val *)ctn->uni.ptr;
+ val->next = pre_val->next;
+ pre_val->next = val;
+ ctn->uni.ptr = val;
+ ctx->pre = pre_val;
+ } else {
+ cur_val = pre_val->next;
+ val->next = cur_val->next;
+ cur_val->next = val;
+ if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val;
+ ctx->pre = cur_val;
+ }
+ }
+ unsafe_yyjson_inc_len(ctn);
+ return true;
+}
+
+yyjson_api_inline bool yyjson_ptr_ctx_replace(yyjson_ptr_ctx *ctx,
+ yyjson_mut_val *val) {
+ yyjson_mut_val *ctn, *pre_key, *cur_key, *pre_val, *cur_val;
+ if (!ctx || !ctx->ctn || !ctx->pre || !val) return false;
+ ctn = ctx->ctn;
+ if (yyjson_mut_is_obj(ctn)) {
+ pre_key = ctx->pre;
+ pre_val = pre_key->next;
+ cur_key = pre_val->next;
+ cur_val = cur_key->next;
+ /* replace current value */
+ cur_key->next = val;
+ val->next = cur_val->next;
+ ctx->old = cur_val;
+ } else {
+ pre_val = ctx->pre;
+ cur_val = pre_val->next;
+ /* replace current value */
+ if (pre_val != cur_val) {
+ val->next = cur_val->next;
+ pre_val->next = val;
+ if (ctn->uni.ptr == cur_val) ctn->uni.ptr = val;
+ } else {
+ val->next = val;
+ ctn->uni.ptr = val;
+ ctx->pre = val;
+ }
+ ctx->old = cur_val;
+ }
+ return true;
+}
+
+yyjson_api_inline bool yyjson_ptr_ctx_remove(yyjson_ptr_ctx *ctx) {
+ yyjson_mut_val *ctn, *pre_key, *pre_val, *cur_key, *cur_val;
+ size_t len;
+ if (!ctx || !ctx->ctn || !ctx->pre) return false;
+ ctn = ctx->ctn;
+ if (yyjson_mut_is_obj(ctn)) {
+ pre_key = ctx->pre;
+ pre_val = pre_key->next;
+ cur_key = pre_val->next;
+ cur_val = cur_key->next;
+ /* remove current key-value */
+ pre_val->next = cur_val->next;
+ if (ctn->uni.ptr == cur_key) ctn->uni.ptr = pre_key;
+ ctx->pre = NULL;
+ ctx->old = cur_val;
+ } else {
+ pre_val = ctx->pre;
+ cur_val = pre_val->next;
+ /* remove current key-value */
+ pre_val->next = cur_val->next;
+ if (ctn->uni.ptr == cur_val) ctn->uni.ptr = pre_val;
+ ctx->pre = NULL;
+ ctx->old = cur_val;
+ }
+ len = unsafe_yyjson_get_len(ctn) - 1;
+ if (len == 0) ctn->uni.ptr = NULL;
+ unsafe_yyjson_set_len(ctn, len);
+ return true;
+}
+
+#undef yyjson_ptr_set_err
+
+
+
+/*==============================================================================
+ * JSON Value at Pointer API (Implementation)
+ *============================================================================*/
+
+/**
+ Set provided `value` if the JSON Pointer (RFC 6901) exists and is type bool.
+ Returns true if value at `ptr` exists and is the correct type, otherwise false.
+ */
+yyjson_api_inline bool yyjson_ptr_get_bool(
+ yyjson_val *root, const char *ptr, bool *value) {
+ yyjson_val *val = yyjson_ptr_get(root, ptr);
+ if (value && yyjson_is_bool(val)) {
+ *value = unsafe_yyjson_get_bool(val);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
+ that fits in `uint64_t`. Returns true if successful, otherwise false.
+ */
+yyjson_api_inline bool yyjson_ptr_get_uint(
+ yyjson_val *root, const char *ptr, uint64_t *value) {
+ yyjson_val *val = yyjson_ptr_get(root, ptr);
+ if (value && val) {
+ uint64_t ret = val->uni.u64;
+ if (unsafe_yyjson_is_uint(val) ||
+ (unsafe_yyjson_is_sint(val) && !(ret >> 63))) {
+ *value = ret;
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ Set provided `value` if the JSON Pointer (RFC 6901) exists and is an integer
+ that fits in `int64_t`. Returns true if successful, otherwise false.
+ */
+yyjson_api_inline bool yyjson_ptr_get_sint(
+ yyjson_val *root, const char *ptr, int64_t *value) {
+ yyjson_val *val = yyjson_ptr_get(root, ptr);
+ if (value && val) {
+ int64_t ret = val->uni.i64;
+ if (unsafe_yyjson_is_sint(val) ||
+ (unsafe_yyjson_is_uint(val) && ret >= 0)) {
+ *value = ret;
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ Set provided `value` if the JSON Pointer (RFC 6901) exists and is type real.
+ Returns true if value at `ptr` exists and is the correct type, otherwise false.
+ */
+yyjson_api_inline bool yyjson_ptr_get_real(
+ yyjson_val *root, const char *ptr, double *value) {
+ yyjson_val *val = yyjson_ptr_get(root, ptr);
+ if (value && yyjson_is_real(val)) {
+ *value = unsafe_yyjson_get_real(val);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ Set provided `value` if the JSON Pointer (RFC 6901) exists and is type sint,
+ uint or real.
+ Returns true if value at `ptr` exists and is the correct type, otherwise false.
+ */
+yyjson_api_inline bool yyjson_ptr_get_num(
+ yyjson_val *root, const char *ptr, double *value) {
+ yyjson_val *val = yyjson_ptr_get(root, ptr);
+ if (value && yyjson_is_num(val)) {
+ *value = unsafe_yyjson_get_num(val);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ Set provided `value` if the JSON Pointer (RFC 6901) exists and is type string.
+ Returns true if value at `ptr` exists and is the correct type, otherwise false.
+ */
+yyjson_api_inline bool yyjson_ptr_get_str(
+ yyjson_val *root, const char *ptr, const char **value) {
+ yyjson_val *val = yyjson_ptr_get(root, ptr);
+ if (value && yyjson_is_str(val)) {
+ *value = unsafe_yyjson_get_str(val);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+
+/*==============================================================================
+ * Deprecated
+ *============================================================================*/
+
+/** @deprecated renamed to `yyjson_doc_ptr_get` */
+yyjson_deprecated("renamed to yyjson_doc_ptr_get")
+yyjson_api_inline yyjson_val *yyjson_doc_get_pointer(yyjson_doc *doc,
+ const char *ptr) {
+ return yyjson_doc_ptr_get(doc, ptr);
+}
+
+/** @deprecated renamed to `yyjson_doc_ptr_getn` */
+yyjson_deprecated("renamed to yyjson_doc_ptr_getn")
+yyjson_api_inline yyjson_val *yyjson_doc_get_pointern(yyjson_doc *doc,
+ const char *ptr,
+ size_t len) {
+ return yyjson_doc_ptr_getn(doc, ptr, len);
+}
+
+/** @deprecated renamed to `yyjson_mut_doc_ptr_get` */
+yyjson_deprecated("renamed to yyjson_mut_doc_ptr_get")
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointer(
+ yyjson_mut_doc *doc, const char *ptr) {
+ return yyjson_mut_doc_ptr_get(doc, ptr);
+}
+
+/** @deprecated renamed to `yyjson_mut_doc_ptr_getn` */
+yyjson_deprecated("renamed to yyjson_mut_doc_ptr_getn")
+yyjson_api_inline yyjson_mut_val *yyjson_mut_doc_get_pointern(
+ yyjson_mut_doc *doc, const char *ptr, size_t len) {
+ return yyjson_mut_doc_ptr_getn(doc, ptr, len);
+}
+
+/** @deprecated renamed to `yyjson_ptr_get` */
+yyjson_deprecated("renamed to yyjson_ptr_get")
+yyjson_api_inline yyjson_val *yyjson_get_pointer(yyjson_val *val,
+ const char *ptr) {
+ return yyjson_ptr_get(val, ptr);
+}
+
+/** @deprecated renamed to `yyjson_ptr_getn` */
+yyjson_deprecated("renamed to yyjson_ptr_getn")
+yyjson_api_inline yyjson_val *yyjson_get_pointern(yyjson_val *val,
+ const char *ptr,
+ size_t len) {
+ return yyjson_ptr_getn(val, ptr, len);
+}
+
+/** @deprecated renamed to `yyjson_mut_ptr_get` */
+yyjson_deprecated("renamed to yyjson_mut_ptr_get")
+yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointer(yyjson_mut_val *val,
+ const char *ptr) {
+ return yyjson_mut_ptr_get(val, ptr);
+}
+
+/** @deprecated renamed to `yyjson_mut_ptr_getn` */
+yyjson_deprecated("renamed to yyjson_mut_ptr_getn")
+yyjson_api_inline yyjson_mut_val *yyjson_mut_get_pointern(yyjson_mut_val *val,
+ const char *ptr,
+ size_t len) {
+ return yyjson_mut_ptr_getn(val, ptr, len);
+}
+
+/** @deprecated renamed to `yyjson_mut_ptr_getn` */
+yyjson_deprecated("renamed to unsafe_yyjson_ptr_getn")
+yyjson_api_inline yyjson_val *unsafe_yyjson_get_pointer(yyjson_val *val,
+ const char *ptr,
+ size_t len) {
+ yyjson_ptr_err err;
+ return unsafe_yyjson_ptr_getx(val, ptr, len, &err);
+}
+
+/** @deprecated renamed to `unsafe_yyjson_mut_ptr_getx` */
+yyjson_deprecated("renamed to unsafe_yyjson_mut_ptr_getx")
+yyjson_api_inline yyjson_mut_val *unsafe_yyjson_mut_get_pointer(
+ yyjson_mut_val *val, const char *ptr, size_t len) {
+ yyjson_ptr_err err;
+ return unsafe_yyjson_mut_ptr_getx(val, ptr, len, NULL, &err);
+}
+
+
+
+/*==============================================================================
+ * Compiler Hint End
+ *============================================================================*/
+
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#elif defined(__GNUC__)
+# if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+# pragma GCC diagnostic pop
+# endif
+#elif defined(_MSC_VER)
+# pragma warning(pop)
+#endif /* warning suppress end */
+
+#ifdef __cplusplus
+}
+#endif /* extern "C" end */
+
+#endif /* YYJSON_H */